프로젝트 (Java)/예약마켓

[프로젝트] 18. 게시물 댓글 작성 및 삭제 기능

hihyuk 2024. 1. 26. 10:07

프로젝트에 게시물 댓글 작성 및 삭제 기능은 사용자 간의 상호작용을 촉진하고, 커뮤니티 내에서 의견을 공유할 수 있는 중요한 기능입니다. 이 기능을 통해 사용자는 게시물에 대해 의견을 남기거나, 자신의 댓글을 삭제할 수 있습니다. 

 

PostController 수정

PostController에 댓글 추가 및 삭제를 위한 엔드포인트를 추가합니다. 사용자 ID는 토큰 컨텍스트에서 추출합니다.

    @PostMapping("/comment/{post-id}")
    public List<CommentDto> addComment(
            @PathVariable(value = "post-id") Long postId,
            @RequestBody CreateCommentDto commentDto
    ) {
        TokenContext context = TokenContextHolder.getContext();
        Long userId = context.getUserId();
        return postService.addComment(userId, postId, commentDto);
    }

    @DeleteMapping("/comment/{post-id}/{comment-id}")
    public void removeComment(
            @PathVariable(value = "post-id") Long postId,
            @PathVariable(value = "comment-id") Long commentId
    ) {
        TokenContext context = TokenContextHolder.getContext();
        Long userId = context.getUserId();
        postService.removeComment(userId, postId, commentId);
    }

 

Comment와 Post 엔티티 수정

CommentPost 엔티티에 댓글을 추가하고 삭제하는 메소드를 구현하여, 엔티티 간의 관계를 관리합니다.

Comment

    public void setPost(Post post) {
        if (this.post != null) {
            this.post.getComments().remove(this);
        }
        this.post = post;

        if (!post.getComments().contains(this)) {
            post.getComments().add(this);
        }
    }

Post

    public void addComment(Comment comment) {
        this.comments.add(comment);
        if(comment.getPost() != this) {
            comment.setPost(this);
        }
    }

    public void removeComment(Comment comment, Long userId) {
        if(comment.getWriter().getId() != userId) {
            throw new BadRequestException("댓글 삭제는 댓글 작성자만 가능합니다.");
        }

        Iterator<Comment> iterator = this.comments.iterator();
        while (iterator.hasNext()) {
            Comment e = iterator.next();
            if (comment.equals(e)) {
                iterator.remove();
            }
        }
    }

 

CreateCommentDto 구현

CreateCommentDto는 클라이언트로부터 받은 댓글 생성 요청 데이터를 담는 객체입니다. 댓글 내용을 필드로 포함합니다.

@Getter
public class CreateCommentDto {
    private String content;

    public Comment toEntity(User writer) {
        return Comment.builder()
                .writer(writer)
                .content(content)
                .build();
    }
}

 

PostService 수정

PostService에서는 댓글 추가 및 삭제 로직을 구현합니다. 댓글 추가 시 해당 게시물과 사용자를 찾아 댓글을 연결하고, 댓글 삭제 시 사용자와 게시물에 대한 검증을 거친 후 댓글을 삭제합니다.

    @Transactional
    public List<CommentDto> addComment(Long userId, Long postId, CreateCommentDto commentDto) {
        Post post = postRepository.findById(postId).orElseThrow(
                () -> new BadRequestException("존재하지 않는 게시물입니다.")
        );
        User user = userRepository.findById(userId).orElseThrow(
                () -> new BadRequestException("유저 정보를 찾을 수 없습니다.")
        );
        post.addComment(commentDto.toEntity(user));

        return post.getComments().stream()
                .map(CommentDto::getCommentDto)
                .collect(Collectors.toList());
    }

    @Transactional
    public void removeComment(Long userId, Long postId, Long commentId) {
        Post post = postRepository.findById(postId).orElseThrow(
                () -> new BadRequestException("존재하지 않는 게시물입니다.")
        );
        Map<Long, Comment> comments = post.getComments()
                .stream()
                .collect(Collectors.toMap(Comment::getId, Function.identity()));

        if (!comments.containsKey(commentId)) {
            throw new BadRequestException("댓글 삭제는 댓글을 단 게시물에만 가능합니다.");
        }

        post.removeComment(comments.get(commentId), userId);
    }

 

결론

이렇게 구현된 게시물 댓글 작성 및 삭제 기능을 통해, 사용자는 게시물에 대한 의견을 자유롭게 표현하고, 필요한 경우 자신의 댓글을 삭제할 수 있습니다. 이 기능은 사용자 경험을 향상시키며, 커뮤니티 내에서의 상호작용을 촉진하는 데 중요한 역할을 합니다.