강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

6udguin님의 프로필 이미지
6udguin

작성한 질문수

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

주문 조회 V3.1: 엔티티를 DTO로 변환 - 페이징과 한계 돌파

JPA 유의점과 V3.1 에 대한 질문입니다!

작성

·

82

0

=========================================
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)

[질문 내용]

 

안녕하세요.
JPA 유의점과 V3.1 에 대한 질문입니다!

지금까지 수업을 들으며 제가 요약한 내용은

  1. Repository 에서 Entity 를 조회한다.

  2. 해당 조회에서 N+1이 발생한다면

     

    -> 회원목록을 조회한다면 N+1 이 발생하지 않지만, 회원목록 + 가장 최근에 주문한 상품1개 도 함께 조회를 한다면 N+1 문제가 발생한다.

     

    > 목록데이터를 조회하는데, 목록데이터 각각의 PK를 FK로 참조하는 다른 테이블의 데이터를 함께 조회하는데 Lazy 로딩일 경우 N+1 문제가 발생한다.

  3. N+1 이 발생할 경우 fetch join 으로 변경한다.

  4. 해당 fetch join 쿼리에 컬렉션(리스트 등) 타입이 존재할 경우 select 문에서 컬렉션을 조회하는 쿼리를 지우고, XtoOne 연관관계에 있는 엔티티 조회는 fetch join 을 유지한다. + hibernate.default_batch_fetch_size 설정한다.

     

    이렇게 정리했습니다! 혹시 정정해야하는 부분이 있을까요??

     

     

     

    V3.1 에 대한 질문은, 조회쿼리에서 OrderItem은 없지만, Controller 에서의

     

    @Data
        static class OrderDto {
            private Long orderId;
            private String name;
            private LocalDateTime orderDate;
            private OrderStatus orderStatus;
            private Address address;
            private List<OrderItemDto> orderItems;
    
            public OrderDto(Order order) {
                orderId = order.getId();
                name = order.getMember().getName();
                orderDate = order.getOrderDate();
                orderStatus = order.getStatus();
                address = order.getDelivery().getAddress();
                orderItems = order.getOrderItems().stream()
                        .map(orderItem -> new OrderItemDto(orderItem))
                        .collect(toList());
            }
        }
    
        @Data
        static class OrderItemDto {
    
            private String itemName; //상품명
            private int orderPrice; //주문가격
            private int count; //주문수량
    
            public OrderItemDto(OrderItem orderItem) {
                itemName = orderItem.getItem().getName();
                orderPrice = orderItem.getOrderPrice();
                count = orderItem.getCount();
            }
        }
    

    여기서 List<OrderItemDto> orderItems
    부분으로 인하여
    proxy 로 들고 왔던 것을 실제 DB조회를 하여
    orderItems 에 값을 채워넣는 게 맞나요?

답변 1

0

안녕하세요, 인프런 AI 인턴입니다.

6udguin님, 질문해 주신 JPA의 N+1 문제와 V3.1에 대한 내용에 대해 확인해보겠습니다.

  1. JPA N+1 문제와 Fetch Join:

    • JPA에서 N+1 문제는 주로 여러 연관 관계의 엔티티를 조회하면서 발생합니다. 여러분이 정리한 것처럼, 회원 목록뿐만 아니라 각 회원이 주문한 상품까지 조회하려고 하는 경우에 문제가 발생할 수 있습니다.
    • 이런 경우, fetch join으로 연관된 데이터를 즉시 로딩하여 N+1 문제를 해결할 수 있습니다.
    • 하지만, 컬렉션 타입의 연관 관계를 fetch join으로 조회할 때에는 조인 결과가 중복될 수 있어 결과 세트가 방대해질 수 있습니다. 따라서 필요하다면 hibernate.default_batch_fetch_size를 설정하여 성능을 최적화할 수 있습니다.
    • 요약하신 내용은 전반적으로 JPA 성능 최적화의 핵심을 잘 반영하고 있습니다.
  2. V3.1에서의 OrderDto:

    • OrderDto 클래스에서 List<OrderItemDto> orderItems 부분 때문에, 기본적으로 Lazy Loading 설정된 연관 엔티티(OrderItem)를 실제로 DB에서 조회하게 되고, 그 결과를 OrderItemDto로 매핑하게 됩니다.
    • 이러한 과정은 프로시에서 데이터가 실제로 필요하게 되었을 때 발생하며, 이를 통해 각각의 OrderItem 엔티티에 접근하여 DB에서 값을 가져와 채우게 됩니다.

따라서, N+1 문제를 피하기 위해서는 쿼리 단계에서 필요한 데이터들을 최대한 효율적으로 fetch join 등을 사용하여 한 번에 가져오는 것이 좋습니다.

혹시 더 궁금한 점이나 구체적인 부분에 대한 설명이 필요하다면 언제든지 질문 주세요!

추가 정보가 필요하시다면 참고할 수 있는 URL이 있으니 확인해 보세요:
자세한 내용 보기

6udguin님의 프로필 이미지
6udguin

작성한 질문수

질문하기