Summary

엔티티 조회

  1. 엔티티 그대로 반환 : 엔티티가 수정되면 API도 수정해야하는 문제점

  2. DTO(Data Transformed Object)로 변환 : API 스펙에 맞게 DTO 생성해서 DTO로 반환

  3. xToOne : fetch join으로 쿼리수 최적화

  4. fetch join 한계 : 페이징 불가(실무에서는 페이징 사용 많이 함) ex) 대량의 데이터를 API로 전송해야하는 경우 끊어서 보낸야한다. (페이징 필요)

  5. 컬렉션 페이징과 한계돌파 컬렉션은 페치 조인 시 페이징❌ ToOne 관계는 페치 조인으로 쿼리 수 최적화 컬렉션은 페치 조인 대신 지연 로딩 유지, hhibernate.default_batch_fetch_size, @BatchSize로 최적화 지연로딩 : 하나의 엔티티에 대해 연관된 모든 엔티티에 따로 하나씩 조회 쿼리를 날린다!(N+1문제 발생)

DTO 직접 조회

  1. JPA에서 DTO 직접 조회(V4)

  2. 컬렉션 조회 최적화 : 일대다 관계인 컬렉션IN 절을 활용해서 메모리에 미리 조회해서 최적화(V5)

  3. 플랫 데이터 최적화 : JOIN 결과를 그대로 조회애플리케이션에서 원하는 모양으로 직접 변환(V6)

권장 순서

  1. 엔티티 조회 방식으로 우선 접근 1. 페치조인으로 쿼리 수를 최적화 2. 컬렉션 최적화 1. 페이징 필요 : hibernate.default_batch_fetch_size , @BatchSize 로 최적화 2. 페이징 필요X : 페치 조인 사용

2. 엔티티 조회 방식으로 해결이 안 되면 DTO조회 방식 사용 3. DTO 조회 방식으로 해결이 안되면 NativeSQL or 스프링 JdbcTemplate =>DB 커넥션 가져와서 쓰는 방법.

  • 참고 ① 엔티티 조회 방식은 페치 조인이나, hibernate.default_batch_fetch_size , @BatchSize 같이 코드를 거의 수정하지 않고, 옵션만 약간 변경해서, 다양한 성능 최적화를 시도할 수 있다. 반면, DTO를 직접 조회하는 방식은 성능을 최적화 하거나 성능 최적화 방식을 변경할 때 많은 코드를 변경해야 한다.

=>대부분의 경우 ①로 해결이 된다! ①로 해결되지 않는다면 서비스의 트래픽이 굉장하다는 것이다. 이런 경우에는 DTO로 직접 JPQL을 작성하는 방법 보다는 캐시(Redis/Local Memory)를 쓰는 방법 쪽으로 고려해야 한다.

  • 참고 엔티티는 캐싱하면 안된다! 영속성 컨텍스트에서 관리 되기 때문에 캐시에 잘못 올라가면 데이터가 꼬일 수 있다! => 캐시할 거면 무조건 DTO로 변환해서 DTO를 캐시해야한다!

DTO 조회 방식의 선택지

  • V4 : 코드 단순. 특정 주문 한건만 조회하면 이 방식을 사용해도 성능이 잘 나온다. ex) 조회한 Order 데이터가 1건이면 OrderItem을 찾기 위한 쿼리도 1번만 실행하면 된다.

  • V5 : 코드 복잡. 여러 주문을 한꺼번에 조회하는 경우에는 V4 대신에 이것을 최적화한 V5 방식을 사용해야 한다. 예를 들어서 조회한 Order 데이터가 1000건인데, V4 방식을 그대로 사용하면, 쿼리가 총 1 + 1000번 실행된다. 여기서 1은 Order 를 조회한 쿼리고, 1000은 조회된 Order의 row 수다. V5 방식으로 최적화 하면 쿼리가 총 1 + 1번만 실행된다. 상황에 따라 다르겠지만 운영 환경에서 100배 이상의 성능 차이가 날 수 있다. =>엔티티에서는 batch size 옵션으로 간편하게 해결되는 문제다!

  • V6 : 쿼리 한번으로 최적화되어서 네트워크 통신하는 횟수가 줄어들기 때문에 상당히 좋아보이지만,

    Order를 기준으로 페이징이 불가능! =>실무에서는 이정도 데이터면 수백이나, 수천건 단위로 페이징 처리가 꼭 필요하므로, 이 경우 선택하기 어려운 방법이다. 그리고 데이터가 많으면 중복 전송이 증가해서 V5와 비교해서 성능 차이도 미비하다.

Last updated