정리
- 엔티티 조회
- 엔티티를 조회해서 그대로 반환 : V1 (비권장)
- 엔티티 조회 후 DTO로 변환 : V2
- 페치 조인으로 쿼리 수 최적화 : V3
- 컬렉션 페이징과 한계 돌파 : V3.1
- 컬렉션은 페치 조인시 페이징이 불가능
- ToOne 관계는 페치 조인으로 쿼리 수 최적화
- 컬렉션은 페치 조인 대신에 지연 로딩을 유지하고
default_batch_fetch_size
, @BatchSize
옵션으로 최적화
- DTO 직접 조회
- JPA에서 DTO를 직접 조회 : V4
- 컬렉션 조회 최적화 - 일대다 관계인 컬렉션은 IN 절을 이용해서 메모리에 미리 조회해서 최적화 : V5
- 플랫 데이터 최적화 - JOIN 결과를 그대로 조회 후 애플리케이션에서 원하는 모양으로 직접 변화: V6
권장 순서
- 엔티티 조회 방식으로 우선 접근
- 페치 조인으로 쿼리 수 최적화
- 컬렉션 최적화
- 페이징 필요, batch_fetch_size로 최적화
- 페이징 필요 X → 페치 조인 사용
- 엔티티 조회 방식으로 해결이 안되면 DTO 조회 방식 사용
- DTO 조회 방식으로 해결이 안되면 NativeSQL or 스프링 JdbcTemplate
<aside>
💡 엔티티 조회 방식은 페치 조인이나, batch_fetch_size를 사용해서 코드를 거의 수정하지 않고 옵션만 변경해서 다양한 성능 최적화를 시도할 수 있다. 반면에 DTO는 성능 최적화 방식을 변경할 때 많은 코드를 변경해야 한다.
</aside>
<aside>
💡 개발자는 성능 최적화와 코드 복잡도 사이에서 줄타기를 해야 한다. 보통 성능 최적화를 하게 되면 코드가 복잡해 진다.
엔티티 조회 방식은 JPA가 많은 부분을 최적화 해주기 때문에 단순한 코드를 유지하면서, 성능을 최적화 할 수 있다. 반면에 DTO 조회 방식은 SQL을 직접 다루는 것과 유사하기 때문에, 둘 사이에서 줄타기를 해야 한다.
</aside>
DTO 조회 방식의 선택지
- V4, V5, V6에서 단순하게 V6가 쿼리가 1번 실행 된다고 항상 좋은 방법은 아니다.
- 이 셋은 굳이 엔티티 조회에 비해 이점이 있다고 생각되지 않는다.
- V4는 코드가 단순하다. 특정 주문 1건 조회면 이 방식을 사용해도 된다.
- V5는 V4의 단점인 N + 1을 해결했다. 사실상 batch_fetch_size를 직접 구현한 것과 같다. 페이징도 가능하다.
- V6는 완전 다른 접근 방식이다. 쿼리 한번에 쭉 가져오고 애플리케이션 레벨에서 복잡한 조합을 해야 한다. 뻥튀기 된 데이터의 페이징이 불가능하다. V5와 성능 차이도 미비하다. 중복 데이터가 많이 때문에