코틀린 웹 프로그래밍 using Ktor (2)
ver 1.0
이번 글에서는 지난 글에서 만들었던 ktor-first-app을 모듈형 프로젝트 구조로 변경해보겠습니다.
지난 시간에 만들었던 ktor-first-app은 다음과 같은 디렉토리 구조를 가지고 있었습니다.
ktor generator가 생성해준 이 프로젝트 구조는 전통적인 자바 프로젝트 디렉토리 구조와는 차이가 있습니다. 그리고 자바 9에서 Java Platform Module System(JPMS - 줄여서 Module이라고 흔히 부름)이 추가된 이후로는 아마 대부분의 프로젝트에서 모듈을 흔히 사용합니다. 자바 모듈을 사용하면 연관성 있는 패키지들을 모듈로 묶어 재사용성을 높이고 유지 보수를 더 수월하게 만들 수 있습니다. 따라서 기존 프로젝트를 자바 프로그래머에게 좀 더 익숙하고 장점이 많은 모듈 구조로 바꿔보겠습니다.
먼저 build.gradle.kts 파일을 열고 파일 마지막에 다음 내용을 지웁니다.
1 2 3 4 5
... kotlin.sourceSets["main"].kotlin.srcDirs("src") kotlin.sourceSets["test"].kotlin.srcDirs("test") sourceSets["main"].resources.srcDirs("resources") sourceSets["test"].resources.srcDirs("testresources")
해당 부분을 지우면 프로젝트 도구 윈도우에서 하늘색 네모 아이콘이 사라진 모습을 보실 수 있습니다.
프로젝트 도구 윈도우에서 프로젝트 루트를 마우스 오른쪽 버튼으로 선택한후 모듈 추가를 선택합니다.
다음과 같이 backend 이름을 넣고 모듈을 생성합니다.
모듈을 생성하면 빌드가 깨지는 것을 볼 수 있습니다. 하지만 당황하지 마시고 backend/build.gradle.kts 파일의 모든 내용을 지운후에 파일을 저장 합니다.
똑같은 방식으로 common, frontend 모듈을 생성하고 각 모듈아래의 build.gradle.kts 내용을 모두 지우고 저장합니다. 작업을 완료하면 다음과 같은 구조를 가지게 됩니다.
프로젝트 루트 밑의 settings.gradle 파일을 열고 모든 내용을 settings.gradle.kts로 복사합니다. 그리고 다음과 같이 변경합니다.
1 2 3 4
rootProject.name = "ktor-first-app" include("backend") include("common") include("frontend")
변경후에는 settings.gradle파일을 삭제합니다.
프로젝트 루트의 build.gradle.kts 파일을 열어 다음과 같이 변경합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
val kotlin_version: String by project val logback_version: String by project buildscript { repositories { mavenCentral() } dependencies { classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.40") } } plugins { java } allprojects { group = "com.example" version = "0.0.1-SNAPSHOT" apply(plugin = "org.jetbrains.kotlin.jvm") repositories { mavenCentral() } dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version") implementation("ch.qos.logback:logback-classic:$logback_version") } } subprojects { version = "0.0.1-SNAPSHOT" } project("backend") { } project("common") { } project("frontend") { }
backend 모듈의 build.gradle.kts을 열고 다음과 같이 변경합니다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
val kotlin_version: String by project val ktor_version: String by project plugins { application } application { mainClassName = "io.ktor.server.cio.EngineMain" } repositories { jcenter() } dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version") implementation("io.ktor:ktor-server-cio:$ktor_version") testImplementation("io.ktor:ktor-server-tests:$ktor_version") }
src/Application.kt 파일을 backend 모듈 밑에 src/main/kotlin 폴더를 생성하고 이곳으로 복사합니다. 그리고 기존의 프로젝트 루트 폴더의 src 폴더는 삭제합니다.
test/Application.kt 파일을 backend 모듈 밑에 src/test/kotlin 폴더를 생성하고 이곳으로 복사합니다. 그리고 기존 프로젝트 루트 폴더의 test 폴더는 삭제합니다.
프로젝트 루트 폴더의 resources 폴더를 backend 모듈의 src/main 폴더 밑으로 옮겨 줍니다.
이제 프로젝트 구성을 마쳤습니다.
프로젝트가 잘 변경되었는지 확인해 보겠습니다.
지금은 브라우저에서 / 경로에 저급하면 HELLO WORLD!" 를 출력하고 있습니다.
이 문자열을 "HELLO WORLD from Backend!"로 변경해 봅니다.
backend 모듈의 test/kotlin/ApplicationTest를 열고 다음과 같이 변경합니다.
1 2 3 4 5 6
... handleRequest(HttpMethod.Get, "/").apply { assertEquals(HttpStatusCode.OK, response.status()) assertEquals("HELLO WORLD from Backend!", response.content) } ...
테스트를 실행하면 실패하는 것을 보실 수 있습니다.
테스트가 통과할 수 있게 backend/src/kotlin/Application.kt 파일을 다음과 같이 변경합니다.
1 2 3 4 5 6 7
... routing { get("/") { call.respondText("HELLO WORLD from Backend!", contentType = ContentType.Text.Plain) } ... }
다시 한 번 테스트를 실행해 봅니다. 테스트가 잘 실행되는 것을 볼 수 있습니다.
프로그램을 실행하고 브라우저에서 0.0.0.0:8080에 접근해서 변경한 결과가 나오는지 확인합니다.
축하드립니다. 아마 이 시리즈에서 가장 어려운 부분을 끝마치셨습니다. JVM기반 언어 프로젝트에서는 프로젝트 셋팅이 초보자들에게 가장 큰 허들이라고 해도 과언이 아닙니다. 필자도 초보시절에는 프로젝트 셋팅만으로 몇 일을 고생한 적이 있습니다. 다들 처음에는 익숙하지 않아 어렵게 느껴집니다. 지겹고 어려운 부분은 정말 다 끝났습니다. 이제 다음 글에서는 본격적으로 코딩을 시작해보겠습니다.