카테고리 없음

JPA N+1 문제 해결법

Blue_bull 2025. 4. 17. 15:07

 

JPA N+1 문제 최종 정리

N+1 문제란?

**"한 번의 쿼리(1)로 N개의 데이터를 가져온 후, 각 데이터에 대해 추가 쿼리(N)를 실행하는 비효율적인 쿼리 문제"**를 말합니다.


발생 예시

List<Member> members = em.createQuery("SELECT m FROM Member m", Member.class).getResultList();

for (Member m : members) {
    System.out.println(m.getTeam().getName());
}
  • 위 코드 실행 시 다음과 같은 쿼리 발생:
    1. SELECT * FROM member → 1번 실행
    2. SELECT * FROM team WHERE id = ? → 멤버 수만큼 실행 (N번)
      → 총 1 + N번 쿼리 실행됨

원인

  • 연관 관계가 fetch = LAZY일 경우, 연관 엔티티는 실제 접근 시점에 쿼리가 실행됩니다.
  • 루프에서 .getTeam()과 같이 접근할 경우, 각 멤버마다 팀을 조회하는 쿼리가 추가로 발생합니다.

해결 방법

  1. Fetch Join 사용
  2. SELECT m FROM Member m JOIN FETCH m.team
  3. @EntityGraph 사용
  4. @EntityGraph(attributePaths = {"team"}) List<Member> findAll();

왜 EAGER는 비추천인가?

이유 설명

불필요한 데이터 조회 모든 연관 객체를 무조건 불러옴
쿼리 예측 어려움 내부적으로 조인 시점이 명확하지 않음
성능 저하 위험 연관 엔티티가 많을수록 느려짐
무한 루프 위험 양방향 관계 시 StackOverflow 발생 가능

실무에서는 기본적으로 LAZY 사용을 권장하며, 필요한 시점에만 fetch join이나 @EntityGraph로 직접 조회하는 방식이 좋습니다.


기억할 핵심 포인트

  • 기본은 LAZY로 설정하되,
  • N+1 문제가 생길 때만 fetch join으로 최적화
  • @ManyToOne(fetch = LAZY)는 실무에서 가장 안전한 기본 설계입니다.