본문 바로가기
책벌레와 벌레 그 사이 어딘가/개념쌓기

[개념쌓기] N+1 문제

by veganwithbacon 2023. 1. 2.
반응형

FetchType에 대해 공부한 후 연장선 상에서 N+1문제까지 같이 공부했다.

정리를 글 하나에 같이 하기에는 내용이 너무 많은 것 같아, 가독성을 위해 분리했다.

 

  JPA & JPQL

N+1을 이해하기 위해서는 JPA와 JPQL에 대해서 알아야한다. 

그렇다면 JPA 와 JPQL는 무슨 관계일까

우선 JPQL은 엔티티를 조회하는 객체지향 쿼리이다. 따라서 대상 테이블에 쿼리를 날리는 것이 아니라 엔티티 그 자체에 쿼리를 날리는 것이다. 문법은 SQL과 유사하며 간결하다. JPQL은 결국 SQL로 변환되긴한다.

 

JPA에서 제공하는 메소드 호출만으로는 섬세하게 쿼리 작성이 어렵다는 점에서 JPQL이 탄생하게 되었다.

 

JPQL의 장점은 SQL을 추상화해서 특정 DB에 의존하지 않는다는 점이다.즉, 여러 DB에도 동일한 JPQL을 사용하면 DB에 접근이 가능하다.

 

그래서 JPA&JPQL 연관관계가 뭐냐고?

=> JPA를 위해 Repository를 만들고, JpaRepository를 상속받아 정의한 인터페이스 메소드를 DB와 연동해 사용한다

 

JPA는 이러한 JPQL을 읽고 분석해 SQL을 생성한 후 DB에 SQL을 실행한다.

 

여튼 N+1 알아보러 왔다가 왜 JPQL같은 소리를 하냐고 말하면, JPA&JPQL의 동작방식 때문에 N+1이 발생하기 때문이다.

또한 JPQL의 기능에 Fetch Join이 있는데, SQL의 성능 최적화에 보통 사용되기 때문이다.

 


1. JPA N+1문제

연관 관계에서 발생하는 문제로 연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터 수만큼 연관관계의 조회 쿼리가 추가 발생하여 데이터를 많이 읽어오게 되는데 이것을 N+1 문제라고 한다.

 

쉽게 말해 1번 조회할 것을 N개 종류의 데이터를 각각을 추가로 조회하여 N+1번  DB를 조회하게 되는 문제이다.

어긋난 연관관계로 인해 데이터 조회 시 1번만 조회할 것을 데이터 수만큼 +@로 조회하게 되는 것이다.

 

 

✅N+1의 발생 경우

JPA Repository를 통해 인터페이스 메소드를 호출할 때(Read 시)

 

언제?

1:N / N:1 관계를 가진 엔티티에서 조회할 때

 

어떤 상황에?

- JPA FetchType.EAGER의 경우 데이터를 조회할 때

- JPA FetchType.LAZY의  경우 데이터를 가져온 후 연관관계에서 하위 데이터를 추가적으로 조회하는 경우

- JPQL은 기본적으로 글로벌 Fetch 전략을 무시하고 JPQL만을 통해 SQL을 생성하는 경우

 

위 경우들이 종합적으로 발생할 때, N+1문제가 일어난다.

 

✔  EAGER(즉시 로딩)

1) JPQL을 통해 나온 SQL을 통해 데이터를 조회

2) JPA에서 Fetch 전략을 가지나, 해당 데이터의 연관 관계인 하위 엔티티들을 추가 조회

3) 2번 과정으로 인해 N+1문제가 발생

 

✔ LAZY(지연 로딩)

1) EAGER와 마찬가지로 JPQL을 통해 나온 SQL을 통해 데이터를 조회

2) JPA에서 Fetch 전략을 가지나, 지연로딩이기에 추가 조회는 가지지 않는다

3) 하위 엔티티를 가지게 되면 추가 조회하기 때문에 N+1문제가 발생한다

 

@XToOne의 경우 FetchType의 default값이 EAGER이지만 확실한 경우가 아닌 이상은 LAZY를 사용하는 것이 좋다.

그러나 LAZY라고 해도 N+1문제에서 자유로울 수는 없다는 것을 인지해야한다.

 

해결 방법으로는 Fetch Join과 @EntityGraph가 있으나 이해가 부족하기 때문에,

추가적으로 공부한 뒤에 업로드할 계획이다.

반응형

댓글