위 프로젝트에서
댓글그리고 해당 댓글의좋아요수를 담당하였다.
@GetMapping("/articles/{articleId}/comment")
public ResponseEntity<Page<CommentResponseDto>> getComments(
@PathVariable Long articleId,
@RequestParam(required = false, defaultValue = "0") int page,
@RequestParam(required = false, defaultValue = "10") int size,
@CookieValue(value = "Authorization", required = false) String authorization) {
return ResponseEntity.status(HttpStatus.OK)
.body(commentService.getComments(articleId, page, size, authorization));
}
위와 같은 컨트롤러를 통해 Page 객체를 반환하는 컨트롤러를 구현하였다.
CookieValue 의Authorization키를 가지는 값(value) 를 통해 토큰을 가져오고 그 값을
service 단으로 옮긴다.
public Page<CommentResponseDto> getComments(Long articleId, int page, int size, String authorization) {
if (!articleRepository.existsById(articleId)) {
throw new IllegalArgumentException("Article id " + articleId + " not found");
}
Pageable pageable = PageRequest.of(page, size, Sort.by("updatedAt").descending());
Page<Comment> comments = commentRepository.findAllByArticleId(pageable, articleId);
Member author = findByEmail(authorization);
return comments.map(comment -> {
boolean isLiked = commentLikeRepository.existsByCommentIdAndMemberId(comment.getId(), author.getId());
return CommentResponseDto.of(comment, isLiked);
}
);
}
서비스 단의 코드로서, 기본적으로 수정일 기준 내림차순으로 Page객체에 담도록 하였다. Comment 엔티티를 CommentResponseDto 로 변환하도록 한 후 Page 객체로 반환하였다.

실제로 테스트를 해보니 아래와 같은 오류가 발생하였다.
에러 로그를 보니 아래와 같았다.

public static CommentResponseDto from(Comment comment) {
return CommentResponseDto.builder()
.id(comment.getId())
.articleId(comment.getArticle().getId())
.nickname(comment.getAuthor().getNickname())
.body(comment.getBody())
.createdAt(comment.getCreatedAt())
.updatedAt(comment.getUpdatedAt())
.build();
}
위 코드에서 닉네임을 얻어오는데 이때
getAuthor().getNickname()을 실행할때 위와 같은 오류가 발생하는 것이다.
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
@OnDelete(action = OnDeleteAction.CASCADE)
private Member author;
위 처럼 Comment 엔티티에서 Member 를 불러올때
LAZY즉 지연 로딩을 이용하기 때문에 위 오류가 발생할 수 있는 것이다.
1) 위 코드에서 fetch 타입을 Eager 로 변경하면 된다.
이렇게 되면 Comment 조회 시 Author 까지 모두 불러오게 된다.
=> BUT 이 방법은 권장되지 않는다. Comment 만 조회 하고 싶을 때 필요 없는 Author 까지 조회하게 되어 오버헤드가 발생할 수 있기 때문!!
2) 리포지토리에서 조인하기
public interface CommentRepository extends JpaRepository<Comment, Long> {
@Query("SELECT c FROM Comment c JOIN FETCH c.author WHERE c.article.id = :articleId")
Page<Comment> findAllByArticleId(Pageable pageable, @Param("articleId") Long articleId);
}
위 서비스에서 사용되었던 메서드인
findAllByArticleId를 선언 할때JPQL을 이용하여 한번에 join하여 가져올 수 있도록 하였다.

fetch 타입을 변경하면서 문제를 해결하였다.