[Project] Stackoverflow 클론코딩하기 - 댓글 CRUD 기능 구현 (API 계층)

정동아·2023년 8월 22일
0

Stackoverflow

목록 보기
5/8

이제 배포환경 구축이 끝났으니! 내가 맡은 다음 작업을 진행해야한다.
내가 맡은 다음 작업은 댓글 CRUD기능 구현이었다.

jpa를 배우면서 연관관계매핑하는게 가장 어려웠는데, 이번에 프로젝트를 하며 좀 많이 이해되어서 뿌듯했다.
정말 코딩은 직접 해봐야한다...!


댓글 기능을 구현할 때 Question과 Member 기능이 거의 다 구현되어있어서 바로 작업을 시작했다.
이 글에서는 API 계층까지 구현한 내용을 정리하려한다.

CommentController

@RestController
@RequestMapping("/questions/{question-id}/comments")
@Validated
public class CommentController {
    private final static String REPLY_DEFAULT_URL = "/questions/{question-id}/comments";
    private final CommentService commentService;
    private final CommentMapper mapper;

    public CommentController(CommentService commentService, CommentMapper mapper) {
        this.commentService = commentService;
        this.mapper = mapper;
    }

    //질문에 대한 답변을 등록
    @PostMapping
    public ResponseEntity postComment(@RequestBody @Valid CommentPostDto commentPostDto,
                                      @PathVariable("question-id") @Positive long questionId){

        commentPostDto.setQuestionId(questionId);
        Comment postComment = mapper.commentPostDtoToComment(commentPostDto);
        Comment response = commentService.createComment(postComment);

        URI location = UriComponentsBuilder.newInstance()
                .path(REPLY_DEFAULT_URL+"/{comment-id}")
                .buildAndExpand(questionId,response.getCommentId())
                .toUri();

        return ResponseEntity.created(location).build();
    }

    //답변 수정
    @PatchMapping("/{comment-id}")
    public ResponseEntity patchComment (@PathVariable("question-id") @Positive long questionId,
                                        @PathVariable("comment-id") @Positive long commentId,
                                        @RequestBody @Valid CommentPatchDto commentPatchDto){

        commentPatchDto.setCommentId(commentId);
        Comment patchComment = mapper.commentPatchDtoToComment(commentPatchDto);
        Comment response = commentService.updateComment(patchComment);

        return new ResponseEntity<>(mapper.commentToCommentResponseToDto(response), HttpStatus.OK);
    }

    //답변 조회
    @GetMapping
    public ResponseEntity getComments (@PathVariable("question-id") @Positive long questionId){
        List<Comment> comment = (List<Comment>) commentService.findCommentAll(questionId);

        return new ResponseEntity<>(mapper.commentsToCommentsResponseDto(comment), HttpStatus.OK);
    }

    //답변 삭제
    @DeleteMapping("/{comment-id}")
    public ResponseEntity deleteComment (@PathVariable("question-id") @Positive long questionId,
                                         @PathVariable("comment-id") @Positive long commentId){

        commentService.deleteComment(questionId, commentId);

        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
}
  • 질문에 대한 답변을 다는 기능이기 때문에 API요청 URI를 /questions/{question-id}/comments 로 설정했다.
  • POST와 PATCH는 DTO를 이용해서 핸들러메서드를 작성했다.

CommentPatchDto

ackage com.stackoverflow.Server.comment.dto;

import com.stackoverflow.Server.member.entity.Member;
import com.stackoverflow.Server.question.entity.Question;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.validation.constraints.NotEmpty;

@Getter
@Setter
@NoArgsConstructor
public class CommentPatchDto {

    private Long commentId;

    @NotEmpty(message = "답변 내용을 작성해주세요.") 
    private String commentBody;


}

CommentPostDto

package com.stackoverflow.Server.comment.dto;

import com.stackoverflow.Server.comment.entity.Comment;
import com.stackoverflow.Server.member.entity.Member;
import com.stackoverflow.Server.question.entity.Question;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.validation.constraints.NotEmpty;


@Getter
@Setter
@NoArgsConstructor
public class CommentPostDto {

    private Long questionId;

    private Long memberId;

    private String nickname;

    @NotEmpty(message = "답변 내용을 작성해주세요.")
    private String commentBody;

    public Member getMember(){
        Member member = new Member();
        member.setMemberId(memberId);
        member.setNickname(nickname);

        return member;
    }

    public Question getQuestion (){
        Question question = new Question();
        question.setQuestionId(questionId);
        return question;
    }

}
  • getMember()와 getQuestion ()는 Member와 Question 객체를 생성해서 설정하기위해 작성했습니다.
  • 댓글 등록할 때 member의 id와 nickname 정보를 저장하고, question의 id를 저장해서 댓글 작성자와 질문 정보를 나타내고 댓글 불러올 때 정보도 불러오기위해 사용했습니다.
  • 이렇게 작성하면 CommentPostDto 객체의 데이터를 다른 클래스의 객체로 변환해서 이후에 이 정보를 활용하거나 저장하는데 사용될 수 있도록 도와주는 역할을 한다.
  • 이렇게 작성하는건 데이터 전송 객체가 다양한 컴포넌트 또는 레이어간의 데이터를 전달하고 변환하기 위해 자주 사용되는 패턴이라고한다.

2개의 댓글

comment-user-thumbnail
2023년 8월 23일

아침에 출근해서 남 블로그 읽는게 개꿀...쿄쿄쿄

1개의 답글