220823 N+1 문제 해결

Jongleee·2022년 8월 23일
1

TIL

목록 보기
35/576

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형태의 데이터가 필요했음

0개의 댓글