게시글의 댓글 기능을 단순히 후기만을 올리는 것이 아니라 사용자 간의 질문 및 정보 공유 바탕으로 상호작용하게 하고 싶었다. 그러기 위해서는 대댓글 기능이 필요할것 같다는 생각이 들었고 이를 구현해 보았다.

먼저 위 같이 댓글의 관계를 그림으로 표현한 후, 이를 어떻게 구현할지 고민하다가 데이터베이스 수업시간에 배운 self join을 이용해 보기로 했다.
public class ArticleComment {
```
@Setter
private Long parentCommentId;
@ToString.Exclude
@OrderBy("createdAt ASC")
@OneToMany(mappedBy = "parentCommentId", cascade = CascadeType.ALL)
private Set<ArticleComment> childComments = new LinkedHashSet<>();
```
}
위와 같이 댓글과 대댓글을 1:N 관계라 생각하고 매핑해주었다.

comment 테이블을 살펴보면 위와 같이 댓글과 대댓글의 계층 상태가 표현 되어있지 않다. 최종적으로 view에 내려줄 때는 계층 상태로 내보내주어야 하기 때문에 converting logic이 필요하다.
private static Set<ArticleCommentResponse> organizeChildComments(Set<ArticleCommentDto> dtos) {
Map<Long, ArticleCommentResponse> map = dtos.stream()
.map(ArticleCommentResponse::from)
.collect(Collectors.toMap(ArticleCommentResponse::getId, Function.identity()));
map.values().stream()
.filter(ArticleCommentResponse::hasParentComment)
.forEach(comment -> {
ArticleCommentResponse parentComment = map.get(comment.getParentCommentId());
parentComment.getChildComments().add(comment);
});
return map.values().stream()
.filter(comment -> !comment.hasParentComment())
.collect(Collectors.toCollection(() ->
new TreeSet<>(Comparator
.comparing(ArticleCommentResponse::getCreatedAt)
.reversed()
.thenComparingLong(ArticleCommentResponse::getId)
)
));
}
1. 데이터에 쉽게 접근하기 위해 dto를 response로 mapping한 후 key는 id, value는 response로 변환시켜준다.
2. 부모가 있는 댓글을 추출한 후, id를 통해 부모 댓글을 구한 뒤 자식 Set에 추가해준다.
3. 반환하기 전에 대댓글에 정렬 순서를 설정하는 작업이 필요하다.
4. map.values().stream().filter() 를 통해 자식 댓글만 뽑은 뒤,
5. Comparator에서 첫번째 비교 대상은 생성일자를 기준으로 내림차순 정렬하고, 시간이 동일할 경우를 대비하여 댓글에 id 값을 기준으로 오름차순 정렬한다.
'부트모아' 카테고리의 다른 글
[V1] 수정기능 구현시 쿼리수 줄이기 (0) | 2024.09.28 |
---|---|
[V1] 사용자 인증 구현 (1) | 2024.09.28 |
[V2] JPA는 sql injection에 무조건 안전한가? (0) | 2024.09.28 |
[V2] 부트모아 사이트 XSS 필터링 (1) | 2024.09.28 |
[V2] Spring Security CSRF (1) | 2024.09.28 |