HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🌚
[New] 우기팀
/
득윤
득윤
/
➕
JPA N+1 문제
/
N + 1 문제

N + 1 문제

조회 쿼리에 연관된 필드를 채우기 위해 첫 번째 쿼리 이후에 연관된 fk에 대해서 N개의 쿼리가 추가로 발생하는 문제
 
먼저 N+1 문제를 터트려 보겠습니다.
위와 같은 데이터가 있을 때 사용자를 조회해봅시다!

즉시로딩 테스트

@ManyToOne(fetch = EAGER) private Team team;
@Test void 사용자_조회() { String jpql = "select u from User u"; List<User> resultList = em.createQuery(jpql, User.class).getResultList(); System.out.println("==========================="); for (User user : resultList) { System.out.println("username : " + user.getUsername()); } System.out.println("==========================="); for (User user : resultList) { System.out.println("username = " + user.getUsername()); Team team = user.getTeam(); System.out.println(team.getClass()); System.out.println("user teamName = " + team.getName()); System.out.println(); } }
notion image
=========================== username : 짱구 username : 유리 username : 치타 username : 코난 =========================== username = 짱구 class com.study.jpql.domain.Team user teamName = 해바라기반 username = 유리 class com.study.jpql.domain.Team user teamName = 해바라기반 username = 치타 class com.study.jpql.domain.Team user teamName = 장미반 username = 코난 class com.study.jpql.domain.Team user teamName = 어린이 탐정단
미리 다 땡겨와서 채워 놓는 Eager Loading
사용자만 조회 했는데 사용자의 팀 정보를 채우기 위해 jpa가 즉시 3개의 팀 조회 쿼리를 발생 시켰습니다.

지연 로딩 테스트

같은 테스트에 대해서 fetch 설정만 lazy로 변경하면 N+1문제가 사라질까요??
@ManyToOne(fetch = LAZY) private Team team;
notion image
요청한 쿼리 단 하나만을 잘 실행 했습니다.
이를 통해 사용자의 이름정보 만을 조회 할 때는 아무런 추가 쿼리가 나가지 않았습니다.
=========================== username : 짱구 username : 유리 username : 치타 username : 코난
하지만 사용자의 팀 정보를 조회 할 때는 새로운 팀 정보가 발견 될 때마다 db에 쿼리를 발생 시켜 팀 정보를 조회 합니다. 결과 적으로 루프 시에 3개의 팀 조회 쿼리가 발생합니다.
=========================== username = 짱구 class com.study.jpql.domain.Team$HibernateProxy$ghrxMDXg Hibernate: select team0_.id as id1_1_0_, team0_.teamname as teamname2_1_0_ from team team0_ where team0_.id=? user teamName = 해바라기반 username = 유리 class com.study.jpql.domain.Team$HibernateProxy$ghrxMDXg user teamName = 해바라기반 username = 치타 class com.study.jpql.domain.Team$HibernateProxy$ghrxMDXg Hibernate: select team0_.id as id1_1_0_, team0_.teamname as teamname2_1_0_ from team team0_ where team0_.id=? user teamName = 장미반 username = 코난 class com.study.jpql.domain.Team$HibernateProxy$ghrxMDXg Hibernate: select team0_.id as id1_1_0_, team0_.teamname as teamname2_1_0_ from team team0_ where team0_.id=? user teamName = 어린이 탐정단
프록시를 채워 두었다가 호출을 할 때에 느긋하게 채워 놓는 Lazy Loading
 
즉시로딩과 지연로딩 둘 모두 N+1 문제에서 자유롭지 않습니다.
이를 해결하기 위해서는 fetch join를 활용해야합니다.