(김유선) 중고거래 사이트를 SPA로 만들기 10일차 - 다양한 기능

2024. 4. 18. 17:44프로젝트 일지

자 드디어 로그인 후 변화는 아래의 두 가지가 남았다.

 

로그인 후 변화해야 하는 것(3)

3. 채팅 기능이 동작할 것 => '채팅'에 필요한 데이터는 내 정보, 주고받은 채팅 내용

 

<소켓 통신 배우고 할 것임 ㅜㅜ>

 

로그인 후 변화해야 하는 것(5)

5. 내 상점 버튼이 동작할 것 => '내상점'에 필요한 데이터는 내 정보, 내가 올린 물건들, 내가 찜한 물건들 리스트

 

<이건 마지막에 하는 게 편할 듯>

 

그 외에 해야 할 것들

많이 남지는 않은 것 같다.

 

1. 누구나 상품 하나를 누르면 상품 상세페이지로 이동한다(물론 spa로 구현).

2. 상품 상세 페이지에서 판매자, 제목, 내용, 가격을 보고 채팅을 걸 수 있고, 찜을 할 수 있다(홈으로 돌아가는 버튼도).

3. 검색 기능을 통해 내가 원하는 상품을 찾을 수 있다.

4. (시간 남으면) 후기 기능 : 한 계정당 한 상대에게는 한 개의 후기만 남길 수 있음

 

상세 페이지 디자인

이렇게 막상 만들어보니까 닉네임이 하나 있으면 좋을 것 같아 유저에게 닉네임 데이터를 추가해주겠다. 

 

완성된 회원가입 html 코드

$('#register_submit').click(function(){ // 가입버튼 클릭하면 (회원가입 기능)
                if($('#register_id').val()!='' && $('#register_pw').val()!='' && $('#register_name').val()!=''){ // (1) 아이디랑 비번, 닉넴 셋 다 공백이 아니면
                    if($('#register_id').val().length>=8 && $('#register_pw').val().length>=8 && $('#register_id').val().length<=10 && $('#register_pw').val().length<=10){ // (2) 아이디랑 비번 둘다 8자~10자이면
                        $.post('/register',{ // (1),(2) 조건문 모두 부합하면 register로 post 요청 보냄
                            nickname : $('#register_name').val(),
                            username : $('#register_id').val(),
                            password : $('#register_pw').val(),
                        })
                        .done(function(data){ // 제출 후 서버에서 닉네임 중복, 아이디 중복 확인해줌
                            alert(data) // 여기서 데이터는 서버쪽 코드에 있는 응답.json 값임
                            $('.login_bg').css('display','none')
                            $('.login_container').css('display','none') // 띄운 창들 사라지게 함
                        })
                    }
                    else{alert('아이디와 비밀번호는 각각 8~10자리로 입력해주세요.')} // (2) 조건문 틀렸을시 실행코드
                }
                else{alert('아이디 혹은 비밀번호를 입력하지 않았습니다.')} // (1) 조건문 틀렸을시 실행코드
            })

 

회원가입 서버 코드

app.post('/register', async(요청, 응답) => { // 가입요청 들어오면 서버에서 닉네임 중복, 아이디 중복 확인해줌
  if(await db.collection('user').findOne({nickname : 요청.body.nickname})!=null){ // 닉네임으로 찾아서 이미 있으면
    응답.json('이미 존재하는 닉네임입니다. 다른 닉네임을 사용해주세요.') // 응답으로 제이슨 데이터를 보내줌
  }
  else{ // 닉네임 중복 안 뜨면
    if(await db.collection('user').findOne({username : 요청.body.username})!=null){ // 아이디 있는지 검사해서 있으면
      응답.json('동일한 아이디를 이미 사용중입니다. 다른 아이디를 사용해주세요.') // 응답으로 제이슨 데이터를 보내줌
    }
    else{ // 닉네임 아이디 중복 없으면
      let 해시 = await bcrypt.hash(요청.body.password, 10)
      await db.collection('user').insertOne({ // 계정 하나 만들어주고
        nickname : 요청.body.nickname,
        username : 요청.body.username,
        password : 해시,
      })
      응답.json(`나다장터에 오신 걸 환영합니다. 가입하신 아이디로 로그인해주세요!`) // 응답 보냄
    }
  }
})

 

로그인 화면은 어차피 닉네임 안 받아서 수정 안해도 될 듯

 

필요한 데이터 : 상품 가격, 상품 이름, 판매자아이디, 판매자닉네임, 상품 내용, 상점 리뷰 개수(아직은 안 만듦)

 

erd

erd 라는 게 있길래 나도 한번 해봐야 할 것 같아서 대충 작성해봤다. 사실 erd는 관계형 데이터베이스를 위한 거지만 몽고디비도 어쨋거나 하나씩은 연관성이 있어야 이리저리 꺼내면서 다닐 수 있기 때문이다.

이렇게 한번 작성해보니까 products에 user라고 되어있는 게 혼동을 일으킬 것 같았다. 그래서 이름을 writerid로 수정해줬다.

(채팅 기능도 만들면 chat 포럼도 만들어야 한다.)

 

자 그럼 상세 페이지를 다시 진행해보겠다.

 

