JPA의 N+1 문제

김민규·2026년 10월 9일

겅부

목록 보기
13/18

N+1은 무엇인가?

처음 실행한 SQL 외에 연관 데이터를 가져오기 위해 추가 SQL이 실행되는 문제이다.

  • 예를 들어 게시글 100개를 조회하고, 각 게시글의 작성자를 확인한다고 가정하자.
    게시글 조회: SQL 1회
    각 게시글의 작성자 조회: 최대 SQL 100회
    총 SQL 실행 횟수: 최대 101회
  • 실제로는 1+N에 더 가까운 느낌이다.

발생 원인

연관 엔티티를 조회하는 시점 때문이다.

List<Post> posts = postRepository.findAll();

for (Post post : posts) {
    System.out.println(post.getMember().getName());
}
// post의 member는 FetchType.LAZY
  • 위 코드에서 처음 findAll은 member를 가져오지 않는다.
  • 이후 for문이 getMember를 호출할 때 posts의 크기만큼 sql이 실행된다.
    (영속성 컨테이너에 이미 로딩된 member가 있을 경우 sql의 실행 횟수가 줄어들 수 있다)

해결법

Fetch Join

JPQL에서 연관 데이터를 한 번의 SQL로 가져온다.

@Query("""
    SELECT p
    FROM Post p
    JOIN FETCH p.member
    """)
List<Post> findAllPosts();

@EntityGraph

어노테이션을 통해 함께 조회할 연관 엔티티를 선언한다.

@EntityGraph(attributePaths = {"member"})
List<Post> findAll();

DTO

DTO를 통해 실제로 필요한 데이터만 조회한다.

@Query("""
    SELECT new com.example.dto.PostResponse(
        p.id,
        p.title,
        m.name
    )
    FROM Post p
    JOIN p.member m
    """)
List<PostResponse> findPostResponses();

0개의 댓글