즉시 로딩

findById 처럼 단일 객체를 조회하는 경우에는 JPA 가 내부적으로 join 문을 사용해 최적화를 진행한다 하지만 그 외의 쿼리문을 실행시킬 경우 문제가 발생한다 이는 JPQL 문제인데, JPQL 은 쿼리문 자체를 해석하여 실행한다 예를 들어 findAll 을 호출할 경우 메인 객체 리스트를 모두 조회한 후, 즉시 로딩으로 엮여있는 하위 객체 리스트들을 조회한다 즉, N+1 문제가 발생하게 된다

→ JPA 가 내부적으로 처리해주는 과정이기 때문에 커스텀하기 어렵다 지연 로딩을 사용하자

지연 로딩

지연 로딩을 걸어두어 하위 객체들은 프록시 객체로 대체되었지만 결국 이후에 게터를 호출하면 실제 객체를 조회하기 위한 쿼리문이 호출된다 즉, N+1 문제가 발생한다

fetch join 사용

일반적인 join 쿼리문 사용(JPQL)

직접 조인을 사용해서 조회하더라도 지연 로딩으로 묶여있으면 프록시 객체를 조회한다 결국 문제는 해결되지 않는다

fetch join 사용 → 문제 해결!

페치 조인이란 지연 로딩 관계로 묶여있을 때 프록시 객체가 아닌 실제 객체로 조회하는 조인이다 말 그대로 페치 조인을 사용하여 N+1 문제를 해결할 수 있다

fetch join 사용(JPQL+@EntityGraph) → 문제 해결!

@EntityGraph 어노테이션을 이용하여 JPQL 에서 설정해야 하는 정보를 줄일 수 있다

fetch join 사용 시 유의할 점

Pagination limit 안걸림ㅠㅠ

fetch join 을 이용하여 findById 이외의 다양한 쿼리문에 대해 조치를 해두었지만 페이징 처리를 할 경우 다시 문제가 발생한다

결국에는 조인을 사용하여 가져온 정보이기 때문에 메인 객체에 대한 정보가 중복적으로 조회되는 형태로 가져와진다 여기에서 페이징 처리를 한다고 하더라도 원하는 결과값과는 다른 결과를 반환한다 이러한 현상을 방지하기 위해 JPA 는 데이터베이스에 저장되어 있는 모든 정보를 불러온 후 인메모리에서 페이징 처리를 진행한다 → 메모리 낭비 발생

  1. 의존 관계를 @ManyToOne 관계로 바꾸어보자

중복적인 결과가 나올거라는 경우의 수를 지웠기 때문에 limit 절이 동작한다

  1. Batch size