보라코딩
JPA N+1 문제 본문
Lazy 로딩을 사용할 때 N+1 문제가 발생하지 않는 이유
Lazy Loading (지연 로딩) 동작 원리
- 지연 로딩 설정: JPA에서는 연관 관계를 지연 로딩으로 설정할 수 있습니다. 이는 연관된 엔티티를 실제로 사용할 때까지 데이터베이스에서 가져오지 않고, 필요할 때 로딩하는 방식입니다.
- Proxy 객체 생성: Lazy 로딩이 설정된 연관 관계는 실제 엔티티 대신 프록시(proxy) 객체를 반환합니다. 프록시 객체는 실제 엔티티를 대신하여 필요한 시점에 데이터베이스에서 엔티티를 로딩하는 역할을 합니다.
- 첫 번째 쿼리 실행: 예를 들어, 부모 엔티티를 조회할 때 연관된 자식 엔티티는 초기에 로딩되지 않고, 대신에 해당 자식 엔티티들에 대한 데이터베이스 쿼리가 발생하지 않습니다. 대신, 부모 엔티티의 필드에는 자식 엔티티에 대한 참조(프록시)가 설정됩니다.
- 자식 엔티티 접근 시 로딩: 실제로 자식 엔티티를 사용하려 할 때(예: 자식 엔티티의 필드를 조회하거나 메서드를 호출할 때), 프록시 객체는 데이터베이스에 추가 쿼리를 실행하여 실제 자식 엔티티를 로딩합니다. 이때 N+1 문제가 발생하지 않도록 자식 엔티티들을 한 번에 모아서 로딩할 수 있습니다.
N+1 문제 예제
- 부모 엔티티 목록 조회: 예를 들어, 부모 엔티티가 10개 있다고 가정합니다.
- N+1 쿼리 문제: Lazy 로딩을 사용하지 않고, 부모 엔티티 목록을 조회한 후 각 부모 엔티티마다 연관된 자식 엔티티를 추가로 조회하려고 할 때, 각 부모 엔티티마다 데이터베이스 쿼리가 추가로 발생합니다. 따라서 부모 엔티티 조회 1번 + 자식 엔티티 조회 N번으로 총 N+1 개의 쿼리가 발생하게 됩니다.
Lazy 로딩 사용 시 N+1 문제 해결
- 초기 조회 시점: Lazy 로딩을 사용하면 처음에는 연관된 자식 엔티티들을 모두 로딩하지 않고, 프록시 객체를 부모 엔티티에 설정합니다. 이로 인해 처음에는 추가적인 쿼리가 발생하지 않습니다.
- 실제 사용 시점: 부모 엔티티에서 실제로 자식 엔티티의 필드나 메서드에 접근할 때, JPA는 프록시 객체를 통해 실제 데이터베이스 쿼리를 실행하여 필요한 자식 엔티티를 로딩합니다. 이때 자식 엔티티들을 한 번에 모아서 로딩할 수 있어 N+1 문제를 방지할 수 있습니다.
결론
Lazy 로딩을 사용하면 연관된 엔티티를 초기에 모두 로딩하지 않고, 필요할 때 데이터베이스에서 추가 쿼리를 실행하여 로딩합니다. 이 방식은 N+1 문제를 피할 수 있는 주요 전략 중 하나입니다. 따라서 애플리케이션에서 성능 최적화를 위해 JPA 엔티티 관계를 설계할 때 Lazy 로딩을 적절히 활용하는 것이 중요합니다.
'코딩 > Spring' 카테고리의 다른 글
최근에 본 좋은 글들 (예외처리/일급컬렉션/API 디자인 - URI) (1) | 2024.12.02 |
---|---|
try-with-resources, CompletableFuture, Optional (0) | 2024.07.02 |
AOP, 프록시, Transactional (0) | 2024.06.20 |
MapStruct (0) | 2024.04.04 |
Spring Security Config 버전별 정보 (0) | 2024.03.03 |