2023. 12. 28. 20:22ㆍTIL
오늘 낮에 TodoApp을 완성했고, 남은 시간엔 코드작성이 어려웠던 부분을 되새김질 하며 공부하는데 시간을 보냈다.
domain을 todocard, todo, comment로 나누었지만
그중 가장 중요한 todocard 패키지만 일단 나열해보겠다.
<TodoCard>
TodoCard조회시 뒤에 적을 Todo와 Comment를 포함할 예정
또 TodoCard 패키지 하위에는 dto, controller, service, model, repository패키지를 포함하고있다.
dto 패키지
CreateTodoCardRequest
package com.example.mytodoapp.domain.todocard.dto
data class CreateTodoCardRequest(
val user: String,
val password: String,
)
TodoCardResponse
package com.example.mytodoapp.domain.todocard.dto
data class TodoCardResponse(
val id: Long,
val user: String,
val date: String,
)
UpdateTodoCardRequest
package com.example.mytodoapp.domain.todocard.dto
data class UpdateTodoCardRequest(
val user: String,
)
dto는 프로세스 간에 데이터를 전달하는 개체이다.
전체적으로 TodoCard는 id, user, password, date 등을 포함하고 있지만 상황에따라서 필요한 데이터가 다르기에 이런식으로 나눠두는 것.
controller 패키지
TodoCardController
package com.example.mytodoapp.domain.todocard.controller
import com.example.mytodoapp.domain.todocard.dto.CreateTodoCardRequest
import com.example.mytodoapp.domain.todocard.dto.TodoCardResponse
import com.example.mytodoapp.domain.todocard.dto.UpdateTodoCardRequest
import com.example.mytodoapp.domain.todocard.service.TodoCardService
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
@RequestMapping("/todoCards")
@RestController
class TodoCardController(
private val todoCardService: TodoCardService
) {
@PostMapping
fun createTodoCard(@RequestBody createTodoCardRequest: CreateTodoCardRequest)
: ResponseEntity<TodoCardResponse>{
return ResponseEntity
.status(HttpStatus.CREATED)
.body(todoCardService.createTodoCard(createTodoCardRequest))
}
@GetMapping()
fun getTodoCardList(): ResponseEntity<List<TodoCardResponse>>{
return ResponseEntity
.status(HttpStatus.OK)
.body(todoCardService.getAllTodoCardList())
}
@GetMapping("/{todoCardId}")
fun getTodoCard(@PathVariable todoCardId: Long): ResponseEntity<TodoCardResponse> {
return ResponseEntity
.status(HttpStatus.OK)
.body(todoCardService.getTodoCardById(todoCardId))
}
@PutMapping("/{todoCardId}")
fun updateTodoCard(
@PathVariable todoCardId: Long,
@RequestBody updateTodoCardRequest: UpdateTodoCardRequest
): ResponseEntity<TodoCardResponse> {
return ResponseEntity
.status(HttpStatus.OK)
.body(todoCardService.updateTodoCard(todoCardId, updateTodoCardRequest))
}
@DeleteMapping("/{todoCardId}/{password}")
fun deleteTodoCard(
@PathVariable todoCardId: Long,
@PathVariable password: String,
): ResponseEntity<Unit>{
return ResponseEntity
.status(HttpStatus.NO_CONTENT)
.body(todoCardService.deleteTodoCard(todoCardId, password))
}
}
@RestController는 스프링 빈으로 등록하기 위해 작성된 어노테이션
또 각각의 매핑을 붙여주면서 메소드의 역할을 지정해주는 듯 싶다.
매핑옆에 오는 /todocard/{todoCardId}/ 등 이런거는 직접 실행된 화면을 보니까 페이지 주소쪽을 나타내는 것인듯 하다.
repository 패키지
TodoCardRepository
package com.example.mytodoapp.domain.todocard.repository
import com.example.mytodoapp.domain.todocard.model.TodoCard
import org.springframework.data.jpa.repository.JpaRepository
interface TodoCardRepository: JpaRepository<TodoCard, Long> {
}
단순하게 JpaRepository를 상속받으면 스프링에서 알아서 레포지토리 파일인것을 인지해준다고 한다.
이런 편리한 면이 스프링을 쓰는 이유인가보다.
model 패키지
TodoCard
package com.example.mytodoapp.domain.todocard.model
import com.example.mytodoapp.domain.comment.model.Comment
import com.example.mytodoapp.domain.todo.model.Todo
import com.example.mytodoapp.domain.todocard.dto.TodoCardResponse
import jakarta.persistence.*
import java.time.LocalDateTime
var now = LocalDateTime.now()
@Entity
@Table(name = "todocard")
class TodoCard (
@Column(name = "app_user", nullable = false)
var app_user: String,
@Column(name = "password", nullable = false)
var password: String,
@Column(name = "date", nullable = false)
val date: String = "${now.year}-${now.month}-${now.dayOfMonth}",
@OneToMany(
cascade = [CascadeType.ALL],
orphanRemoval=true,
fetch = FetchType.LAZY)
@JoinColumn(name = "todocard_id")
var todoList: MutableList<Todo> = mutableListOf(),
@OneToMany(
cascade = [CascadeType.ALL],
orphanRemoval=true,
fetch = FetchType.LAZY)
var comments: MutableList<Comment> = mutableListOf()
) {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
fun addComment(comment: Comment) {
comments.add(comment)
}
fun removeComment(comment: Comment) {
comments.remove(comment)
}
fun addTodo(todo: Todo) {
todoList.add(todo)
}
fun removeTodo(todo: Todo) {
todoList.remove(todo)
}
}
fun TodoCard.toResponse(): TodoCardResponse {
return TodoCardResponse(
id = id!!,
user = app_user,
date = date
)
}
내가 만든 데이터베이스의 테이블과 DTO를 연결해주는 파일이다.
테이블 하나하나의 컬럼과 DTO의 변수들을 지정해주고,
Id의 경우 @GeneratedValue(strategy = GenerationType.IDENTITY) 를 써서 자동입력되도록 했다.
service 패키지
앱에서 사용될 메소드를 정리해둔 패키지인데
내가 이해한대로 적자면
클라이언트들은 아래 파일을 접하게 될거고
TodoCardService
package com.example.mytodoapp.domain.todocard.service
import com.example.mytodoapp.domain.todocard.dto.CreateTodoCardRequest
import com.example.mytodoapp.domain.todocard.dto.TodoCardResponse
import com.example.mytodoapp.domain.todocard.dto.UpdateTodoCardRequest
interface TodoCardService {
fun getAllTodoCardList(): List<TodoCardResponse>
fun getTodoCardById(todoCardId: Long): TodoCardResponse
fun createTodoCard(request: CreateTodoCardRequest): TodoCardResponse
fun updateTodoCard(todoCardId: Long, request: UpdateTodoCardRequest): TodoCardResponse
fun deleteTodoCard(todoCardId: Long, password: String,)
}
메소드들이 상세하게 적혀있는 파일은 위 파일을 상속받은
TodoCardServiceImpl
package com.example.mytodoapp.domain.todocard.service
import com.example.mytodoapp.domain.exception.IncorrectPasswordException
import com.example.mytodoapp.domain.exception.ModelNotFoundException
import com.example.mytodoapp.domain.todocard.dto.CreateTodoCardRequest
import com.example.mytodoapp.domain.todocard.dto.TodoCardResponse
import com.example.mytodoapp.domain.todocard.dto.UpdateTodoCardRequest
import com.example.mytodoapp.domain.todocard.model.TodoCard
import com.example.mytodoapp.domain.todocard.model.toResponse
import com.example.mytodoapp.domain.todocard.repository.TodoCardRepository
import jakarta.transaction.Transactional
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
@Service
class TodoCardServiceImpl(
private val todoCardRepository: TodoCardRepository
): TodoCardService {
override fun getAllTodoCardList(): List<TodoCardResponse> {
return todoCardRepository.findAll().map{ it.toResponse() }
}
override fun getTodoCardById(todoCardId: Long): TodoCardResponse {
val todoCard = todoCardRepository.findByIdOrNull(todoCardId)
?: throw ModelNotFoundException("TodoCard", todoCardId)
return todoCard.toResponse()
}
@Transactional
override fun createTodoCard(request: CreateTodoCardRequest): TodoCardResponse {
return todoCardRepository.save(
TodoCard(
app_user = request.user,
password = request.password
)
).toResponse()
}
@Transactional
override fun updateTodoCard(todoCardId: Long, request: UpdateTodoCardRequest): TodoCardResponse {
val todoCard = todoCardRepository.findByIdOrNull(todoCardId)
?: throw ModelNotFoundException("TodoCard", todoCardId)
val (user) = request
todoCard.app_user = user
return todoCardRepository.save(todoCard).toResponse()
}
@Transactional
override fun deleteTodoCard(todoCardId: Long, password: String) {
val todoCard = todoCardRepository.findByIdOrNull(todoCardId)
?: throw ModelNotFoundException("TodoCard", todoCardId)
if (password == "masterPW5946" || password == todoCard.password ){
todoCardRepository.delete(todoCard)
} else {
throw IncorrectPasswordException(password, todoCardId)
}
}
}
이것이다.
오늘의 한마디 : 일단 완성은 했지만 출제의도 대로 작성한것인지는 모르겠다. 빨리 피드백을 받아보고싶다.
'TIL' 카테고리의 다른 글
20240102 (화) TodoApp 2차 과제물 코딩 (2) | 2024.01.02 |
---|---|
20231229 (금) 금요일TIL (1) | 2023.12.29 |
20231227 (수) TodoApp 막바지 (2) | 2023.12.27 |
20231226 (화) TodoApp 제작기 (0) | 2023.12.26 |
20231222 (금) CourseRegistration 앱 마무리, Todo 앱 만들기 시작 (1) | 2023.12.22 |