GitHub

https://github.com/Choidongjun0830

Spring

[JPA 활용 2편] API 개발 고급 - 지연 로딩과 조회 성능 최적화

gogi masidda 2024. 7. 3. 16:50

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

 

  • 간단한 주문 조회 V1: 엔티티를 직접 노출 -> 무한 루프에 빠지게 됨. 주문에서 멤버로, 멤버에서 주문이 있네? 주문으로
    • 양방향이 걸리는 필드를 @JsonIgnore 해주어야 함.
      • 하지만 이러면 500 오류가 남.
    • 또는 Hibernate5Module을 등록해서 사용해야함.
    • 하지만 엔티티를 직접 노출하면 데이터 그대로 노출하는 것이라 좋지 않다. 
    • 이 방식을 사용하면 안된다.
    • DTO로 변환해서 사용하는 것이 좋다.
    • 지연 로딩을 피하기 위해 즉시 로딩으로 바꾸면 안됨. 연관 관계가 필요없는 경우에도 데이터를 항상 조회해서 성능 문제가 발생한다. 
  • 간단한 주문 조회 V2: 엔티티를 DTO로 변환 
    • 이 방식이면 엔티티가 바뀌어도 api 스펙이 바뀌지 않아서 좋다. 
    • 하지만 v1과 v2 모두 레이지 로딩으로 인해 쿼리가 너무 많이 호출된다. (N+1문제 발생)
  • 간단한 주문 조회 V3: 페치 조인 최적화
    • 페치 조인은 다 조인하고 한번에 다 가져오는 것. 프록시를 넣는 것이 아니라 레이지를 무시하고 진짜 값을 넣음
    • v2에서 총 5번의 쿼리가 나갔었지만, 페치 조인을 이용한 v3에서는 쿼리가 1번 나간다. 
  • 간단한 주문 조회 V4: JPA에서 DTO로 바로 조회
    • new를 사용하여 JPQL의 결과를 DTO로 반영
    • v3와는 다르게 v4에서는 원하는 것만 가져옴. 그래서 select 절의 길이가 짧아짐.
    • v3와 v4 간에 우열을 가리긴 어려움. 트레이드 오프가 있음. 
      • v3는 내부에 원하는 것만 페치 조인으로. 재사용 가능 
      • v4는 재사용 불가, api 스펙이 바뀌면 다 고쳐야 함. 

쿼리 방식 선택 권장 순서

  1. 엔티티를 DTO로 변환
  2. 필요하면 페치 조인 => 대부분의 성능 이슈 해결
  3. 그래도 안되면 DTO로 직접 조회하는 방법
  4. 최후의 방법은 JPA가 제공하는 네이티브 SQL이나 스프링 JDBC template을 사용해서 SQL을 직접 사용 
728x90