0. 개요
- 일반적으로 JPA에서 조회를 수행할 때, Entity로부터 조회된 결과를 DTO를 통해 전달한다.
- 그러나 이러한 과정을 스킵하고 바로 DTO를 통해 조회할 수 있는 방법은 없을까?
- 이번 포스팅에서는 DTO를 통해 직접 조회 방법에 대해 알아보자.
1. DTO를 통한 직접 조회
- 이전 포스팅에서는 Entity의 조회 결과를 DTO에 넘겨서 DTO 객체를 반환하는 방법으로 조회하였다.
- DTO를 통한 직접 조회 방법은 조회 결과를 DTO 객체로 직접 반환하는 방법이다.
a) DTO 클래스 생성
- 다음과 같이 DTO 클래스를 생성한다.
@Data
public class SimpleOrderQueryDto {
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address;
public SimpleOrderQueryDto(Long orderId, String name, LocalDateTime orderDate,
OrderStatus orderStatus, Address address) {
this.orderId = orderId;
this.name = name;
this.orderDate = orderDate;
this.orderStatus = orderStatus;
this.address = address;
}
}
- 위의 코드에서 주목해야 할 부분은 생성자의 매개변수다.
- 이전 포스팅에서 Entity를 거쳐 DTO로 변환하는 방식에서는 매개변수에 Entity 객체가 들어갔다.
- 그러나 DTO를 통한 직접 조회 방식은 위의 생성자처럼 모든 요소를 매개변수로 받는다.
b) Repository에 조회 메서드 생성
- 필드를 매개변수로 받는 이유는 Repository의 조회 메서드 내부에서 사용하기 위함이다.
- 다음 Repository의 조회 메서드를 살펴보자.
@Repository
@RequiredArgsConstructor
public class OrderRepository {
private final EntityManager em;
public List<SimpleOrderQueryDto> findAllUsingDto() {
return em.createQuery(
"select new jpabook" +
".jpabook.api" +
".SimpleOrderQueryDto(o.id, m.name, o.orderDate, o.status, d.adderss)" +
" from Order o" +
" join o.member m" +
" join o.delivery d", SimpleOrderQueryDto.class).getResultList();
}
}
- 위의 메서드 내부의 JPQL을 주목하자.
- DTO를 통해 직접 조회하기 위해서 JPQL에서 new 연산자를 이용해 DTO 객체를 생성하였다.
- 그리고 매개변수로 조회된 Entity의 요소가 들어간다.
- 이 과정을 위해 DTO 생성자에서 객체가 아닌 필드를 매개변수로 받은 것이다.
→ 이전 포스팅에서도 언급한 내용으로, JPQL에서 객체는 기본 키를 의미한다. (https://devraphy.tistory.com/604)
- Controller에서 다음 메서드를 생성하고 API를 호출해보자.
@RestController
@RequiredArgsConstructor
public class OrderSimpleApiController {
private final OrderRepository orderRepository;
@GetMapping("api/v4/simple-orders")
public List<SimpleOrderQueryDto> orderV4() { // DTO를 이용한 직접 조회
return orderRepository.findAllUsingDto();
}
}
c) 실행 결과
- 콘솔을 확인하면 다음과 같은 쿼리가 발행한다.
- 이전 포스팅의 실행 결과와는 다르게 select 부분이 굉장히 깔끔한 것을 확인할 수 있다.
- 이처럼 select 부분이 깔끔한 이유는 필요한 데이터를 직접 선택하였기 때문이다.
2. DTO 변환 VS DTO 직접 조회
- 이전 포스팅에서 배웠던 DTO 변환 방식과 이번 포스팅의 DTO 직접 조회 방식의 차이를 알아보자.
a) DTO 직접 조회 방식의 장단점
- DTO 직접 조회 방식은 데이터를 선택적으로 조회할 수 있다는 것이 장점이자 단점이다.
- 데이터가 선택적 조회되므로 DB 네트워크의 비용이 저렴하다는 것이 장점이다.
- 반환형을 DTO로 선언하므로 해당 DTO에 한정적으로 사용된다는 것이 단점이다.
- 즉, 조회된 데이터의 재사용성이 좋지 않다.
b) DTO 변환 방식의 장단점
- 객체가 조회 대상이므로 필요하지 않은 데이터까지 모두 조회된다는 것이 장점이자 단점이다.
- 객체의 모든 데이터가 조회되므로 상대적으로 DB 네트워크 비용이 비싸다는 것이 단점이다.
- 객체의 모든 데이터가 조회되므로 다양한 DTO에서 조회 결과를 활용할 수 있다는 장점이 있다.
- 즉, 조회된 데이터의 재사용성이 좋다.
c) 결론
- DTO 변환 방식과 DTO 직접 조회 방식은 서로 상반된 특성을 가진다.
- 그러므로 특정 방식이 우위에 있다고 말할 수 없다.
- 사실 조회 방식에 따른 DB 네트워크 비용을 비교하는 것은 요즘 서버 스펙상 무의미하다.
- 즉, 데이터의 재사용성 또는 트래픽 수요에 따라 두 방식 중 하나를 사용하면 되겠다.
3. 권장하는 조회 방식
- 지금까지 DTO 변환 방식와 DTO 직접 조회 방식에 대해서 알아보았다.
- 이 두가지 방식은 상반된 특성을 가지고 있으므로 어떤 방식이 더 우위에 있다고 설명하기 어렵다.
- 다만, 유지보수성과 재사용성을 고려했을 때 DTO 변환 방식을 우선적으로 사용하는 것을 권장한다.
- 대부분의 쿼리 성능 이슈는 Fetch Join을 사용하면 해결된다.
- 그러므로 우선 DTO 변환 방식을 우선적으로 사용한다.
- Fetch Join을 사용해도 쿼리 성능 이슈가 해결되지 않는다면 DTO 직접 조회 방식을 적용한다.
- DTO 직접 조회 방식을 사용해도 문제가 해결되지 않는다면 네이티브 SQL을 사용하여 해결하는 것을 권장한다.
'Back-end > JPA 개념' 카테고리의 다른 글
API 조회 성능 최적화 - 컬렉션(Fetch Join, distinct) (0) | 2022.06.02 |
---|---|
API 조회 성능 최적화 - 컬렉션(DTO 변환) (0) | 2022.06.01 |
API 조회 성능 최적화 - DTO 변환 방식(Fetch Join) (0) | 2022.05.30 |
API 조회 성능 최적화 - Entity 직접 노출 방식 (0) | 2022.05.28 |
JPA를 이용한 API 개발 꿀팁 - Annotation (0) | 2022.05.27 |
댓글