N+1 문제 마스터하기
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
웹 개발
대상자
- Java/JPA 개발자 (중급 이상)
- ORM 성능 최적화에 관심 있는 개발자
- 데이터베이스 쿼리 패턴 분석 필요자
핵심 요약
- N+1 문제는 JPA의 FetchType.LAZY 설정으로 인해 N개의 추가 쿼리가 생성되는 성능 이슈
- 카르테시안 곱은 JOIN 대신 복수 쿼리로 인해 결과 집합의 곱집합이 발생하는 현상
- Fetch 전략(JOIN FETCH, EAGER, SUBSELECT)과 쿼리 힌트(@BatchSize)를 통해 상황별 최적화 적용 필요
섹션별 세부 요약
1. N+1 문제의 근본 원인
- FetchType.LAZY 설정 시 N+1 쿼리 발생 (1개 기본 쿼리 + N개 연관 쿼리)
- 카르테시안 곱은 JOIN 대신 복수 쿼리로 인해 결과 집합의 곱집합이 생성
- JPA의 1차 캐시가 아닌 DB 쿼리 패턴에 초점 맞추어야 함
2. 실전 시나리오별 최적화 접근
- 1:N 관계 → JOIN FETCH 사용하여 1개 쿼리로 해결
- N:N 관계 → @BatchSize 또는 JOIN FETCH 적용
- 복잡한 연관 관계 → @EntityGraph 또는 NamedQuery 활용
- 대량 데이터 처리 → 페이징 + @BatchSize 적용
3. 실전 해결책 및 예시
- Fetch 전략 변경 →
@OneToMany(fetch = FetchType.LAZY)
→@OneToMany(fetch = FetchType.EAGER)
- 쿼리 힌트 적용 →
@BatchSize(size = 20)
로 반복 쿼리 최소화 - JPQL 직접 활용 →
SELECT u FROM User u JOIN FETCH u.posts
로 JOIN FETCH 명시 - Querydsl 활용 →
user.posts.size().gt(0)
로 JOIN 조건 명시
결론
- JOIN FETCH를 활용해 N+1 쿼리 제거, @BatchSize로 카르테시안 곱 방지
- Fetch 전략과 쿼리 힌트는 데이터 모델과 사용 시나리오에 맞게 조정해야 함
- Query Profiling 도구(e.g., JPA Buddy, Hibernate Statistics)로 쿼리 패턴 분석 후 최적화 적용