# 문제 상황
.offset 및 .limit로 페이지 매김을 수행하는 querydsl 쿼리를 작성했습니다. 페이징 가능한 개체를 사용합니다. N+1 문제를 해결하기 위해 연관된 엔티티는 fetchJoined입니다.
List<FarmLog> farmLogs = jpaQueryFactory
.selectFrom(farmLog)
.leftJoin(farmLog.likers).fetchJoin() // 좋아요한 사람들 fetch join
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.orderBy(farmLog.createdAt.desc())
.fetch();
쿼리 결과가 나오면?
# 컬렉션 가져오기로 지정된 firstResult/maxResults; 메모리의 응용 프로그램
경고가 나타납니다.

일대다 관계가 여러 개 있는 상황에서 페치 조인과 유사하게 전체 쿼리 결과를 메모리에 로드한 다음 페이지 매김을 수행하기 때문으로 보입니다. 최대 절전 모드에서 쿼리 문을 보면 offset 또는 limit 키워드가 전혀 표시되지 않습니다.

fetchJoin이 있는 경우 쿼리 매개 변수는 Hibernate 쿼리 문에서 null 값으로 입력된 것으로 나타납니다.
# 해결 방법: 쿼리 분할
// limit 절만 사용할 query 따로 뺌
List<Long> farmLogIds = jpaQueryFactory.select(farmLog.farmLogId)
.from(farmLog)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.orderBy(farmLog.createdAt.desc())
.fetch();
// fetchJoin
List<FarmLog> farmLogs = jpaQueryFactory.selectFrom(farmLog)
.leftJoin(farmLog.likers).fetchJoin()
.where(farmLog.farmLogId.in(farmLogIds))
.fetch();
1) pagination을 적용하여 entity id만 추출하는 쿼리
2) 해당 ID 개체 및 fetchJoin 가져오기 쿼리
두 개를 나눠서 얻은 결과다.
실제로 동일한 요청에 대해 동일한 쿼리가 두 번 발행됩니다.
쿼리 2개 던지기 vs. N+1 실행
무엇을 포기하느냐에 달려 있는 것 같습니다.