본문 바로가기
JPA Study

N+1 문제 해결방법

by xogns93 2024. 9. 25.

N+1 문제를 해결하는 두 가지 대표적인 방법, 페치 조인(Fetch Join)배치 처리

 

1. 페치 조인(Fetch Join)

페치 조인은 JPQL이나 Hibernate에서 사용하는 기법으로, 연관된 엔티티를 함께 조회하여 N+1 문제를 해결하는 방법입니다. 기본적으로 JPA는 연관된 엔티티를 조회할 때 지연 로딩(Lazy Loading)을 사용하여 필요할 때마다 쿼리를 추가로 발생시키는데, 이때 N+1 문제가 발생할 수 있습니다.

페치 조인의 원리

페치 조인을 사용하면 연관된 엔티티를 한 번에 조인하여 한 번의 쿼리로 조회할 수 있습니다. 즉, 지연 로딩 대신 즉시 로딩(Eager Loading)을 사용하여 연관된 데이터를 한 번에 가져오는 방식입니다.

페치 조인 예시

예를 들어, 회원과 팀(1:N 관계)이 있다고 가정할 때, N+1 문제가 발생할 수 있습니다. 이를 해결하기 위해 페치 조인을 사용할 수 있습니다.

SELECT m FROM Member m JOIN FETCH m.team

이 쿼리는 회원(Member)과 팀(Team)을 한 번의 쿼리로 조인하여 가져옵니다. 즉, 회원과 연관된 팀을 조회할 때 추가적인 쿼리가 발생하지 않기 때문에 N+1 문제가 해결됩니다.

페치 조인의 장점

  • 성능 향상: 연관된 엔티티를 한 번에 조회하므로 성능이 향상됩니다.
  • 간단한 쿼리 작성: 추가적인 설정 없이 JPQL에서 쉽게 사용할 수 있습니다.

페치 조인의 단점

  • 페이징 불가능: 페치 조인을 사용할 경우, 일부 데이터베이스에서 페이징 처리가 불가능하거나 성능 문제가 발생할 수 있습니다.
  • 복잡한 연관 관계에서 사용 시 주의: 여러 연관 엔티티를 페치 조인할 경우, 데이터 중복이 발생할 수 있으므로 사용에 주의해야 합니다.

2. 배치 처리(Batch Processing)

배치 처리는 JPA의 설정을 통해 한 번에 여러 개의 엔티티를 조회할 수 있도록 쿼리를 최적화하는 방식입니다. N+1 문제는 기본적으로 하나의 부모 엔티티를 조회한 후 연관된 자식 엔티티를 개별 쿼리로 조회하면서 발생하는 문제인데, 배치 처리를 사용하면 이러한 쿼리들을 일괄 처리로 변환하여 성능을 개선할 수 있습니다.

배치 처리의 원리

배치 처리를 사용하면 연관된 엔티티들을 한 번에 여러 개씩 조회합니다. 이를 통해 지연 로딩이 발생할 때마다 추가로 발생하는 쿼리의 수를 줄일 수 있습니다.

배치 처리 설정 예시

Hibernate에서 배치 크기를 설정하는 방법입니다.

<property name="hibernate.default_batch_fetch_size" value="100"/>

이 설정을 추가하면 연관된 엔티티를 조회할 때 최대 100개의 데이터를 한 번에 가져옵니다. 즉, 개별적으로 쿼리가 발생하는 대신, 100개의 데이터를 묶어서 조회하는 방식으로 성능을 향상시킬 수 있습니다.

배치 처리의 장점

  • 효율적인 쿼리 처리: 연관된 엔티티를 일괄적으로 조회하므로 쿼리 발생 횟수를 줄여 성능을 개선합니다.
  • 페이징과 함께 사용 가능: 페치 조인과 달리 배치 처리는 페이징과 함께 사용할 수 있습니다.

배치 처리의 단점

  • 최적의 배치 크기 설정이 필요: 배치 크기를 잘못 설정하면 성능이 오히려 저하될 수 있습니다. 상황에 맞는 적절한 배치 크기를 설정하는 것이 중요합니다.

결론

  • 페치 조인: 한 번의 쿼리로 연관된 엔티티를 함께 조회하는 방식으로 N+1 문제를 해결하며, 간단하고 성능 개선 효과가 크지만, 페이징이 어려울 수 있다는 단점이 있습니다.
  • 배치 처리: 설정을 통해 연관된 엔티티들을 일괄적으로 조회하여 N+1 문제를 해결하는 방식으로, 페이징과 함께 사용할 수 있는 장점이 있지만, 배치 크기 설정이 중요합니다.

두 방법은 상황에 따라 적절히 선택해서 사용해야 합니다. 페이징이 필요하지 않다면 페치 조인이 간편하고 성능 개선에 좋고, 페이징이 필요하다면 배치 처리 방식이 더 적합합니다.