Spring/API

API 개발 : 간단한 주문조회 (지연로딩 최적화 - 패치 조인)

JWonK 2022. 6. 26. 17:45
728x90
반응형

전 게시글과 동일한 조건에서 지연로딩으로 발생하는 1 + N 문제를 최적화하는 방법이다.

 

< 주어진 조건 >

  • 회원 조회가 아닌 주문 조회
  • REST API : GET Method 적용
  • 주문과 xToOne관계로 맺어져 있는 정보를 조회할 것
  • 즉, 컬렉션 조회가 아님
  • 주문과 연관되어있는 회원, 배송정보를 조회할 것
  • 지금까지 게시글로 원하는 API 반환을 위해서는 API 스펙에 맞춰 DTO 클래스를 설계하여 반환해야한다는 것을 알고 있다는 가정 하, DTO로 변환하여 반환하는 코드로 작성
  • 조건 : API 반환으로 원하는 조건은 { 주문 번호, 사용자 이름, 주문 날짜, 주문 상태, 배송지 정보} 이다. 이 스펙에 맞춰 DTO를 개발해야한다.

@RestController
@RequiredArgsConstructor
/**
 * Order
 * Order -> Member
 * Order -> Delivery
 * 즉, 컬렉션 조회가 아닌 xToOne(ManyToOne, OneToOne) 관계
 */
public class OrderSimpleApiController {

    private final OrderRepository orderRepository;
    
    @GetMapping("/api/v3/simple-orders")
    public List<SimpleOrderDto> ordersV3(){
        List<Order> result = orderRepository.findAllWithMemberDelivery();
        return result.stream()
                .map(o -> new SimpleOrderDto(o))
                .collect(Collectors.toList());
    }

    @Data
    static class SimpleOrderDto{
        private Long orderId;
        private String name;
        private LocalDateTime orderDate;
        private OrderStatus orderStatus;
        private Address address;

        public SimpleOrderDto(Order order){
            orderId = order.getId();
            name = order.getMember().getUsername();
            orderDate = order.getOrderDate();
            orderStatus = order.getOrderStatus();
            address = order.getDelivery().getAddress();
        }
    }
}
@Repository
@RequiredArgsConstructor
public class OrderRepository {

    private final EntityManager em;
    
    public List<Order> findAllWithMemberDelivery(){
        /**
         * LAZY 설정이지만 프록시 객체가 아닌 진짜 객체로 모두 조인한 후 가져온다 -> 패치 조인
         */
        return em.createQuery(
                "select o from Order o" +
                        " join fetch o.member m" +
                        " join fetch o.delivery d", Order.class).getResultList();
    }
}

전과 달리 변한 것은 쿼리문에 패치 조인이 적용되었다는 것 뿐이다. 만약 패치 조인을 하지 않을 경우에는 

1. Order를 전부 가져온다.

2. 원하는 정보 중 Order 테이블과 연관관계가 있는 회원 Member 테이블과 Delivery 테이블을 모두 가져온 후 원하는 정보를 추출한다.

즉, 원하는 정보가 있는 테이블을 모두 가져와야했다.

 

하지만 패치 조인을 적용하게 되면 우리가 원하는 정보만을 하나의 테이블로 합쳐 이를 반환받는다. 따라서, 1 + N개의 쿼리문이 아닌 1개의 쿼리문으로 끝나버린다. 엄청난 최적화가 이루어질 수 있다.

 

실무에서 발생하는 대부분의 문제는 1 + N문제라고 한다. 패치 조인을 정확하고 올바르게 이해해야 하는 이유이다.

728x90
반응형