API 스펙을 명확하게 규정했다고 가정합시다. 참고해서 SimpleOrderDto 를 만들겠습니다.
@RestController
@RequiredArgsConstructor
public class OrderSimpleApiController {
private final OrderRepository orderRepository;
@GetMapping("/api/v2/simple-orders")
public List<SimpleOrderDto> ordersV2() { //...1
List<Order> orders = orderRepository.findAllByString(new OrderSearch());
return orders.stream()
.map(SimpleOrderDto::new)
.collect(Collectors.toList());
}
@Data
static class SimpleOrderDto {
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address; //...3
public SimpleOrderDto(Order order) { //...2
orderId = order.getId();
name = order.getMember().getName();
orderDate = order.getOrderDate();
orderStatus = order.getStatus();
address = order.getDelivery().getAddress();
}
}
}
V2 API 의 반환값은 간단히 하기 위해서 리스트를 반환했습니다.
DTO 가 entity 를 파라미터로 받는 것은 크게 문제가 되지 않습니다.
별로 중요하지 않은 곳에서 중요한 엔티티에 의존하는 것이기 때문이죠.
→ 자세히
Address 는 value object ( VO ) 입니다.
실행을 하면 정해진 스펙으로 최적화되어 응답이 되는 것을 확인할 수 있습니다.
그런데 V1 과 동일하게 V2 도 가지고 있는 문제점이 있습니다.
지연로딩으로 인한 데이터베이스 쿼리가 너무 많이 호출되는 문제점입니다.
지금까지 만든 API 는 order, member, delivery 란 총 3개의 테이블을 건들고 있죠.
그러면 쿼리는 처음에 order 를 조회해서 데이터를 가져오고, DTO에서 getMember() 와 getDelivery() 로 Lazy 초기화를 시키면서 member 와 delivery 의 데이터를 가져올겁니다.
영속성 컨텍스트가 찾아온 order 에서 member id 를 가지고 찾는데 없으니까 DB에서 찾아오고, 또 delivery id 가지고 찾는데 없으니까 DB에서 찾아오겠죠.
그래서 총 3개의 쿼리가 발생하면서 첫번째 주문이 완성됩니다.