좋아요, 장바구니 기능

유수민·2022년 7월 11일
0

FoodMall 프로젝트

목록 보기
8/14

상품목록의 중심이 되는 기능들에 대해 설명해보려고 한다.

사실 이전까지는 내가 Spring Boot를 이론으로만 접하여 제대로 이해가 안갔었다. 하지만 이 기능들을 만들면서 처음으로 Spring Boot가 이런것이구나 라는 것을 깨닫게 해주었다. ajax도 같이 써야만 했는데, 솔직히 '내가 기능을 구현할 수 있을까.. 안될 수도 있겠다..' 하면서 거의 2주내내 절망에 갇힌상태로 좋아요 기능 하나만 붙들고 있었다. 그때 당시에는 정말 못만들줄 알았다ㅎㅎ 근데 이 2주동안의 나와의 싸움이, 지나고 보니 이후의 다른 기능들을 만드는데 덕분에 수월하게 만들어줬다.

좋아요 기능과 장바구니 기능은 아이콘 이미지만 다를뿐 기능을 만들어낸 방법은 똑같다. 따라서 좋아요 기능만을 설명하도록 하겠다. 다만 두 기능에 한가지 차이점이 있는데 그것은 마지막에 설명을 덧붙이겠다.

📌유저의 사용패턴

'좋아요'기능을 사용하기 위한 유저의 사용패턴을 예상해보면,

1) 상품목록에서 '어? 이 상품 좋아요 해놓아야지'하면서 하트 아이콘을 클릭한다.

2) 클릭하니 현재 로그인이 되지 않았다면서 로그인 화면으로 전환된다.

3) 로그인 후 다시 원래 있던 상품목록으로 돌아간다.

4) 상품의 하트 아이콘을 클릭한다.

5) 꽉찬 하트로 아이콘이 변경된다.

정말 이 간단한 과정이 프로젝트 상에서는 아주 많은 것을 알아야 하며, 판단되어야 한다.


  1. 유저가 어떤 상품의 하트를 클릭하면 그 데이터를 보내야한다.

  2. 유저의 로그인 여부를 알고 있어야 한다. 또한, 이 정보를 바탕으로 유저가 클릭시 로그인 페이지로 전환해야 할지, 원래 있던 페이지 그대로 있게 할지 판단되어야 한다.

  3. 유저가 로그인 한 상태에서 클릭한 상품의 하트가 이전에 좋아요 클릭을 했다면 꽉찬 이미지로 좋아요 클릭을 안했다면 빈 하트 이미지로 보여줘야 한다.

  4. 하트를 클릭한 후 한번 더 클릭하면 꽉찬 하트에서 빈 하트로 이미지 전환이 되어야 한다.

  5. 디비 내에서도 좋아요 데이터에 대한 데이터가 기록되어야 한다.


로그인 기능과 결합해야 해서 더욱 어려웠다. 이제 차근차근 그 흐름을 따르면서 기능을 설명해보고자 한다.

📖1. 유저가 어떤 상품의 하트를 클릭

(1) 유저가 하트 아이콘을 클릭하는 순간 클릭한 상품의 Id 데이터와 함께 서버에 요청한다.

(2) baseController 에서 요청받은 url(⇒ '/heart')이 mapping이 되어 데이터(goodId)를 받게 된다.

📖2. 유저의 로그인 유무 판단.

📖3. 좋아요 기능 구현

📚1) Likes 테이블 만들기

디비에 '좋아요' 기능을 위한 테이블을 만들기 위해 아래 그림처럼 도메인을 만들어주었다.

📚2) Repository, Service,Controller

현재 컨트롤러에서는 userId와 productId의 데이터를 알고 있다. 즉, 누가 어떤 상품의 좋아요를 눌렀는지 알고 있다는 말이다.

디비의 likes 테이블에는 컬럼이 likeId, userId, productId가 존재 한다. 여기서 userId, productId라는 두가지 정보를 이미 알고 있기 때문에 이것을 이용하여 likeId를 알수 있다. → repository의 역활

