Kotlin으로 Spring Boot Web 만들기

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"}%

그밖에




최종 수정 : 2021-09-26