Kotlin으로 Spring Boot Web 만들기
개요
Kotlin 언어를 사용하여 간단한 Spring Boot Web를 만들어 보겠다.
프로젝트 생성
아래와 같이 curl
명령어를 사용하여 Spring Boot 초기 프로젝트를 생성한다.
curl https://start.spring.io/starter.tgz \
-d bootVersion=2.4.11 \
-d dependencies=web \
-d baseDir=spring-boot-hello-world \
-d groupId=com.devkuma \
-d artifactId=spring-boot-hello-world \
-d packageName=com.devkuma.hello \
-d applicationName=HelloApplication \
-d packaging=jar \
-d language=kotlin \
-d javaVersion=11 \
-d type=gradle-project | tar -xzvf -
위 명령어를 실행하게 되면 Java 11, Spring Boot 버전은 2.4.11로 web 프로젝트가 생성된다.
생성된 프로젝트의 파일 구조는 아래와 같이 구성된다.
.
├── HELP.md
├── build.gradle.kts
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src
├── main
│ ├── kotlin
│ │ └── com
│ │ └── devkuma
│ │ └── hello
│ │ └── HelloApplication.kt
│ └── resources
│ ├── application.properties
│ ├── static
│ └── templates
└── test
└── kotlin
└── com
└── devkuma
└── hello
└── HelloApplicationTests.kt
생성된 프로젝트 확인
build.gradle.kts
생성된 파일에 빌드 파일의 확장자가 .kts
으로 코틀린 스크립트 파일로 된것을 볼 수 있다.
(참고로, Java에서는 빌드 파일의 확장자는 .gradle
이고, Go언어로 되어 있다.)
/build.gradle.kts
// ... 생략 ...
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
// ... 생략 ...
파일 내용 중에 의존성 라이브러리를 확인해 보면 Spring 프레임워크(org.springframework.boot
), 코틀린용 Jackson(com.fasterxml.jackson.module
), 코틀린 라이브러리(org.jetbrains.kotlin
)가 추가되어 있는 것을 볼수 있다.
Application Context
/src/main/kotlin/com/devkuma/hello/controller/HelloController.kt
package com.devkuma.hello
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class HelloApplication
fun main(args: Array<String>) {
runApplication<HelloApplication>(*args)
}
Spring Boot를 실행하기 위한 @SpringBootApplication
어노테이션과 main 함수가 보이는 것을 확인 할 수 있다.
(전반적으로 자바 코드와 비슷해 보인다.)
Controller 생성
Controller 파일을 생성하여 아래와 같이 작성한다.
/src/main/kotlin/com/devkuma/hello/controller/HelloController.kt
package com.devkuma.hello.controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class HelloController {
@GetMapping("/hello")
fun hello(): String {
return "hello world"
}
}
테스트 코드를 생성하고, 실행해 본다.
/src/test/kotlin/com/devkuma/hello/controller/HelloControllerTests.kt
package com.devkuma.hello.controller
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.ResultActions
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.print
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
@WebMvcTest(HelloController::class)
class HelloControllerTests {
@Autowired
lateinit var mockMvc: MockMvc
@Test
@DisplayName("Hello")
fun hello() {
// when
val resultActions: ResultActions = mockMvc.perform(get("/hello"))
.andDo(print())
// then
resultActions
.andExpect(status().is2xxSuccessful)
.andExpect(content().string("hello world"))
.andDo(print())
}
}
실행 결과에 에러가 없는지 확인하다.
실제 동작 여부도 확인을 위해 프로젝트를 실행 후에 아래 curl
명령어로 작동 여부를 확인한다.
% curl localhost:8080/hello
hello world%
Service 생성
Service 파일을 생성하고 아래와 같이 작성한다.
/src/main/kotlin/com/devkuma/hello/service/HelloService.kt
package com.devkuma.hello.service
import org.springframework.stereotype.Service
@Service
class HelloService {
fun getHello(): String {
return "hello service"
}
}
Controller 파일에서 아래와 같이 ‘helloService()‘를 추가한다.
/src/main/kotlin/com/devkuma/hello/controller/HelloController.kt
package com.devkuma.hello.controller
import com.devkuma.hello.service.HelloService
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class HelloController(val helloService: HelloService) {
// ...중간 생략...
@GetMapping("/hello-service")
fun helloService(): String {
return helloService.getHello()
}
}
아래와 같이 테스트 코드 helloService()
를 추가하고, 실행해 본다.
/src/test/kotlin/com/devkuma/hello/controller/HelloControllerTests.kt
package com.devkuma.hello.controller
import com.devkuma.hello.service.HelloService
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.mockito.BDDMockito.given
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.ResultActions
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.print
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
@WebMvcTest(HelloController::class)
class HelloControllerTests {
@Autowired
lateinit var mockMvc: MockMvc
@MockBean
lateinit var helloService: HelloService
// ...중간 생략...
@Test
@DisplayName("Hello Service")
fun helloService() {
// given
given(helloService.getHello()).willReturn("hello service");
// when
val resultActions: ResultActions = mockMvc.perform(get("/hello-service"))
.andDo(print())
// then
resultActions
.andExpect(status().is2xxSuccessful)
.andExpect(content().string("hello service"))
.andDo(print())
}
}
실제 동작 여부도 확인을 위해 프로젝트를 실행 후에 아래 curl
명령어로 작동 여부를 확인한다.
% curl localhost:8080/hello-service
hello service%
DTO 생성
DTO 파일을 생성하고 아래와 같이 작성한다.
/src/main/kotlin/com/devkuma/hello/dto/HelloDto.kt
package com.devkuma.hello.dto
class HelloDto(val greeting: String)
Controller 파일에서 아래와 같이 ‘helloDto()‘를 추가한다.
/src/main/kotlin/com/devkuma/hello/controller/HelloController.kt
@RestController
class HelloController(val helloService: HelloService) {
// ...중간 생략...
@GetMapping("/hello-dto")
fun helloDto(): HelloDto {
return HelloDto("hello dto")
}
}
아래와 같이 테스트 코드 helloDto()
를 추가하고, 실행해 본다.
/src/test/kotlin/com/devkuma/hello/controller/HelloControllerTests.kt
package com.devkuma.hello.controller
import com.devkuma.hello.service.HelloService
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.mockito.BDDMockito.given
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.ResultActions
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.print
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.*
@WebMvcTest(HelloController::class)
class HelloControllerTests {
// ...중간 생략...
@Test
@DisplayName("Hello DTO")
fun helloDto() {
// when
val resultActions: ResultActions = mockMvc.perform(get("/hello-dto"))
.andDo(print())
// then
resultActions
.andExpect(status().is2xxSuccessful)
.andExpect(jsonPath("greeting").value("hello dto"))
.andDo(print())
}
}
실제 동작 여부도 확인을 위해 프로젝트를 실행 후에 아래 curl
명령어로 작동 여부를 확인한다.
% curl localhost:8080/hello-dto
{"greeting":"hello dto"}%
그밖에
- 이 포스트의 내용은 Baeldung:Spring Boot and Kotlin을 기본으로 다시 작성되었다.
- 위에 모든 소스 코드는 GitHub에서 확인해 볼 수 있다.