이번 강의 내용을 정리하기 전에 [결론]부터 말하자면,
DTO로 바로 조회하는 방법은 얻는 이점 대비 단점이 더 큰 방법이다.
따라서 대부분의 경우 성능 최적화를 위해서는
DTO로 바로 조회하기 보다는 순수 Fetch Join을 사용하는것이 더 적합하다고 생각한다!
그럼에도 DB에서 데이터를 조회시 [DTO로 바로 조회하는 방법]을 알아보자
- Repository 패키지 안에서, 별도의 패키지를 생성 후, 그 패키지 안에 DTO 조회 전용 Repository와 DTO 정의
- 특정 API에서 해당 Repository와 DTO를 사용
여기서 DTO로 바로 조회할 때 사용하는 [Repository와 DTO를 별도의 패키지로 분리]하는 이유에 대해 주목할 필요가 있는데,
- DTO로 바로 조회하는 로직의 경우, API 스펙이 변하면 로직 또한 변하게 되어 있다. 즉 기존의 MVC 아키텍쳐와 다르게, Repository가 Presentation 계층에 의존적이게 되므로, 이러한 특징을 구분시키기 위하여 다른 Repository와 분리 시킬 필요가 있다!
- 또한 DTO역시 DTO로 바로 조회하는 특수한 경우에만 사용되게 된다. 따라서 이러한 특징을 구분시키기 위하여, 별도의 패키지로 구분시키는 것이 좋다.
/** <별도의 Repositry에서 정의된 로직>*/
public List<OrderSimpleQueryDto> findOrderDtos(){
List<OrderSimpleQueryDto> dtoList = em.createQuery("select new jpabook.jpashop_review.repository.order.simplequery.OrderSimpleQueryDto" +
"(o.id, m.name, o.orderDate, o.status, d.address) from Order o join o.member m join o.delivery d", OrderSimpleQueryDto.class)
.getResultList();
return dtoList;
}
/**
* <주문 조회 API>
* : 모든 주문들을 조회
*
* [버전4]
* : 별도의 Repository와 별도의 DTO를 정의하여, JPA에서 DTO로 바로 조회하는 방법
*
* -> 이 또한 Fetch Join과 유사하게, 내부적으로 Inner Join을 사용하므로, 실제 쿼리는 1번만 나간다.
* -> 또한 1번 나가는 그 쿼리 안에서, DTO가 원하는 컬럼들 만을 선택해서 가져오므로, 별도의 DTO 변환 작업도 필요 없게 된다.
* */
@GetMapping("/api/v4/simple-orders")
public List<OrderSimpleQueryDto> ordersV4(){
return orderSimpleQueryRepository.findOrderDtos();
}
이와 같이 DTO로 직접 조회했을 때 얻는 [장점]
- Fetch Join과 같이 모든 컬럼이 다 네트워크를 타고 넘어오는 것이 아니라, 일부 선택한 컬럼만 네트워크를 타고 넘어오므로, 이에 대한 성능 향상이 있다.
이와 같이 DTO로 직접 조회했을 때 얻는 [단점]
- 단 이때의 성능 향상 정도가 미비하다
- 일단 요즘 Network Bandwidth가 크기 때문에 , 컬럼 몇개가 더 넘어온다고 성능이 크게 떨어지지는 않는다.
- 무엇보다도 실제 성능을 좌지우지 하는것은 컬럼의 개수가 아닌 join 부분이기 때문에, 내부적으로 같은 inner join을 사용하는 Fetch Join 대비 큰 성능 향상을 얻기 어렵다.
- 그 API에 맞는 데이터만 가져오므로, 해당 Repository 로직을 다른 곳에서 재사용 하기가 어렵다.
- 또한 API 스펙이 변하면, 그 Repository 로직또한 변하게 되는 Critical한 문제가 있다.
- 무엇보다도 DB에서 가져온 데이터를 조작해서 반환하는 경우가 태반인데, 그러한 조작 및 가공을 하기가 어렵다.
그리하여 내릴 수 있는 [결론]
대부분의 경우 Fetch Join을 사용하여 조회시 성능 최적화를 시키고, 그럼에도 컬럼이 수십개씩 넘어오고 요청이 빈번하여 성능 최적화가 안되는 경우에 한하여 DTO로 직접 조회하도록 하자!
만약 DTO로 직접 조회하더라도 성능이 나오지 않을 경우.. SQL을 직접 날려 성능을 최적화 시키자.