이 내용은 스프링 부트 쇼핑몰 프로젝트 with JPA 책을 학습한 내용입니다.
- 제품 상세 페이지에서 장바구니에 담을 상품 Id 와 수량을 전달 받을 DTO 객체 생성
 
 | @Getter | 
 | @Setter | 
 | public class CartItemDto { | 
 |   | 
 |     @NotNull(message = "상품 아이디는 필수 입력 값입니다.") | 
 |     private Long itemId;   | 
 |   | 
 |     @Min(value = 1, message = "최소 1개 이상 담아주세요.") | 
 |     private int count;   | 
 |   | 
 | } | 
- 회원 한 명당 1개의 장바구니를 갖으므로 처음 장바구니에 상품을 담을 때는 해당 회원의 장바구니를 생성해야함
 
- 멤버를 파라미터로 받아서 장바구니를 생성하는 static 메소드 추가
 
 |  | 
 |     public static Cart createCart(Member member) { | 
 |         Cart cart = new Cart(); | 
 |         cart.setMember(member); | 
 |   | 
 |         return cart; | 
 |     } | 
- 장바구니에 담을 CartItem 객체를 생성하는 메소드 추가
 
- 장바구니에 담겨 있는 상품을 또 장바구니로 담았을 경우 수량을 증가시키는 메소드 추가
 
 |  | 
 |     public static  CartItem createCartItem(Cart cart, Item item, int count) { | 
 |         CartItem cartItem = new CartItem(); | 
 |         cartItem.setCart(cart); | 
 |         cartItem.setItem(item); | 
 |         cartItem.setCount(count); | 
 |   | 
 |         return cartItem; | 
 |     } | 
 |   | 
 |      | 
 |     public void addCount(int count) { | 
 |         this.count += count; | 
 |     } | 
- 현재 로그인한 유저의 장바구니(Cart)를 찾기 위해서 쿼리 메소드 추가
 
 | public interface CartRepository extends JpaRepository<Cart, Long> { | 
 |   | 
 |      | 
 |     Cart findByMemberId(Long memberId); | 
 |   | 
 | } | 
- 상품이 장바구니에 들어있는지 조회하는 쿼리 메소드 추가
 
 | public interface CartItemRepository extends JpaRepository<CartItem, Long> { | 
 |     CartItem findByCartIdAndItemId(Long cartId, Long itemId); | 
 | } | 
- 유저의 장바구니가 존재하지 않다면 생성
 
- 장바구니 안에 해당 상품이 존재한다면 수량을 증가시키고, 그렇지 않다면 추가
 
 | @Service | 
 | @RequiredArgsConstructor | 
 | @Transactional | 
 | public class CartService { | 
 |   | 
 |     private final ItemRepository itemRepository; | 
 |     private final MemberRepository memberRepository; | 
 |     private final CartRepository cartRepository; | 
 |     private final CartItemRepository cartItemRepository; | 
 |     private final OrderService orderService; | 
 |   | 
 |     public Long addCart(CartItemDto cartItemDto, String email) { | 
 |         Item item = itemRepository.findById(cartItemDto.getItemId()).orElseThrow(EntityNotFoundException::new); | 
 |         Member member = memberRepository.findByEmail(email); | 
 |   | 
 |         Cart cart = cartRepository.findByMemberId(member.getId()); | 
 |         if(cart == null) { | 
 |             cart = Cart.createCart(member); | 
 |             cartRepository.save(cart); | 
 |         } | 
 |   | 
 |         CartItem savedCartItem = cartItemRepository.findByCartIdAndItemId(cart.getId(), item.getId()); | 
 |   | 
 |         if(savedCartItem != null) { | 
 |             savedCartItem.addCount(cartItemDto.getCount()); | 
 |             return savedCartItem.getId(); | 
 |         } else { | 
 |             CartItem cartItem = CartItem.createCartItem(cart, item, cartItemDto.getCount()); | 
 |             cartItemRepository.save(cartItem); | 
 |   | 
 |             return cartItem.getId(); | 
 |         } | 
 |     } | 
- 제품 상세 페이지에서 넘어온 CartItemDto 객체와 email 을 파라미터로 CartService.addCart() 메소드를 수행
 
 | @Controller | 
 | @RequiredArgsConstructor | 
 | public class CartController { | 
 |   | 
 |     private final CartService cartService; | 
 |   | 
 |     @PostMapping("/cart") | 
 |     public @ResponseBody ResponseEntity order(@RequestBody @Valid CartItemDto cartItemDto, BindingResult bindingResult, Principal principal) { | 
 |   | 
 |         if(bindingResult.hasErrors()) { | 
 |             StringBuilder sb = new StringBuilder(); | 
 |             List<FieldError> fieldErrors = bindingResult.getFieldErrors(); | 
 |             for(FieldError fieldError : fieldErrors) { | 
 |                 sb.append(fieldError.getDefaultMessage()); | 
 |             } | 
 |             return new ResponseEntity<String> (sb.toString(), HttpStatus.BAD_REQUEST); | 
 |         } | 
 |   | 
 |         String email = principal.getName(); | 
 |         Long cartItemId; | 
 |   | 
 |         try { | 
 |             cartItemId = cartService.addCart(cartItemDto, email); | 
 |         } catch (Exception e) { | 
 |             return new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST); | 
 |         } | 
 |   | 
 |         return new ResponseEntity<Long>(cartItemId, HttpStatus.OK); | 
 |     } | 
- "장바구니 담기" 버튼을 누르면 수행되는 Ajax 코드
 
 | function addCart(){ | 
 |       var token = $("meta[name='_csrf']").attr("content"); | 
 |       var header = $("meta[name='_csrf_header']").attr("content"); | 
 |   | 
 |       var url = "/cart"; | 
 |       var paramData = { | 
 |         itemId : $("#itemId").val(), | 
 |         count : $("#count").val() | 
 |       }; | 
 |   | 
 |       var param = JSON.stringify(paramData); | 
 |   | 
 |       $.ajax({ | 
 |         url      : url, | 
 |         type     : "POST", | 
 |         contentType : "application/json", | 
 |         data     : param, | 
 |         beforeSend : function(xhr){ | 
 |            | 
 |           xhr.setRequestHeader(header, token); | 
 |         }, | 
 |         dataType : "json", | 
 |         cache   : false, | 
 |         success  : function(result, status){ | 
 |           alert("상품을 장바구니에 담았습니다."); | 
 |           location.href='/'; | 
 |         }, | 
 |         error : function(jqXHR, status, error){ | 
 |   | 
 |           if(jqXHR.status == '401'){ | 
 |             alert('로그인 후 이용해주세요'); | 
 |             location.href='/members/login'; | 
 |           } else{ | 
 |             alert(jqXHR.responseText); | 
 |           } | 
 |   | 
 |         } | 
 |       }); | 
 |     } | 
- "장바구니 담기" 버튼을 누르면 Ajax 코드 수행되게 설정
 
<button type="button" class="btn btn-light border border-primary btn-lg" onclick="addCart()">장바구니 담기</button>