spring / 댓글 기능 구현

kongta2·2023년 12월 1일
0

todo 프로젝트의 마지막 기능인 댓글 기능이다.

Comment - entity

@Getter
@Entity
@NoArgsConstructor
public class Comment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String text;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne
    @JoinColumn(name = "todo_id")
    private Todo todo;

    @Column
    private LocalDateTime createDate;

    public Comment(CommentRequestDto dto) {
        this.text = dto.getText();
        this.createDate = LocalDateTime.now();
    }

    public void setUser(User user) {
        this.user = user;
    }

    public void setTodo(Todo todo) {
        this.todo = todo;
        todo.getComments().add(this);
    }

    public void setText(String text) {
        this.text = text;
    }
}

comment 테이블을 만들어 줘야하기 때문에 Comment.java를 생성해주고 User, Todo 테이블과 다대일 관계이기 때문에 ManyToOne으로 각 테이블의 id와 매핑해준다.

CommentRepository

public interface CommentRepository extends JpaRepository<Comment, Long> {
}

CommentRequestDto - 요청

@Getter
@Setter
public class CommentRequestDto {
    private Long todoId;
    private String text;
}

CommentResponseDto - 반응

@Getter
@Setter
public class CommentResponseDto extends CommonResponseDto {
    private Long id;
    private String content;
    private UserDto user;
    private LocalDateTime createDate;

    public CommentResponseDto(Comment comment) {
        this.id = comment.getId();
        this.content = comment.getText();
        this.user = new UserDto(comment.getUser());
        this.createDate = comment.getCreateDate();
    }
}

Comment를 저장할 수 있도록 CommentRepository를 만들고 CommentRequestDto, CommentResponseDto를 만들어 값 요구와 반환을 할 수 있도록 한다.

CommentController

@RequestMapping("/api/comments")
@RestController
@RequiredArgsConstructor
public class CommentController {
    private final CommentService commentService;


    // 댓글 생성
    @PostMapping()
    public ResponseEntity<CommentResponseDto> postComment(@RequestBody CommentRequestDto commentRequestDto, @AuthenticationPrincipal UserDetailsImpl userDetails) {
        CommentResponseDto responseDto = commentService.createComment(commentRequestDto, userDetails.getUser());
        return ResponseEntity.status(201).body(responseDto);
    }

    // 댓글 조회
    @GetMapping("/{commentId}")
    public ResponseEntity<CommonResponseDto> getComment(@PathVariable Long commentId) {
        try {
            CommentResponseDto responseDto = commentService.getComment(commentId);
            return ResponseEntity.ok().body(responseDto);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(new CommonResponseDto(e.getMessage(), HttpStatus.BAD_REQUEST.value()));
        }
    }


    // 댓글 수정(text)
    @PutMapping("/{commentId}")
    public ResponseEntity<CommonResponseDto> putComment(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable Long commentId, @RequestBody CommentRequestDto commentRequestDto) {
        try {
            CommentResponseDto responseDto = commentService.updateComment(userDetails.getUser(), commentId, commentRequestDto);
            return ResponseEntity.ok().body(responseDto);
        } catch (RejectedExecutionException | IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(new CommonResponseDto("작성자만 수정할 수 있습니다.", HttpStatus.BAD_REQUEST.value()));
        }
    }

    // 댓글 삭제
    @DeleteMapping("/{commentId}")
    public ResponseEntity<CommonResponseDto> deleteComment(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable Long commentId) {
        try {
            commentService.deleteComment(userDetails.getUser(), commentId);
            return ResponseEntity.ok().body(new CommonResponseDto("댓글 삭제가 완료되었습니다.", HttpStatus.OK.value()));
        } catch (RejectedExecutionException | IllegalArgumentException e){
            return ResponseEntity.badRequest().body(new CommonResponseDto("작성자만 삭제할 수 있습니다.", HttpStatus.BAD_REQUEST.value()));
        }
    }

}

CommentService

@Service
@RequiredArgsConstructor
public class CommentService {
    private final CommentRepository commentRepository;
    private final TodoService todoService;


    // 댓글 생성
    public CommentResponseDto createComment(CommentRequestDto requestDto, User user) {
        Todo post = todoService.getTodo(requestDto.getTodoId());

        Comment comment = new Comment(requestDto);
        comment.setUser(user);
        comment.setTodo(post);

        Comment saveComment = commentRepository.save(comment);

        return new CommentResponseDto(saveComment);
    }

    // 댓글 단건조회
    public CommentResponseDto getComment(Long commentId){
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 댓글 ID 입니다."));

        return new CommentResponseDto(comment);
    }

    // 댓글 수정
    @Transactional
    public CommentResponseDto updateComment(User user, Long commentId, CommentRequestDto commentRequestDto) {
        Comment comment = getComment(user, commentId);

        comment.setText(commentRequestDto.getText());

        return new CommentResponseDto(comment);
    }

    // 댓글 삭제
    public void deleteComment(User user, Long commentId) {
        Comment comment = getComment(user, commentId);

        commentRepository.delete(comment);
    }


    // 검증
    public Comment getComment(User user, Long commentId) {
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 댓글 ID 입니다."));

        if(!user.getId().equals(comment.getUser().getId())) {
            throw new RejectedExecutionException("작성자만 수정할 수 있습니다.");
        }

        return comment;
    }
}

CommentController와 CommentService에는 앞에서 배웠던 CRUD기능과 똑같이 구현했다.

Postman을 이용한 기능 구현 확인

  1. 생성

  2. 조회

  3. 수정

  1. 삭제

Todo프로젝트 마무리

Spring 공부를 하면서, 처음 배우는 걸 너무 많이 배우다보니 내가 지금 뭘 공부하고 있는 건지도 모르겠고 이해도 잘 안되었는데, 이번 프로젝트를 진행하면서 감을 조금씩 잡은 것 같고, 다시 spring입문으로 돌아가서 복습을 하면 처음에는 보이지 않고 이해가 되지 않았던 부분이 보일 것 같다.

profile
2025.04.01~

0개의 댓글