지난 포스트에선 Todo에 관련된 부분만 구현을 했다면, 오늘 포스트에서는 코멘트(댓글) 기능을 추가해 볼 것이다.
당연히, API명세서도 추가되고 DB간의 관계도 정의해야한다.
Todo APP 설계
요구사항 재정의
요구사항 | 설명 |
할일 카드 작성 기능 | 할 일 제목, 할일 내용, 작성일, 작성자 이름을 저장할 수 있다. 저장된 할일의 정보를 반환받아 확인할 수 있다. |
선택한 할 일 조회 기능 | 선택한 할 일의 정보를 조회할 수 있다. 반환 받은 할 일 정보에는 할일 제목, 할일 내용, 작성일 ,작성자 이름 정보가 있다. |
할일 카드 목록 조회 기능 | 등록된 할 일 전체를 조회할 수 있다. 조회한 할 일 목록은 작성일 기준 내림차순으로 정렬되어있다. |
선택한 할일 수정 기능 | 선택한 할일의 할일 제목, 작성자명, 작성 내용을 수정할 수 있다. 수정된 할 일의 정보를 반환받아 확인 가능. |
선택한 할 일 삭제 기능 | 선택한 할일 정보를 삭제할 수 있다. |
추가사항 |
|
선택한 할 일 완료 기능 |
선택한 할일의 완료 여부를 표시할 수 있다. (Default = false) |
댓글 작성 기능 | 댓글을 작성할 때, 작성자 이름과 비밀번호를 함께 받는다. (비밀번호는 제외하고 반환) |
댓글 수정 기능 | 선택한 댓글의 DB 저장 유무를 확인해, 작성자 이름과 비밀번호 이름을 받아 저장된 값과 일치하면 수정 한다. (비밀번호는 제외하고 반환) |
댓글 삭제 기능 | 선택한 댓글의 DB 저장 유무를 확인해, 작성자 이름과 비밀번호 이름을 받아 저장된 값과 일치하면 삭제 한다. |
패키지 구조 재정의
기존에 작성한 패키지에 Comment가 추가되었다!
domain
⎿ todo
⎿ controller
⎿ service
⎿ repository
⎿ dto
⎿ model
⎿ comment
⎿ controller
⎿ service
⎿ repository
⎿ dto
⎿ model
exception
infra
⎿ swagger
API 명세서 재정의
우선 필수 요구사항 들을 기준으로 API 명세서를 작성해보았다.
Command | Method | API Path | Response |
할일 작성 | POST | /todos | 201/400 |
할일 목록 조회 | GET | /todos | 200 |
할일 상세 조회 | GET | /todos/{todoId} | 200 |
할일 수정 | PUT | /todos/{todoId} | 200/400 |
할일 삭제 | DELETE | /todos/{todoId} | 204 |
할일 완료 | PATCH | /todos/{todoId}/done | 200 |
댓글 추가 | POST | /todos/{todoId}/comments/{commentId} | 201 |
댓글 수정 | PUT | /todos/{todoId}/comments/{commentId} | 200 |
댓글 삭제 | DELETE | /todos/{todoId}/comments/{commentId} | 204 |
DB
Todo | |
id | Long ( auto generated ) |
title | String |
author | String |
date | LocalDate |
description | String |
comments
|
List |
Comment | |
id | Long ( auto generated ) |
name | String |
body | String |
password | String |
구현
이번에도 구현하기에 앞서, 순서를 정했다.
Step1. Controller와 DTO 설정하기
Step2. Service 작성 및 Controller와 연결
Step3. Repository 작성 및 Service와 연결
Step4. Todo와 Comment 연결하기
코드의 기본적인 작성은 Todo와 동일하여, 전체 코드 관련 링크를 따로 올리고, 그 중 중요하다고 생각된 부분에 대해서만 설명을 남겨 두겠다.
기본적인 Comment 구현은 어느정도 했으나, Todo와 Comment 연결을 하는 부분은 조금 더 상세한 설명이 필요하단 생각이 들었다.
Todo와 Comment 연결하기
다음은 Todo 엔티티와 Comment 엔티티를 1:多 로 연결하는 과정을 보여준다.
- OneToMany : 엔티티 간의 일대 다 관계를 타나낸다. Todo 1개에 Comment가 여러개 연결 될 수 있다는 뜻이다.
- mappedBy = "todo" : todo 엔티티의 어떤 속성이 이 관계를 관리하는지를 가리킨다.
- cascade = [(CascadeType.ALL)] : 부모 엔티티(Todo)의 변경이 자식 엔티티(Comment)에 어떻게 전파되는지를 지정한다. ALL을 사용해 모든 변경 사항이 자식 엔티티에도 적용된다.
- orphanRemoval = true : 부모 엔티티가 삭제되면, 자식 엔티티도 자동으로 삭제되도록 한다.
@Entity
@Table(name = "todo")
class Todo(
@Column(name="done", nullable = false)
var done: Boolean=false,
@OneToMany(mappedBy = "todo",cascade = [(CascadeType.ALL)],orphanRemoval = true)
var comments: MutableList<Comment> = mutableListOf(),
) {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
fun addComment(comment: Comment){
comments.add(comment)
}
fun deleteComment(comment:Comment){
comments.remove(comment)
}
}
fun Todo.toResponse(): TodoResponse {
return TodoResponse(
id=id!!,
title=title,
author=author,
date=createdAt,
body = body!!,
comments = comments.map{it.toResponse()}
)
}
//Todo.kt
- ManyToOne : 엔티티 간의 다 대 일 관계를 타나낸다.
- JoinColumn(name = "todo_id", nullable = false) : todo_id의 열과 조인된다.
@Entity
@Table(name = "comments")
class Comment(
@ManyToOne
@JoinColumn(name = "todo_id", nullable = false)
var todo: Todo,
){
}
//Comment.kt
댓글 수정 삭제
댓글 수정 및 삭제의 경우에는 해당 댓글의 사용자가 맞는지 확인하는 과정을 거쳐야한다.
if (password != comment.password || name != comment.name) {
throw IllegalArgumentException(/*message*/)
}
//CommentServiceImpl.kt - update,deleteComment fun
하단의 깃 레포에 전체 코드가 작성되어있다. 이전에 작성한 것과 겹치는 코드가 많아 별도의 설명은 추가하지 않았다.
Git Repository : https://github.com/DEVxMOON/TodoServer
'PROJECT > Spring Todo 프로젝트' 카테고리의 다른 글
TodoApp 백엔드 서버 만들기 (3) (0) | 2024.05.17 |
---|---|
TodoApp 백엔드 서버 만들기 (1) (0) | 2024.05.14 |