Ktor を Getting started してみる

【完走賞】MxShun ひとりマラソン 🏃 Advent Calendar 2022 毎週水曜日は Advent Calendar を機になにかに入門しよう！3記事目です。

今日は Ktor を Getting started してみます。

https://ktor.io/docs/welcome.html

### Ktor とは
Web アプリケーションや HTTP サービス、モバイルアプリケーション、ブラウザアプリケーションを容易に接続する JetBrains 製の Kotlin 純正フレームワークで、エンドツーエンドのマルチプラットフォームアプリケーションを繋ぐことを目標としています。

### Ktor プロジェクトを立ち上げる
今回は IntelliJ IDEA を利用して立ち上げます。

📝 バージョン情報
- IntelliJ IDEA: v2022.2.4
- Ktor: v2.2.1
- Kotlin: v1.7.22
- Gradle: v7.5.1

今回はビルドシステム、（サーバ）エンジン、構成いずれもデフォルトのままで立ち上げます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/614f9103-5a6c-dd47-d2c6-6c1cc385099d.png)

プラグインに Routing を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/3bbd6463-3c20-09d5-bd26-0bc285a1363c.png)

次のような構成 Ktor プロジェクトが立ち上がりました。

```bash
getting-started-with-ktor
|--.git
|  |-- // 中略
|--.gitignore
|--.gradle
|  |-- // 中略
|--.idea
|  |-- // 中略
|--build.gradle.kts
|--getting-started-with-ktor.iml
|--gradle
|--gradle.properties
|  |--wrapper
|  |  |--gradle-wrapper.jar
|  |  |--gradle-wrapper.properties
|--gradlew
|--gradlew.bat
|--settings.gradle.kts
|--src
|  |--main
|  |  |--kotlin
|  |  |  |--com
|  |  |  |  |--example
|  |  |  |  |  |--Application.kt
|  |  |  |  |  |--plugins
|  |  |  |  |  |  |--Routing.kt
|  |  |--resources
|  |  |  |--logback.xml
|  |--test
|  |  |--kotlin
|  |  |  |--com
|  |  |  |  |--example
|  |  |  |  |  |--ApplicationTest.kt
```

地味に気になるのが `build.gradle.kts` の内容です。

```build.gradle.kts
val ktor_version: String by project
val kotlin_version: String by project
val logback_version: String by project

plugins {
    application
    kotlin("jvm") version "1.7.22"
    id("io.ktor.plugin") version "2.2.1"
}

group = "com.example"
version = "0.0.1"
application {
    mainClass.set("com.example.ApplicationKt")

    val isDevelopment: Boolean = project.ext.has("development")
    applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment")
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.ktor:ktor-server-core-jvm:$ktor_version")
    implementation("io.ktor:ktor-server-netty-jvm:$ktor_version")
    implementation("ch.qos.logback:logback-classic:$logback_version")
    testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
}
```

ログ出力ライブラリに Logback を利用している以外は　Ktor、Kotlin の純正ライブラリにのみ依存しています。とても洗練されていますね。Netty も自前とは・・・。

### Ktor アプリケーションを起動する

メインアプリケーションです。 `embeddedServer` :thinking: これは時間があるときにコードリーディングしたいです。

```Application.kt
package com.example

import com.example.plugins.configureRouting
import io.ktor.server.application.Application
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty

fun main() {
    embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module)
        .start(wait = true)
}

fun Application.module() {
    configureRouting()
}
```

Routing プラグインによりパスルーティングが定義されています。

```Routing.kt
package com.example.plugins

import io.ktor.server.application.Application
import io.ktor.server.application.call
import io.ktor.server.response.respondText
import io.ktor.server.routing.get
import io.ktor.server.routing.routing

fun Application.configureRouting() {

    routing {
        get("/") {
            call.respondText("Hello World!")
        }
    }
}
```

さて、Ktor アプリケーションを起動しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/2f3f0e5c-43f3-9b47-30a8-0eb4f1f49ea0.png)

アプリケーションが起動したら次のようなログがでました。なに、もうこいつマルチスレッドで動いてるの？すご :thinking: 

```
2022-12-08 21:55:26.133 [main] INFO  ktor.application - Autoreload is disabled because the development mode is off.
2022-12-08 21:55:26.862 [main] INFO  ktor.application - Application started in 0.813 seconds.
2022-12-08 21:55:27.920 [DefaultDispatcher-worker-2] INFO  ktor.application - Responding at http://127.0.0.1:8080
```

cURL してみます。ちゃんとハローワールドが返ってきました🎉

```
$ curl http://127.0.0.1:8080
Hello World!
```

いちおうログも見ます。TRACE のログレベルでパスルーティングのトレース情報が表示されました。

```
2022-12-08 21:58:56.652 [eventLoopGroupProxy-4-2] TRACE io.ktor.routing.Routing - Trace for []
/, segment:0 -> SUCCESS @ /
  /, segment:0 -> SUCCESS @ /
    /(method:GET), segment:0 -> SUCCESS @ /(method:GET)
Matched routes:
  "" -> "<slash>" -> "(method:GET)"
Route resolve result:
  SUCCESS @ /(method:GET)
```

### まとめ
さて今回は、Ktor を Getting started してみました。

手軽さこそ今までの Spring 等と変わりませんが、依存ライブラリの洗練さやデフォルトでの非同期通信、初期プロジェクトとしてのコードの読みやすさはグレートですね。コードリーディングのしがいがありそうな気がします。
まだまだドキュメントや情報は醸成が進んでいる段階ですが、サーバーサイド言語としての Kotlin が確立されるのもすぐそこの未来のように感じました。

Spring のような設定やチューニング周りの手の届く範囲、システムとしてのスケーリングのしやすさはもう少し調べてみたいところです。