간단한 주문 조회 V2 - 엔티티를 DTO로 변환

학습 페이지

    @GetMapping("/api/v2/simple-orders")
    public List<SimpleOrderDto> ordersV2() {

    }

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

DTO를 이용해보자.

이제 반환되는 Order 들을 SimpleOrderDto 로 변환해줘야 한다. 이를 위해 DTO에 생성자를 하나 만들어주자.

    @GetMapping("/api/v2/simple-orders")
    public List<SimpleOrderDto> ordersV2() {
        List<Order> orders = orderRepository.findAllByString(new OrderSearch());
        List<SimpleOrderDto> result = orders.stream().map(
                        SimpleOrderDto::new)
                .collect(Collectors.toList());

        return result;
    }

    @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().getName();
            orderDate = order.getOrderDate();
            orderStatus = order.getStatus();
            address = order.getDelivery().getAddress();
        }
    }

이제 포스트맨으로 테스트해보자.

image.png

이제 필요한 데이터들만 출력되고 있다.

이렇게 DTO로 변환하는 것이 API구현의 기본이다.

N+1문제

이렇게 하면 이제 노출되는 데이터를 통제할 수 있어서 문제는 해결됐지만… 테이블 3개를 조인하는데서 오는 성능 문제는 여전히 존재한다.

위 결과를 내기 위해 어떤 쿼리가 날아갔는지 확인해보자.

제일 먼저 지연로딩이기 때문에 Order만 조회한다.

image.png

위에서 스트림으로 DTO로 변환할때, 레이지로딩의 프록시가 초기화되면서 실제 테이블들을 조회하기 시작한다. 이때 where절로 id를 통해 찾는다. 즉, 단 하나의 row만 찾는다. 여기서 슬슬 이상하다는 생각이 든다

image.png

image.png