N+1 문제 해결
문제 상황
- 인스타그램 클론 코딩 중
- 메인 페이지에서 댓글을 좋아요 순으로 2개까지 표시해야해서 jpa에서 제공하는 Top2를 사용
List<Comment> comments = commentRepository.findTop2ByCardOrderByLikeCountDesc(card);
- 이를 이용해 메인 페이지를 가져올 때 쿼리가 굉장히 많이 생김
시도한 해결 수단
- 쿼리 dsl을 이용해 해당 기능을 구현하려고 하였음
->써먹기가 너무 어려워서 실패
- JPQL을 사용해 쿼리 횟수를 줄일 수 있었음 (50+ -> 3)
->그럼에도 필요없는 쿼리가 더 나왔음
실제로 어떤 식으로 해결했는지
JPQL과 좋아요 정렬/필터링 로직 변경 및 imgUrlList를 List->Set 형태로 변환
1. JPQL
@Query("select distinct m from Card m join fetch m.member join fetch m.imgUrlList left join fetch m.commentListDto order by m.createdAt DESC ")
2. 좋아요 정렬 및 필터링 로직 변경
List<Comment> comments = card.getCommentListDto();
comments.sort(new LikeCountSort());
int cnt=0;
for (Comment comment : comments) {
commentList.add(
CommentResponseDto.builder()
.id(comment.getId())
.profilePhoto(comment.getMember().getProfilePhoto())
.nickname(comment.getMember().getNickname())
.content(comment.getContent())
.likeCount(comment.getLikeCount())
.build());
cnt++;
if (cnt>=2) break;
}
- Top2 형태로 매번 쿼리를 하는 것에서 카드에 매핑된 댓글 리스트를 받아온 후 거기서 처리하도록 변경
- 이후 상위 2개 까지만 필터링 하기 위해 cnt를 이용함
3. imgUrlList를 Set으로 형변환
- 위에서 본 JPQL과 같이 join fetch를 하기 위해서는 Set형태의 데이터가 필요했음