Optional

null이 올 수 있는 값을 감싸는 Wrapper 클래스. 값이 존재할 수도, 존재하지 않을 수도 있는 값을 포장한 객체이다.

이제 Service에서는 가져온 Optional를 이용하여 해당 userId와 goodId를 가진 Likes테이블이 존재하는지의 유무를 판단해야한다. 즉, 존재한다면 이전에 사용자가 좋아요를 클릭한 상품이고, 존재하지 않는다면 이전에 사용자가 해당상품의 좋아요를 클릭하지 않았다는 것을 의미한다. 객체가 존재하는지의 여부는 isPresent 메서드를 활용한다.

(1) 객체가 존재했을 경우 (= 이전에 사용자가 좋아요를 클릭한 경우)

먼저 객체가 존재했을 경우의 코드를 보면 유저가 이전에 좋아요를 눌렀는데 다시 눌렀다는 것은 해당 상품의 좋아요 클릭한 것을 취소하겠다는 의미기 때문에

1.해당 상품의 좋아요수를 -1한 값으로 heartNumber를 재설정하여
2.product 테이블을 저장한다.
3.Like테이블에서도 해당 LikeId의 row를 삭제한다.
4.그리고 그 반환 값을 false로 한다.

(2) like 객체가 존재하지 않았을 경우(이전에 사용자가 해당상품의 좋아요를 클릭하지 않았다)

1.해당 상품의 좋아요수를 +1한 값으로 heartNumber를 재설정하여
2.product 테이블을 저장한다.
3.Like테이블에서는 새롭게 row를 만들어준다.
4.그리고 그 반환 값을 true로 한다.

지금보니 product를 두번 호출하였다(파랑색) : 한번만 불렀어도 되었었다. 아쉬운 점이다

반환값을 정리하자면, 이전에 좋아요했다가 취소하면 false가 반환되고, 새롭게 좋아요하면 true로 반환된다. Service에서 이렇게 반환값을 뱉으면,

컨트롤러에서 받아서 html로 heartFullCheck라는 key값으로 데이터를 보낸다.
받은 데이터 값으로

heartFullCheack가 true이면 꽉찬하트로 이미지 전환을 해주고, false이면 빈하트 이미지로 전환하도록 하였다.

📖4. 로그인 이후 이전에 좋아요 눌렀던 것 그대로 반영되게 하기

좋아요 기능을 만들었지만, 매번 로그인 할때마다 이전에 좋아요 눌러놓았던 것이 반영이 안되었던 문제를 해결하였다. 즉, 처음에 상품 데이터들을 뿌릴때 이전에 유저가 좋아요를 누른 기록이 있다면 미리 꽉찬 이미지의 하트로 되어있어야 했다.

📚1) Controller, Repository, Service

유저id가 3이라고 하면, 현재 유저가 좋아요한 상품들이 3개가 존재한다.

  • like테이블에서 해당 유저id를 이용해 row를 찾아서 List에 담는다.
    → likeRepository, Service
  • service에 담은 List를 가져와서 model에 담아 뷰에 뿌린다.
    → Controller

📚2) HTML

(1) 코드를 돌리면 해당 유저가 좋아요한 상품의 id를 value에 넣어둔다.

(2) 페이지가 로드되면, LikeName이라는 이름을 가진 input의 모든 value를 가져와서(=상품의 id와 같다.) 해당 하트이미지를 꽉찬이미지로 바꿔놓는다.

📌좋아요와 장바구니 기능과의 차이점

딱 한가지 다른점이라면 toast 메세지이다.

토스트 창을 띄우기 위해서는 따로 import를 시켜줘야 한다.

그리고 나서 ajax에서 요청하고 나서 success를 하면 toast메세지를 띄우도록 했다.

profile
배우는 것이 즐겁다!

1개의 댓글

comment-user-thumbnail
2022년 7월 11일

와 정리 잘하시네요!!

답글 달기