🖥️ Back-end

JPA의 N+1 문제란?

승승장규 2025. 2. 21. 22:59

연관 관계가 설정된 entity를 조회할 경우에, 조회된 데이터 개수만큼 연관 관계의 조회 쿼리가 추가로 발생하는 현상이다. ex) 게시글과 댓글이 있는 경우, 게시글을 조회한 후 게시글마다 댓글을 조회하기 위한 추가 쿼리가 발생

 

# JPQL 구문

ex) findAll() == SELECT u FROM User u

Spring Data Jpa에서 제공하는 repository의 findAll() 메서드를 Global Fetch 전략을 즉시로딩으로 설정하고 실행하면 N+1 문제가 발생한다. 

JPQL은 Global Fetch 전략을 고려하지 않고 쿼리를 실행한다.

즉, 모든 user를 조회하는 쿼리를 실행 후, 즉시로딩 설정을 보고 연관관계에 있는 모든 entity를 조회하는 쿼리를 실행한다.

 

Global Fetch 전략을 지연 로딩으로 설정하고 findAll()를 실행하면 N+1 문제가 발생하지 않는다. 왜냐하면 연관관계에 있는 entity를 실제 객체 대신에 프록시 객체로 생성하여 주입하기 때문이다. 하지만 프록시 객체를 사용할 경우에 실제 데이터가 필요하여 조회하는 쿼리가 발생하고, N+1 문제가 발생할 수 있다.

 

이러한 문제를 해결하기 위해서는 fetch join, @EntityGraph를 사용해 볼 수 있다.

  • fetch join : 연관 관계에 있는 entity를 한 번에 즉시 로딩하는 구문.
SELECT DISTINCT u 
FROM User u 
LEFT JOIN FETCH u.orders
  • @EntityGraph : 비슷한 기능을 하며, 쿼리 메서드에 해당 어노테이션을 추가해서 사용 가능.
@EntityGraph(attributePaths = {"order"}, type = EntityGraphType.FETCH)
List<User> findAll();

 

이후 계속 학습하면서 추가 작업이 필요한 블로그입니다.🖐️🖐️