전체 조회일 경우, 여러개의 테이블을 Join 하여 응답해주게 됩니다.
Malt 의 경우 fetch 모드를 모두 Lazy 로 설정해두었지만, entity → dto 변환 과정에서 join 된 모든 테이블의 인자를 접근하게 됩니다. 이 때문에, “N + 1”문제가 발생하고 있었습니다.
<aside> 💡 N + 1 문제 연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터 갯수(n) 만큼 연관관계의 조회 쿼리가 추가로 발생하여 데이터를 읽어오는 현상
</aside>
N + 1 문제를 해결하는 방법을 여러가지가 있습니다.
JPQL 을 사용하여 연관된 모든 데이터에 대해 가져오는 방법입니다.
예를 들어, Model 과 ModelSetting 테이블 모두의 정보가 필요하다면 아래와 같이 사용하면된다.
그러면 실제 SQL 문에서는 Model 과 ModelSetting 이 inner join 구문으로 변경되어서 실행된다.
var models = jpaQueryFactory.selectFrom(model)
.leftJoin(model.modelSetting, modelSetting)
.fetchJoin()
하지만, 여러개의 엔티티에 대해 연관관계를 맺고 있어 fetch join 만으로 모든 데이터를 가지고 올 수 없었습니다. 또한, trainingSet 의 경우는 컬렉션의 크기가 커서 추후 데이터가 많아진다면 성능저하의 우려가 있습니다.
fetchJoin의 경우는 inner join 으로 대체가 되는데, @EntityGraph 는 left outer join 으로 대체가 됩니다.
이는 치명적 단점이 있는데. @EntityGraph로 데이터를 가져온다면, join 된 후 커진 데이터를 다 가져온 다음 메모리상에서 페이징 처리를 하게 된다는 것입니다.