[4] 스프링 부트와 JPA 활용 (8) - API 개발 고급 1 (지연로딩 & 조회 성능 최적화)

김정욱·2021년 3월 29일
1
post-thumbnail
post-custom-banner

Intro

  • 연관된 객체컬렉션아닌 경우 최적화 하는 과정
  • orders에 있는 모든 주문을 조회하는 api를 만드는 과정
  • order에는 주문한 memberdelivery 객체가 참조되어 있음
  • Version
    • V1 : Entity 직접 노출
    • V2 : DTO사용
    • V3 : DTO + fetch join
    • V4 : DTO + fetch join + JPQL DTO적용

V1 (Entity 반환)

(API 로직)

  • 문제점
    • jackson프록시 객체 인식 문제
      : 기본적으로 LAZY를 통한 지연로딩 설정을 가지고 있어서 order에 있는 memberaddress프록시 객체를 가리키고 있다
      (프록시 객체 초기화이루어지지 않았기 때문)
      이러한 상황에서 jackson 라이브러리에 의해 json화 되는 과정에서 프록시 객체인식하지 못하기 때문예외가 발생 & 무한루프에 빠짐
  • 해결 방법
    • Hibernate5Module + @JsonIgnore
      : 초기화된 프록시 객체만 노출되게 하며, 양방향 연관관계 무한루프를 해결
      (실무에 적합하지 않은 방법이니 존재만 확인할 것)
    • DTO 사용
      : 반환하는 객체에 맞는 DTO생성해서 사용 --> 실무에 적합!

V2 (DTO 사용)

(API 로직)

  • 문제점
    • N+1 문제 발생
      : 반환 DTO데이터를 생성하는 과정에서(생성자) map에 따라서 차례로 관련 데이터를 가져오는 쿼리가 추가로 발생된다 --> N+1 문제 발생
  • 해결 방법
    • N+1 문제 --> fetch join 사용

(DTO)

  • 생성자를 통해 nameaddress값을 지정하는 과정에서 LAZY로딩 수행
    --> 반복문 순회 할 때 마다 쿼리가 생김
    --> N+1 문제 발생

V3 (DTO + fetch join)

(API 로직)

  • 문제점
    • 테이블모든 Column값을 반환하게 된다
  • 해결 방법
    • 필요한 데이터만 받기
      --> JPQL을 직접 받는 DTO 설정
  • 주의
    • JPQL 직접 받는 DTO설정은 생각보다 효과가 미비
    • DTO + fetch join이면 대부분의 최적화 문제는 해결된다
    • JPQL에 직접 DTO설정을 하는 것은 선택적으로 가져가자
      (설정하기 조금 귀찮기 때문 - V4에서 설명함)

(fetch join 코드 추가 - repository)

  • fetch join을 사용해서 연관 객체들의 정보를 모두 가져와 영속성 컨텍스트에서 관리
    --> 추가적으로 쿼리가 나가는 것방지

V4 (DTO + fetch join + JPQL DTO)

(API 로직)

  • OrderSimpleQueryDto 라는 DTO를 사용
  • orderRepository,findOrderDtos
    : JPQL에 DTO를 직접 설정해서 원하는 필드만 받게하는 것

(DTO)

  • 반드시 생성자에 객체가 아닌 필드를 직접 받아서 매핑해줘야 함
    (조금 번거로움)

(JPQL 튜닝 - repository)

  • new 패키지명.dto(필드 나열) 을 통해서 직접 받는 DTO 설정
  • 결과적으로 성능V4가 제일 좋음

정리

  • Entity를 직접 반환 하지 말고 반드시 DTO를 생성해서 반환
    • 프록시 객체 문제 해결
    • json 무한루프 문제 해결
  • 지연로딩으로 발생하는 N+1 문제fetch join으로 해결
  • JPQL에 값을 직접 받는 DTO설정선택적으로 사용
    • 생각보다 성능 개선미비
    • API스펙에 맞춘 코드repository에 들어가는 단점이 있음
    • 필드를 직접 나열해야하는 불편함이 있음
  • 결과
    : V3기본적으로 가져가며 V4설정선택적으로 사용
profile
Developer & PhotoGrapher
post-custom-banner

0개의 댓글