게시판 상세조회 성능 개선
초기에는 게시판 상세조회에서 게시글, 게시글 이미지, 댓글, 대댓글, 게시글 좋아요, 댓글 좋아요, 대댓글 좋아요
를 한 번에 조회하도록 구현하였습니다.
그 결과, 다음과 같이 게시글을 조회할 때 약 143ms
의 시간이 소요되었으며, 추가적인 select 쿼리들이 발생하는 n+1 문제
가 발생하였습니다.
위와 같은 문제를 개선하기 위해, 다음과 같이 시스템 기능을 재정의하였습니다.
- 하나의 게시글을 조회할 때, 초기에는 10개의 댓글만을 보이게 한다.
- 사용자가 추가적으로 댓글 정보를 원할 때, 10개씩 페이징하여 보여준다. (대댓글에 대해서도 댓글과 동일하게 구현한다.)
게시글, 댓글, 대댓글
좋아요 테이블은 연관관계를 매핑하지 않고, 각각의 엔티티에likeCnt
칼럼을 두는반정규화
를 적용한다.
public FreePostReadRes read(Long idx) {
FreePost freePost = freePostRepository.findByIdWithAuthor(idx).orElseThrow(() -> new BaseException(BaseResponseStatus.COMMUNITY_BOARD_NOT_FOUND));
List<FreeCommentReadRes> freeComments = freeCommentService.findAllWithPage(idx, 0, 10);
List<String> imageUrls = freePost.getImages().stream()
.map((url) -> url.getUrl())
.collect(Collectors.toList());
return FreePostReadRes.builder()
.idx(freePost.getIdx())
.title(freePost.getTitle())
.content(freePost.getContent())
.author(freePost.getUser().getNickname())
.imageUrlList(imageUrls)
.created_at(LocalDateTime.now())
.likeCount(freePost.getLikesCount())
.freeCommentList(freeComments)
.build();
}
댓글 & 대댓글 조회 성능 개선
- 댓글과 대댓글은 조회 성능 개선 방법이 동일하기에, 대댓글에 대한 설명과 사진첨부는 생략합니다.
- 조회 성능 문제 발생 : 게시글의 댓글 10개를 조회할 때
❌ 성능 개선 전
→ 다음과 같이 게시글의 댓글을 조회할 때, n+1 문제가 발생하였습니다.
[해결 방법] Join Fetch 와 반정규화 이용
✅ 성능 개선 후
댓글을 조회할 때, toOne 관계에 있는 user(작성자)는 jpql을 사용한 Join Fetch를 진행하였습니다. 또한, FreePost, FreeComment, FreeRecomment 테이블과 각각의 likes 테이블 사이의 연관관계를 제거하고,likeCnt 칼럼을 추가하는 반정규화를 진행하였습니다.
반정규화하는 과정 중, likeCnt를 증가하고 감소하는 작업에서 동시성 문제가 발생하였고,낙관적 락
을 이용해 동시성 문제를 해결할 수 있었습니다.
❓왜 낙관적 락을 사용했나요
boot_up 시스템에서는 좋아요 기능
이 실패
했다고 해서, 치명적인 오류가 발생하지 않습니다. 낙관적락으로도 충분히 조회 성능을 개선시킬 수 있습니다.
📌 [최종] 최적화한 결과
게시글의 댓글을 조회할 때, 발생했던 N+1 문제를 해결하였고, 게시글 상세조회 수행시간을 약 83ms
로 단축시켰습니다.
select
fc1_0.idx,
fc1_0.content,
fc1_0.created_at,
fc1_0.post_idx,
fc1_0.likes_count,
u1_0.idx,
u1_0.address,
u1_0.course_num,
u1_0.created_at,
u1_0.email,
u1_0.enabled,
u1_0.name,
u1_0.nickname,
u1_0.password,
u1_0.phone_number,
u1_0.role,
u1_0.social_logined,
u1_0.status,
u1_0.team_idx,
u1_0.updated_at,
fc1_0.version
from
free_comment fc1_0
join
user u1_0
on u1_0.idx=fc1_0.user_idx
where
fc1_0.post_idx=?
order by
fc1_0.idx desc
limit
?, ?
'Project' 카테고리의 다른 글
[Project] Redis를 이용하여 대기열 구현하기 (0) | 2024.10.28 |
---|---|
[Boot-up] 로그인 Refresh Token 구현 (0) | 2024.08.19 |