개요
JPA를 사용한 프로젝트를 진행하다보면, DB 조회 시 연관 관계에 있는 하위 엔티티들을 한꺼번에 가져오지 않고, 각각의 하위 엔티티를 개별적으로 조회하면서 불필요한 추가 쿼리가 발생하는 문제인 N+1 문제가 자주 발생합니다.
이러한 N + 1 문제를 해결하는 방법에는 @EntityGraph, @BatchSize , Fetch Join등 여러가지가 있습니다. 그런데 왜 많은 개발자들이 여러가지 방법 중 Fetch Join을 사용하는지에 대해서 정리하고자 합니다.
왜 Fetch Join인가❓
1. 즉시 로딩과 명시적 제어
Fetch Join은 JPQL 쿼리에서 명시적으로 사용되기 때문에, 어떤 연관 데이터를 즉시 로딩할지 명확하게 정의할 수 있습니다. 이는 @EntityGraph나 @BatchSize와 같은 방법들에 비해 제어가 더 직관적입니다.
SELECT h FROM HubPath h JOIN FETCH h.departureHub JOIN FETCH h.arrivalHub
위와 같이 쿼리 안에서 어떤 연관 데이터를 페치 조인할지를 명확하게 지정할 수 있습니다. 따라서 원하는 시점에 원하는 데이터를 가져올 수 있는 장점이 있습니다.
2. N+1 문제의 확실한 해결
Fetch Join은 연관된 엔티티들을 한 번의 쿼리로 모두 가져오기 때문에 N+1 문제를 확실하게 해결합니다. 일반적으로 복잡한 엔티티 관계에서 즉각적으로 연관된 엔티티들을 가져올 수 있는 가장 간단한 방법입니다.
3. 유연성
Fetch Join은 여러 관계를 동시에 fetch할 수 있어, 복잡한 엔티티 관계에서도 유연하게 사용할 수 있습니다. 필요한 관계만 명시적으로 포함하거나 제외할 수 있어 성능 최적화에 도움이 됩니다.
예를 들어, @EntityGraph는 한정된 범위에서만 사용 할 수 있는 반면, Fetch Join은 복잡한 관계를 다루는 JPQL 쿼리에서 더 폭넓게 활용할 수 있습니다.
4. SQL 쿼리의 투명성
Fetch Join을 사용하면 결국 생성되는 SQL 쿼리를 명확히 볼 수 있습니다. 이는 성능 최적화를 할 때 매우 유용한데, 개발자는 JPQL 쿼리에서 직접 어떤 테이블들이 조인되고 어떤 데이터를 가져오는지 직관적으로 파악할 수 있습니다.
5. @EntityGraph & @BatchSize의 한계
- @EntityGraph는 선언적이고 간편하지만, 복잡한 쿼리에서는 사용이 제한적입니다. 특히, 조건부로 연관 엔티티를 가져와야 할 때는 Fetch Join만큼 유연하지 않습니다.
- @BatchSize는 N+1 문제를 완화해줄 수는 있지만, Fetch Join처럼
한 번의 쿼리로 모든 연관 데이터를 가져오는 것이 아니라, 다수의 SQL 쿼리를 병렬로 처리하여 성능을 향상시키는 방식입니다. 이 경우 쿼리 수가 여전히 줄어들지 않을 수 있습니다.
결론적으로 Fetch Join은 제어가 명확하고 직관적이며, 복잡한 엔티티 관계에서도 유연하게 적용 가능하다는 장점 때문에 많이 사용됩니다.
또한 N+1 문제를 해결하는 데 가장 직접적이고 효율적인 방법이기 때문에, 대부분의 경우 성능 최적화를 위해 Fetch Join이 선호되는 것입니다.
'TIL,일일 회고' 카테고리의 다른 글
[TIL, 일일 회고] 2024.11.07 - DDD에서 도메인 서비스와 애플리케이션 서비스를 나누는 이유 (2) | 2024.11.07 |
---|---|
[TIL, 일일 회고] 2024.11.06 - pandas란 무엇일까❓ (1) | 2024.11.06 |
[TIL, 일일 회고] 2024.11.04 - 코딩 관련 기초 지식 (등차수열) (0) | 2024.11.04 |
[TIL, 일일 회고] 2024.11.04 - 게시판 좋아요 기능 동시성 문제 해결 및 고도화된 부하 테스트 (0) | 2024.11.04 |
[TIL, 일일 회고] 2024.11.03 - GlowGrow 프로젝트: 쿠폰 유형에 따른 맞춤 정산 로직 도입기 (2) | 2024.11.03 |