JPA N+1 문제 정리 & 해결 방법

김정규·2025년 10월 22일

✅ N+1 문제란?


JPA에서 연관 관계가 LAZY 로딩일 때,

1번의 메인 쿼리 실행 후, 연관된 엔티티를 N번 추가 조회하는 현상


💡 예시 상황

java
복사편집
List<Post> posts = postRepository.findAll();
for (Post post : posts) {
    System.out.println(post.getUser().getName()); // 작성자 정보 조회
}
  • PostUser@ManyToOne(fetch = LAZY) 관계
  • 게시글이 10개라면:
    • Post 조회 쿼리: 1번
    • User 조회 쿼리: 10번 → 총 11번 쿼리 발생 = N+1 문제

🍜 라면 비유로 이해하기

방식설명비유
❌ N+1 문제게시글은 한 번에 가져오고, 작성자는 하나씩 가져옴라면은 상자째 받지만, 브랜드 정보는 본사에 하나씩 전화해서 확인
✅ fetch join / EntityGraph게시글과 작성자를 한 번에 가져옴라면 10개와 브랜드 정보가 한 포장에 같이 들어 있음

🔧 해결 방법 1: Fetch Join

java
복사편집
@Query("SELECT p FROM Post p JOIN FETCH p.user")
List<Post> findAllWithUser();
  • JPQL에 JOIN FETCH 명시
  • PostUser한 번에 JOIN해서 가져옴
  • 쿼리 1번으로 N+1 해결

🔧 해결 방법 2: EntityGraph

java
복사편집
@EntityGraph(attributePaths = {"user"})
List<Post> findAll();
  • 메서드에 @EntityGraph 선언
  • 내부적으로 JOIN FETCH처럼 작동
  • JPQL 없이도 N+1 문제 해결

📊 쿼리 비교

방식쿼리 횟수설명
❌ 일반 LAZY1 + NPost 1번 + User N번
✅ Fetch Join1Post + User JOIN
✅ EntityGraph1Post + User JOIN (선언형)

⚖️ Fetch Join vs EntityGraph

항목Fetch JoinEntityGraph
사용 위치JPQL 쿼리 안메서드 위 어노테이션
조건 추가O (WHERE, ORDER 가능)X (정적 fetch만 가능)
복잡한 JOINO (정밀 제어 가능)X (과도한 JOIN 가능성)
간단한 fetch덜 직관적✅ 가장 깔끔

✅ 핵심 요약

N+1 문제 = "1번 가져오고, 연관된 것 N번 더 가져오는 비효율"

이를 해결하는 방법은:

  • 복잡한 조건이 있으면 → fetch join
  • 단순 조회라면 → EntityGraph
profile
기획과 설계 그리고 구현까지 하는 개발자가 되고 싶습니다

0개의 댓글