해결한 오류

firstdata.products.forEach(function(a,i){
                        console.log(firstdata.products[i]._id==$(this).data("productid"))
                        // if(firstdata.products[i]._id.includes($(this).data("productid"))){
                        //     console.log(firstdata.products[i])
                        // }
 })
console.log(firstdata.products[1]._id.includes($(this).data("productid")))

위와 같은 코드에서 아래의 콘솔은 true가 리턴되는데 반복문에선 true가 하나도 나오지 않는다.

제이쿼리 문법이 안맞나 싶어서

console.log(firstdata.products.eq(i)._id==$(this).data("productid"))

 

이렇게 작성해봤는데도 해결되지 않았다.

 

https://hamait.tistory.com/244 요걸 참고해보니, 제이쿼리 언어를 써서 그런 것 같다.

 

firstdata.products.forEach(function(a,i){
                        console.log(firstdata.products[1]._id)
                        console.log($(this).data("productid"))
})

이렇게 작성했더니

아무리 다른 것들을 클릭해도 같은 아이디만 나오는 걸 보니

for each 안에 있는 console.log($(this).data("productid"))가 문제인 것 같다. 

반복문 밖으로 빼면 잘만 되는데!

let item = $(this).data("productid")

그래서 변수 안에 넣어줬다.

firstdata.products.forEach(function(a,i){
              console.log(item)
})

그리고 변수 안에서 콘솔을 해주니 잘 나온다 ㅎ

변수에 넣으면서 속성이 변하는 걸지도 모르겠다. 이건 좀 더 공부해봐야 할 듯

 

else{ // 상품 누르면
                    let click_productid = $(this).data("productid")
                    firstdata.products.forEach(function(a,i){
                        if(firstdata.products[i]._id==click_productid){ // 아이템 누른 거랑 상품 중 하나랑 같은 애가 잇으면
                            console.log(firstdata.products[i]) // 걔 콘솔해줌
                        }
                    })
 
}

핫하 내가 해냄!!

 

상품 하나씩 누를 때마다 상품에 대한 정보들 좔좔 나온다. ><

서버 비용도 아끼고 데이터 비용도 아끼고 나 좀 천재인 듯?!

 

이제 데이터는 뽑을 수 있게 되었으니 그 데이터로 꾸밀 화면을 퍼블리싱해보자~!

 

 

https://velog.io/@lively_siwon/CSS-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%82%AC%EC%9D%B4%EC%A6%88-%EB%A7%9E%EC%B6%94%EA%B8%B0-object-fit

 

https://inpa.tistory.com/entry/CSS-%F0%9F%93%9A-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%82%AC%EC%9D%B4%EC%A6%88-%EB%B9%84%EC%9C%A8-%EB%A7%9E%EC%B6%94%EB%8A%94-3%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95-object-fit-background-size-position

 

🌟 이미지 사이즈 비율 맞추는 3가지 방법 (object-fit / background-size / position)

프론트를 작업할때, 컨테이너의 크기는 고정되어 있는데, 해당 컨테이너 안에 들어갈 이미지의 크기는 다양한 경우가 있다. 예를들어 이미지를 확대/축소 하거나 특정 비율로 나타나게 하기위

inpa.tistory.com

이거 백그라운드 포지션 아주 유익하다.

 

일단 이정도 디자인해봤다.

디자인했으니 이제 데이터 바인딩을 하자

 

아니 변수 안에 넣어서 해결된 줄 알았는데 그게 아니었다.

//////////////////////////////////// 로그인 한 유저 화면 //////////////////////////////////

            if(firstdata.user==undefined){
                $('.title_btns').html(`
                <div class="margin_top loginbtn">채팅</div>
                <div class="loginbtn">로그인 / 회원가입</div>
                <div class="loginbtn">내 상점</div>
                <div class="loginbtn">내 물건 팔기</div>`)
                firstdata.products.forEach(function(a,i){
                    $('.products').append(`
                    <div class="products_container" data-productid="${firstdata.products[i]._id}"> <===== 여기에
                        <img class="products_img" src=${firstdata.products[i].img}>
                        <p class="products_title">${firstdata.products[i].title}</p>
                        <div class="products_boxing">
                            <p class="products_price">${firstdata.products[i].price}</p>
                            <img class="heart_fake" src="./img/heart-empty.png" alt="">
                            </div>
                    </div>
                    `)
                })
            }

 

저기 화살표 친 부분에

data-productid="${firstdata.products[i]._id}

를 넣지 않았던 거임...

 

그래서 로그인 하면 못 가져왔던 거였음 ㅜㅜ

 

이제 완전 해결된 것 같다.

 

https://www.fococlipping.com/kr여긴 내가 자주 쓰는 사이트인데 참 좋다.

 

무료 배경 제거: 배경 제거 이미지 배경 제거 3초 안에|FocoClipping

FocoClipping 백그라운드 제거 이미지 배경 제거 과사 그리고 배경 지우기 3초 만에 온라인.

www.fococlipping.com

 

드디어 상세보기 끝

뒤로가기는 동작하는데 채팅하기는 동작하지 않아서 채팅 기능은 집 가서 만들어야겠음