JPA2 - API 개발 고급_지연 로딩과 조회 성능 최적화

young·2023년 5월 22일
0

Spring Boot

목록 보기
15/19
post-thumbnail

💡API 설명을 위해 샘플 데이터 입력 후 진행

API 지연 로딩과 조회 성능 최적화

주문+배송정보+회원을 조회하는 API 만들기 = 주문API 생성

🖇️V1 - 엔티티 직접 노출

🚨문제점

  • order -> member 와 order -> address 는 지연 로딩
    - 따라서 실제 엔티티 대신에 프록시 존재
  • jackson 라이브러리는 기본적으로 이 프록시 객체를 json으로 어떻게 생성해야 하는지 모르기 때문에 예외 발생
    ✅Hibernate5Module 을 스프링 빈으로 등록 시 문제 해결

지연 로딩(LAZY)을 피하기 위해 즉시 로딩(EARGR)으로 설정하면 안된다!

  • 즉시 로딩 때문에 연관관계가 필요 없는 경우에도 데이터를 항상 조회해서 성능 문제가 발생할 수 있다.
  • 즉시 로딩으로 설정하면 성능 튜닝이 매우 어려워 진다.

항상 지연 로딩을 기본으로 하고, 성능 최적화가 필요한 경우에는 페치 조인 사용!

🖇️V2 - 엔티티를 DTO로 변환

🚨문제점
1. 쿼리가 총 1 + N + N번 실행됨(V1과 쿼리 수 동일)

  • order 조회 1번(order 조회 결과 수가 N이 된다.)
  • order -> member 지연 로딩 조회 N 번
  • order -> delivery 지연 로딩 조회 N 번

🖇️V3 - 엔티티를 DTO로 변환-페치 조인 최적화

public List<Order> findAllWithMemberDelivery() {
 	return em.createQuery(
 	"select o from Order o" +
 	" join fetch o.member m" +
 	" join fetch o.delivery d", Order.class)
 	.getResultList();
}
  • 엔티티를 페치 조인을 사용해서 쿼리 1번에 조회
  • 페치 조인으로 order -> member , order -> delivery 는 이미 조회 된 상태 이므로 지연로딩X

페치 조인으로 성능 최적화 시 대부분의 성능 이슈 해결

🖇️V4 - JPA에서 DTO로 바로 조회

public List<OrderSimpleQueryDto> findOrderDtos() {
 	return em.createQuery(
 		"select new jpabook.jpashop.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();
}

DTO로 직접 조회 시, SELECT절에서 원하는 데이터를 직접 선택하므로 DB 네트워크 용량 최적화!!
-> API 스펙에 맞춘 코드가 레포지토리에 들어가기 때문에 재사용성 ⬇️

🖇️쿼리 방식 선택 권장 순서

  1. 엔티티를 DTO로 변환하는 방법 선택
  2. 필요 시 페치 조인으로 성능 최적화 => 대부분의 성능 이슈 해결
  3. 안될 경우 DTO로 직접 조회
  4. JPA가 제공하는 Native SQL이나 스프링JDBC Template을 사용해서 SQL 직접 사용
profile
ฅʕ•̫͡•ʔฅ

0개의 댓글