지연 로딩과 조회 성능 최적화
2023. 9. 29. 00:08ㆍLECTURES/실전! 스프링 부트와 JPA 활용
간단한 주문 조회 V1 : 엔티티를 직접 노출
https://github.com/dpdms529/JpaShop/commit/dd799b8549ce171d4103b883109271c2f0c286cd
- 양방향 연관 관계로 설정한 클래스 한 쪽을
@JsonIgnore
로 가져오지 않도록 한다.- 설정하지 않으면 서로 호출하기 때문에 무한 루프에 빠져 오류 발생
- 지연 로딩 설정을 한 경우 하이버네이트가 실제 객체 대신에
ByteBuddyInterceptor
를 사용하여 프록시 객체를 넣어둠 Jackson
라이브러리가 json 결과를 만드는데 초기화되지 않은 프록시 객체가 들어있으면 오류 발생Hibernate5JakartaModule
등록- 기본적으로 초기화 된 프록시 객체만 노출하고, 초기화되지 않은 프록시 객체는 null
- 강제 지연 로딩 설정으로 모든 객체 값을 가져오도록 할 수 있음
hibernate5Module.configure(Hibernate5JakartaModule.Feature.FORCE_LAZY_LOADING, true);
- 또는 클래스의 아무 필드나 가져오도록 해서 강제로 초기화시킬 수 있음
- 지연 로딩을 피하기 위해 즉시 로딩을 설정하면 안됨
- 연관관계가 필요 없는 경우에도 데이터를 항상 조회해서 성능 문제가 발생할 수 있음
- 성능 최적화가 필요한 경우에는 fetch join 사용
- 필요 없는 데이터를 노출하는 문제 -> DTO 사용
간단한 주문 조회 V2 : 엔티티를 DTO로 변환
https://github.com/dpdms529/JpaShop/commit/047eeb31bef2b1e772bf111c28a8adff3b2b3fd1
- 지연 로딩으로 인해 쿼리가 많이 나감
- N + 1 문제
order
에 대해 select 쿼리 1번 실행- N :
order
select 쿼리 결과 개수 - 연관 관계가 설정된 엔티티(
member
,delivery
)에 대해 N번씩 select 쿼리 실행됨 order
조회 한 번을 위해 연관된 엔티티당 조회하는 쿼리가 N번씩 실행됨
- 이미 조회된 경우에는 영속성 컨텍스트에서 조회하므로 쿼리 생략
간단한 주문 조회 V3 : 엔티티를 DTO로 변환 - 페치 조인 최적화
https://github.com/dpdms529/JpaShop/commit/02bab6ab03005cfd801f7740b56901b6ea04f156
- fetch join을 사용해서 쿼리 1번에 조회
간단한 주문 조회 V4 : JPA에서 DTO로 바로 조회
https://github.com/dpdms529/JpaShop/commit/834d4f53d5909a2028fdd2ad7bf7213872b3c359
- 원하는 값을 선택해서 조회
- 애플리케이션 네트워크 용량 최적화(생각보다 미비)
- 리포지토리 재사용성 떨어짐, API 스펙에 맞춘 코드가 리포지토리에 들어가는 단점
쿼리 방식 선택 권장 순서
- 우선 엔티티를 DTO로 변환하는 방법을 선택
- 필요하면 페치 조인으로 성능을 최적화 -> 대부분의 성능 이슈가 해결됨
- 그래도 안되면 DTO로 직접 조회하는 방법을 사용
- 최후의 방법은 JPA가 제공하는 네이티브 SQL이나 스프링 JDBC Template을 사용해서 SQL을 직접 사용
'LECTURES > 실전! 스프링 부트와 JPA 활용' 카테고리의 다른 글
실무 필수 최적화 (0) | 2023.09.29 |
---|---|
컬렉션 조회 최적화 (0) | 2023.09.29 |
API 개발 기본 / 고급 준비 (0) | 2023.09.29 |
웹 계층 개발 (0) | 2023.09.29 |
주문 도메인 개발 (0) | 2023.09.29 |