공부하는 블로그

Kotlin + Springboot로 REST API 시작하기(3) - Todo API 만들기 본문

스프링부트

Kotlin + Springboot로 REST API 시작하기(3) - Todo API 만들기

devtimothy 2018. 12. 13. 19:23

Todo API를 만들어보자

패키지 내에 먼저는 Todo Entity Class를 만들어준다.

// Todo.kt
package com.example.myapp
import javax.persistence.*

@Entity
@Table(name = "todo")
class Todo {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(columnDefinition = "serial")
   var id: Long? = null

   var title: String? = null
   var description: String? = null
   var finished: Boolean? = false
}

처음에는 @Entity 의 패키지가 어디꺼인지 몰라서 헤매었다. hibernate 관련해서도 Entity라는 annotation이 있고… 자바 진영에서는 동명의 변수값들이 엄청 많다. 잘 알고 써야한다.

TypeORM을 써봐서 그런지, 위 소스가 크게 위화감이 없다. 잘 모르는 annotation들도 변수 위에 마우스를 가져다대고 CMD + 클릭을 해보니 친절하게 설명을 해준다.

  • JPA Repository 인터페이스를 생성해준다.

// TodoRepository.kt
package com.example.myapp

import org.springframework.data.jpa.repository.JpaRepository

interface TodoRepository : JpaRepository<Todo, Long>
  • TodoController를 만들어준다.

package com.example.myapp

import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*
import java.util.*

@RestController
@RequestMapping("/todos")
class TodoController(val todoRepository: TodoRepository) {
   @GetMapping
   fun getTodos() = todoRepository.findAll()

   @RequestMapping(path = ["/{todoId}"], method = [RequestMethod.GET])
   fun getTodo(@PathVariable("todoId") todoId: Long): Optional<Todo>? {
       return todoRepository.findById(todoId)
  }

   @PostMapping
   fun newTodo(@RequestBody todo: Todo): Todo {
       todoRepository.save(todo)
       return todo
  }

   @RequestMapping(path = ["/{todoId}"], method = [RequestMethod.PUT])
   @ResponseStatus(HttpStatus.OK)
   fun updateTodo(@RequestBody todo: Todo, @PathVariable("todoId") todoId: Long) {
       var target: Todo = todoRepository.findById(todoId).get()
       target.title = todo.title
       target.description = todo.description
       target.finished = todo.finished

       todoRepository.save(target)
  }

   @RequestMapping(path = ["/{todoId}"], method = [RequestMethod.DELETE])
   fun deleteTodo(@PathVariable("todoId") todoId: Long){
       todoRepository.deleteById(todoId)
  }
}

  • 이제 앱을 실행하여 Postman에서 http://localhost:8080/todos (GET) 하면… 해당하는 DB 테이블을 찾을수 없다면서 에러를 나타낸다. :(

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'myapp.todo' doesn't exist
  • 왜그럴까? JPA에서 자동으로 생성해주지 않기 때문이다. src > main > resources > application.properties로 가서 아래 내용을 추가한다.

spring.jpa.hibernate.ddl-auto=update
  • 옵션별로 다음과 같은 기능을 한다

    • create: 기존테이블 삭제 후 다시 생성

    • update: 변경된 부분만 반영

    • create-drop: create와 같으나 종료 시점에 테이블 DROP

    • none: 사용하지 않음

  • 기타 아래와 같은 옵션이 있으니 참고하길 바란다.

spring.jpa.generate-ddl=false   # DDl 생성 시 데이터베이스 고유의 기능 사용여부 
spring.jpa.show-sql=true   # 실행되는 쿼리문을 보여줌
spring.jpa.database=mysql   # 사용되는 데이터베이스(MariaDB일 경우에는 mysql로 지정한다.)
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect # 테이블 생성시 엔진을 InnoDB 로 생성. 설정하지 않으면 myisam로 등록
  • 어플리케이션을 다시 실행하면 이제 db 상에 todo 테이블이 생성되었음을 볼 수 있다.

  • Todo 데이터를 넣어보자. Postman에 다음과 같은 데이터를 입력해본다.

    // http://localhost:8080/todos (POST)
    // Content-Type: application/json
    // body
    {
    "title": "코틀린 공부하기",
    "description": "코틀린 문법을 공부하자",
    "finished": false
    }
  • 200 OK 응답과 함께 입력이 정상적으로 처리되었다!

  • 이번엔 http://localhost:8080/todos (GET)을 해본다. 200 OK 응답이 떳지만...

[
  {
       "id": 1,
       "title": "??? ????",
       "description": "??? ??? ????",
       "finished": false
  }
]
  • 한글이 깨져서 나온다. MySQL 설정을 보니까 utf8 설정이 되어 있어서 DB 상의 문제는 아닌 듯 하다.

  • JPA 단에서 인코딩 문제였다. application.properties에서 아래와 같이 인코딩 옵션을 넣어준다.

spring.datasource.url=jdbc:mysql://localhost/myapp?characterEncoding=UTF-8
  • 다시 POST 요청 하고 GET 요청으로 목록을 확인하니 DB에 잘 등록이 되었다.

  • 나머지 PUT, DELETE 등의 요청도 해보면, 잘 실행됨을 확인할 수 있다.


Comments