개발지식 먹는 하마 님의 블로그

[내일배움캠프 47일차] 배달앱 장바구니 구현 본문

내일배움캠프 (CS25)

[내일배움캠프 47일차] 배달앱 장바구니 구현

devhippo 2025. 4. 24. 09:25

장바구니 구현에서 핵심 기능인 부분은 메뉴 추가였다.
메뉴 추가 시 고려해야할 부분이 많았다.

장바구니 메뉴 추가 알고리즘

  • 유저의 장바구니가 이미 존재하는가?
    • 존재하지 않는다면 새로운 장바구니를 생성한다.
        // userId에 해당하는 장바구니 존재 여부를 확인하고 없다면 장바구니를 생성한다.
        Cart cart = cartRepository.findByUserId(userId)
                .orElseGet(() -> {
                    Cart newCart = Cart.createCart(user, store);
                    return cartRepository.save(newCart); //새로 생성해 데이터 베이스에 저장한 newCart 반환
                });
  • 장바구니에 담긴 메뉴들의 가게가 새로 추가하려는 메뉴의 가게와 동일한가?
    • 다르다면 장바구니를 초기화(삭제)하고 새로운 장바구니를 생성한다.
 if(!cart.isEqualStoreId(store.getId())){
            //가게 id가 다르다면 장바구니를 초기화한다.
            cart.getCartItems().clear();
            cartRepository.deleteById(cart.getId());
            cart = cartRepository.save(Cart.createCart(user, store));
}
  • 추가하려는 메뉴가 이미 장바구니에 담겨 있는가?
    • 담겨있다면 기존 수량에 추가하려는 수량을 더한다
    • 담겨있지 않다면 새로운 메뉴를 장바구니에 추가한다.
Optional<CartItem> cartItem = cartItemRepository.findByCartIdAndMenuId(cart.getId(), menu.getId());
if(cartItem.isPresent()){
            //이미 존재하는 Menu라면 기존 수량과 새로운 수량을 더한다.
            CartItem existing = cartItem.get();
            existing.updateQuantity(existing.getQuantity() + createCartItemRequest.getQuantity());
            return ;
 }

 

추가할 가능성이 있는 부분

장바구니의 유효성 검증 여부를 어떻게 구현할지는 이벤트 스케줄러를 먼저 구현한 후, 고민해봐야할 것 같다.

예상) AOP 또는 Interceptor로 요청 전에 장바구니가 유효한지 검사

 


장바구니에 속한 메뉴 조회

Dto Projection과 Mapping 방법 중에 고민하였다.

Dto Projection와 Mapping 비교 

  장점 단점
Dto Projection 불필요한 엔티티 조회를 피하며 성능 향상, 가독성 낮은 재사용성, 순서 뒤바뀜 주의.
복잡한 Dto에는 적합하지 않음
Mapping 높은 재사용성, 용이한 유지보수 N+1 문제 발생, 메모리 사용량 증가 가능성

장단점을 비교해본 후 우선 Dto Projection을 사용하였다.
(피드백 받은 후, 변경할 가능성이 있다.)

Dto Projection 예시

   @Query("""
            SELECT new org.example.delivery.domain.cart.dto.response.CartItemResponse (
                ci.id, m.id, m.name, ci.quantity, ci.priceSnapshot
            )
            FROM CartItem ci
            JOIN ci.menu m
            WHERE ci.cart.id = :cartId
    """)

Mapping 예시

findAllByUserId.stream().map(FindAllOrderResponseDto::toDto).toList();