필사 모드: モダン Kotlin 2026 — Kotlin 2.1 / K2 コンパイラ / Compose Multiplatform / KMP 2.1 / Ktor 3 / Spring Boot Kotlin 深掘りガイド
日本語プロローグ — 2026 年の Kotlin はもう「Android の言語」ではない
2017 年の Google I/O で Android 公式言語になった日から、Kotlin はしばらく「Android のための Java 代替」として生きてきた。サーバ陣営は Java 17、21 を使えばよかったし、マルチプラットフォームはアルファからベータへゆっくりと進んでいた。
2026 年 5 月の風景は当時とまったく違う。
- **Kotlin 2.1**(2024 年 11 月)が **K2 コンパイラをデフォルト**に昇格させた。IDE も K2 モードがデフォルトで、クリーンビルドは K1 比平均 1.8 倍速い。
- **Kotlin 2.2**(2025 年 3 月)が **context parameters** — 旧 context receivers の正式な後継 — を導入。戻り値の型を汚さずに、関数シグネチャに依存性を結びつけられる。
- **Compose Multiplatform 1.7**(2024 年 10 月)が **iOS を stable** と宣言。Android・iOS・デスクトップ・Web(Wasm)を 1 コードベースで描く。
- **KMP(Kotlin Multiplatform)2.1** は production-ready を超え、メルカリ・マクドナルドなどがコア SDK を KMP に書き換えている。
- **Ktor 3**(2024 年 10 月)が **WebAssembly ターゲット**を追加し、kotlinx-io ベースで書き直されてスループットが平均 90% 上昇。
- **Spring Boot 3.5** は Kotlin を一級言語扱い。coroutine サポートは成熟、Kotlin DSL ビルドが標準。
本稿は「Kotlin を見始めたばかり」から「2026 年の本番でどう動くか全部見たい」までを一気に整理する。言語・コンパイラ・UI・サーバ・ライブラリ陣営・国内外事例を漏らさず押さえる。
1 章 · 2026 年のモダン Kotlin — Kotlin 2.x 時代の座標
まず座標を取ろう。2026 年 5 月時点の Kotlin フルスタックは次のとおり。
+----------------------------------------+
| Kotlin 2.2.x |
| (K2 compiler default, JVM/JS/Wasm) |
+----------------------------------------+
|
+-------------------+--------------------+
| | |
v v v
[JVM バックエンド] [マルチプラットフォーム] [Native / Wasm]
Spring Boot 3.5 KMP 2.1 + CMP 1.7 Kotlin/Native
Ktor 3 iOS/Android/Desktop Kotlin/Wasm
gRPC-Kotlin Web (Wasm) (Ktor 3 server)
| | |
+-------------------+--------------------+
|
v
+-------------------------+
| kotlinx ライブラリ |
| coroutines / Flow |
| serialization / io |
| datetime / atomicfu |
+-------------------------+
|
v
+---------------+----------------+
| | |
v v v
[DI/FP/ORM] [静的解析/テスト] [ビルド]
Koin / Arrow Detekt / Konsist Gradle Kotlin DSL
Exposed Kotest / MockK Maven Kotlin plugin
要点整理:
- 言語自体は 2 年に 1 度 major(1.x → 2.x)、半年に 1 度 minor。
- マルチプラットフォームはもう「実験」ではない。iOS stable がゲームチェンジャー。
- サーバ陣営は Spring Boot と Ktor の両方が健在。
- ライブラリ陣営(Koin/Arrow/Exposed/Kotest/MockK)が分厚く、Kotlin らしい流儀でフルスタックを組める。
この座標の上で、各エリアを一つずつ深掘りする。
2 章 · Kotlin 2.1(2024.11)— K2 デフォルト + マルチドル文字列
Kotlin 2.0 が K2 コンパイラを stable に昇格した最初のリリースなら、2.1 はそれを **全員に強制**したリリース。JetBrains は同時に IntelliJ IDEA の K2 モードもデフォルトにし、K1 フォールバックは 2025 年末までしかサポートしない。
2.1 のヘッドライン機能:
1. **K2 コンパイラがデフォルト** — `-language-version 2.0` 以上はすべて K2。
2. **マルチドル(`$$`、`$$$`)文字列補間** — テンプレートや LaTeX を扱うときの `$` エスケープ地獄から解放。
3. **`when` 式の guard condition** — `when (x) { is Foo if x.bar > 10 -> ... }` で分岐に追加条件をインラインで書ける。
4. **`.kotlin` キャッシュディレクトリ** — Gradle の `.gradle` のように、ビルド成果物をプロジェクト直下に集約。
5. **non-local `break` / `continue`** — inline ラムダ内からも外側のループを抜けられる(preview)。
マルチドル文字列は本当に楽になる。
// Kotlin 2.1: $$"..."$$ 内では単一の $ はリテラル、$$ で補間開始
val template = $$"""
Hello, $$name!
Your balance is $1000 (USD).
JSON: {"value": "$$value"}
"""
従来は毎回 `"\$1000"` のように `$` をエスケープするか、raw string にさらに別の文字列を継ぎ足す必要があった。これが一行で終わる。
`when` guard も頻出。
sealed interface Order
data class Pending(val amount: Int) : Order
data class Paid(val amount: Int, val txId: String) : Order
fun handle(order: Order) = when (order) {
is Pending if order.amount > 10_000 -> "high-value pending"
is Pending -> "pending"
is Paid -> "paid: ${order.txId}"
}
K1 では `is Pending` 分岐の中で `if` をネストする必要があり、その瞬間に exhaustive チェックが効かなくなった。今や一行で終わり、網羅性も維持される。
3 章 · Kotlin 2.2(2025.3)— context parameters
Kotlin 2.2 のヘッドラインは **context parameters** — 1.7 からベータで動いていた「context receivers」の正式後継。
何を解決するのか
関数に **暗黙的に** 依存性を注入したいことがある。例えば:
// 従来: 毎回 logger を明示的に受け取る
fun calculate(x: Int, y: Int, logger: Logger): Int {
logger.info("calc $x + $y")
return x + y
}
// あるいはクラスで包む
class Calculator(private val logger: Logger) {
fun calculate(x: Int, y: Int): Int { ... }
}
context parameters は **シグネチャに依存性を宣言しつつ、呼び出し側は明示的に渡さなくてよい** 中間路線。
// Kotlin 2.2 context parameters
context(logger: Logger)
fun calculate(x: Int, y: Int): Int {
logger.info("calc $x + $y")
return x + y
}
// 呼び出し側: スコープに Logger を持ち込めば自動注入
fun main() {
with(MyLogger()) {
val result = calculate(1, 2) // logger 明示なし
}
}
context receivers と何が違うか
旧 1.x の `context(Logger)` は **名前が無かった**。同じ型のコンテキストが二つ入ると衝突。2.2 の `context(logger: Logger)` は **名前付き**。Arrow の effect ライブラリ、Compose の CompositionLocal、structured logging が軒並みこれを基盤に書き直されている。
実例: Arrow の raise
context(raise: Raise<String>)
fun parsePositive(s: String): Int {
val n = s.toIntOrNull() ?: raise.raise("not a number: $s")
if (n <= 0) raise.raise("must be positive: $n")
return n
}
// 呼び出し側
fun main() {
val result = either {
val n = parsePositive("42")
n * 2
}
// result: Either.Right(84)
}
`Either<E, A>` のような結果型を露出させずにエラーチャネルを合成できる。Scala の ZIO や Haskell の monad transformer 流の effect system を Kotlin らしく落とし込んだ解。
4 章 · K2 コンパイラ — 何が速くなり、何が変わるのか
K2 はコンパイラのフロントエンドを **全面書き直し** した成果物。K1 は 2010 年代初頭の設計で、型推論・smart cast・generic inference のコードが複数のパスに散らばっていた。K2 は **FIR(Frontend IR)** という単一 IR に統一した。
体感効果:
| 指標 | K1 | K2 | 備考 |
|---|---|---|---|
| クリーンビルド | 1.0x | 1.6 〜 1.9x 高速 | 大規模プロジェクトほど差が大きい |
| インクリメンタルビルド | 1.0x | 2.0 〜 2.4x 高速 | キャッシュ / invalidation 改善 |
| IDE highlight | 1.0x | 1.5x 高速 | smart cast / 推論キャッシュ |
| ピークメモリ | 1.0x | 約 0.7x | FIR 統合で重複削減 |
数値は JetBrains 公式ベンチマーク + メルカリ・Square のマイグレーション報告の平均。
Smart cast がさらに賢くなった
K1 は複雑な分岐で一貫した型の絞り込みが苦手だった。
fun process(value: Any?) {
if (value is String || value is Int) {
// K1: value は依然 Any?
// K2: value は String | Int(intersection)
println(value.hashCode()) // K2 なら問題なく呼べる
}
}
K2 は **`val` の遅延初期化** パターンも認識する。
class Holder {
val data: List<Int>
init {
val tmp = mutableListOf<Int>()
tmp.add(1); tmp.add(2)
data = tmp.toList() // K2: OK
}
}
コンパイラプラグイン API の安定化
Compose コンパイラプラグイン、kotlinx-serialization、Arrow の raise プラグインがすべて K2 FIR ベースで書き直された。結果としてビルド時間が短縮、IDE インデックスも安定。
マイグレーションチェックリスト
- `kotlin.languageVersion = "2.1"` に上げる。
- `kotlin.compiler.execution.strategy = in-process`(Gradle daemon)。
- Compose プロジェクトは `compose-compiler-gradle-plugin`(2024 年から JetBrains が直接配布)を使う。
- `-Xuse-fir-lt` のような旧フラグを削除。
5 章 · Compose Multiplatform — iOS stable!
2024 年 10 月の Compose Multiplatform 1.7 は本当に大きな節目だった。**iOS ターゲットが stable** に昇格。それまで Compose-Android は本番品質だったが iOS はベータ。1.7 以降は本番 OK。
1.7 ヘッドライン(2024.10)+ 1.7+ の積み増し
- **iOS stable** — UIViewController 統合、テキスト入力、アクセシビリティ、ダークモードすべて stable。
- **Resource API 1.0** — drawable / string / font を `Res.drawable.icon` のような型安全プロキシで参照。
- **adaptive layouts** — `WindowSizeClass` API。スマホ / タブレット / フォルダブルの分岐。
- **Skia 0.8 → 0.10** — テキスト描画品質、GPU メモリ改善。
- **ホットリロード(desktop)** — Java 21 の enhanced class redefinition を活用。デザインループが本当に速い。
1 画面、4 プラットフォーム
// commonMain/HelloApp.kt
@Composable
fun HelloApp(name: String) {
MaterialTheme {
Column(modifier = Modifier.padding(16.dp)) {
Text("Hello, $name!", style = MaterialTheme.typography.headlineSmall)
Spacer(Modifier.height(8.dp))
Button(onClick = { /* ... */ }) {
Text("Tap me")
}
}
}
}
このまま Android、iOS、macOS / Windows / Linux デスクトップ、そして(実験的に)Web Wasm で動く。プラットフォーム固有部分だけ `expect` / `actual` に切り出す。
// commonMain
expect fun platformName(): String
// androidMain
actual fun platformName(): String = "Android ${Build.VERSION.RELEASE}"
// iosMain
actual fun platformName(): String =
UIDevice.currentDevice.systemName + " " + UIDevice.currentDevice.systemVersion
Compose vs SwiftUI 比較(2026)
| 項目 | Compose Multiplatform 1.7+ | SwiftUI |
|---|---|---|
| プラットフォーム | Android / iOS / Desktop / Web | Apple のみ |
| 言語 | Kotlin | Swift |
| コード共有 | 100%(UI まで) | 0%(他プラットフォーム) |
| iOS パフォーマンス | 95%(スクロール / アニメーション一部 gap 残) | 100% native |
| ネイティブウィジェット | `UIViewControllerRepresentable` 風の interop | 自然 |
| ビルド時間 | KMP のビルドオーバーヘッドあり | Xcode 標準 |
選び方:
- iOS のみ → SwiftUI。
- Android + iOS、デザイン一貫性が重要 → CMP。
- 「Apple の新 API をその日から使う」 → SwiftUI。
6 章 · KMP 2.1 — production-ready
Compose Multiplatform が UI なら、**KMP(Kotlin Multiplatform)** は **ロジック共有**。ビジネスロジック、ネットワーキング、ディスクキャッシュ、ドメインモデルを Kotlin で 1 度書いて、Android・iOS・サーバ・Web で使い回す。
KMP モジュール構成
shared/
build.gradle.kts
src/
commonMain/kotlin/ <- 全プラットフォーム共通コード
androidMain/kotlin/ <- Android 専用
iosMain/kotlin/ <- iOS 専用(Kotlin/Native)
jvmMain/kotlin/ <- JVM サーバ用
wasmJsMain/kotlin/ <- Wasm Web 用
commonTest/kotlin/ <- 共通テスト
コアライブラリ
- **kotlinx.coroutines** — どのプラットフォームでも同じ API。
- **kotlinx.serialization** — JSON / Protobuf / CBOR。multiplatform 標準。
- **Ktor Client** — multiplatform HTTP / WebSocket。
- **SQLDelight 2** — 型安全 SQL ドライバ。iOS / Android / JVM / Wasm 対応。
- **Multiplatform Settings** — UserDefaults / SharedPreferences / ファイルを抽象化。
- **Decompose / Voyager** — multiplatform ナビゲーション。
- **Koin** — DI、multiplatform。
iOS 統合 — KMP 成果物を Xcode へ
// shared/build.gradle.kts
kotlin {
iosX64()
iosArm64()
iosSimulatorArm64()
cocoapods {
version = "1.0"
summary = "Shared module for MyApp"
homepage = "https://example.com"
ios.deploymentTarget = "15.0"
framework {
baseName = "Shared"
isStatic = false
}
}
}
./gradlew :shared:podPublishXcFramework
成果物を Xcode プロジェクトの Podfile に追加
Swift 側はそのまま import。
let repo = UserRepository()
Task {
let users = try await repo.fetchUsers()
print(users)
}
Kotlin の `suspend fun` は Swift の `async throws` に自動マッピングされる(2.1 と Kotlin/Native の swift-export 改善のおかげ)。
メルカリ、マクドナルドなどの事例
- **メルカリ** — 検索 / 決済のコアロジックを KMP に移行。Android / iOS のバグが 1 か所で直る。
- **マクドナルド** — Global Mobile App を KMP ベースで再構築。
- 国内事例(メルカリ・ZOZO・CyberAgent)は 13 章で詳しく。
7 章 · Ktor 3(2024.10)— WebAssembly ターゲット
Ktor 3 は 2024 年 10 月リリース。「v2 のマイナーアップ」ではなく **ほぼ書き直し** のメジャー。
ヘッドライン
1. **kotlinx-io ベースに書き直し** — okio / java.nio 依存を撤廃。スループット平均 +90%。
2. **WebAssembly ターゲット** — Kotlin/Wasm で Ktor サーバが組める。エッジコンピュートのシナリオ。
3. **CIO エンジン HTTP/2 stable** — 外部依存なしで HTTP/2 サーバを立てられる。
4. **Server-Sent Events プラグイン** — `install(SSE)`。
5. **WebSocket extensions** — Compression、ping / pong を再設計。
最小 Ktor 3 サーバ
// build.gradle.kts
plugins {
kotlin("jvm") version "2.1.0"
application
}
dependencies {
implementation("io.ktor:ktor-server-core:3.0.0")
implementation("io.ktor:ktor-server-cio:3.0.0")
implementation("io.ktor:ktor-server-content-negotiation:3.0.0")
implementation("io.ktor:ktor-serialization-kotlinx-json:3.0.0")
}
// src/main/kotlin/Application.kt
@Serializable
data class User(val id: Long, val name: String)
fun main() {
embeddedServer(CIO, port = 8080) {
install(ContentNegotiation) { json() }
routing {
get("/users") {
call.respond(listOf(User(1, "Alice"), User(2, "Bob")))
}
}
}.start(wait = true)
}
`./gradlew run` で 8080 から JSON が返る。coroutine ベースなので thread-per-request ではなく、1 スレッドが数千コネクションを捌く。
Spring Boot vs Ktor — どこで何を使うか
| 項目 | Ktor 3 | Spring Boot 3.5 + Kotlin |
|---|---|---|
| 哲学 | minimal、opt-in plugins | 「convention over config」 |
| 並行モデル | coroutine native | WebFlux(reactive)or virtual threads |
| エコシステム | 軽量 | 巨大、なんでもある |
| コールドスタート | 速い | GraalVM native image なら速い |
| 学習コスト | 短い | 長いが資料豊富 |
| 向き | マイクロサービス、エッジ、MVP | 大型モノリス、エンタープライズ |
8 章 · Spring Boot + Kotlin — JVM サーバ
JVM サーバで Kotlin を使うと言われたとき、企業の 70% は依然 Spring Boot。そして Spring チームはそのトラフィックを無視しなかった。Spring Framework 6、Boot 3 系列は Kotlin サポートを「一級」に格上げした。
モダン Spring Boot + Kotlin スタック(2026)
- **Spring Boot 3.5**(Java 21 baseline、Kotlin 2.1+)
- **Spring WebFlux + coroutines** — `suspend` 関数をコントローラで直接受ける。
- **R2DBC + Kotlin Coroutines** — async DB。
- **Spring Security 6** — Kotlin DSL。
- **Spring AOT + GraalVM native image** — コールドスタート 100 ms 未満。
Coroutine コントローラ
@RestController
class UserController(private val repo: UserRepository) {
@GetMapping("/users/{id}")
suspend fun getUser(@PathVariable id: Long): UserDto =
repo.findById(id)?.toDto() ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
@GetMapping("/users", produces = [MediaType.APPLICATION_NDJSON_VALUE])
fun streamUsers(): Flow<UserDto> =
repo.findAll().map { it.toDto() }
}
`suspend fun` をそのまま受け取る。WebFlux の `Mono` / `Flux` を変換する必要はない。`Flow<UserDto>` は NDJSON ストリーミングレスポンスへ自動変換。
Coroutine リポジトリ(R2DBC)
interface UserRepository : CoroutineCrudRepository<UserEntity, Long> {
suspend fun findByEmail(email: String): UserEntity?
@Query("SELECT * FROM users WHERE created_at > :since")
fun findRecentUsers(since: Instant): Flow<UserEntity>
}
Kotlin DSL コンフィグ
@Configuration
class AppConfig {
@Bean
fun routes(handler: UserHandler) = coRouter {
accept(MediaType.APPLICATION_JSON).nest {
GET("/users", handler::list)
POST("/users", handler::create)
}
}
@Bean
fun securityFilter(http: ServerHttpSecurity): SecurityWebFilterChain =
http {
authorizeExchange {
authorize("/public/**", permitAll)
authorize(anyExchange, authenticated)
}
oauth2ResourceServer { jwt {} }
}
}
`http { ... }` が Kotlin DSL。XML / Java config のボイラープレートが消える。
9 章 · kotlinx.coroutines + Flow — async モデル
Kotlin の async モデルは 2 軸。**coroutines**(一度完結する非同期処理)と **Flow**(時間軸を流れる値のストリーム)。
Coroutines 基本
suspend fun fetchUser(id: Long): User { /* HTTP 呼び出し */ }
suspend fun fetchOrders(userId: Long): List<Order> { /* HTTP 呼び出し */ }
suspend fun loadProfile(id: Long): Profile = coroutineScope {
val userDeferred = async { fetchUser(id) }
val ordersDeferred = async { fetchOrders(id) }
Profile(userDeferred.await(), ordersDeferred.await())
}
`coroutineScope` 内で 2 つのタスクが並列に走り、どちらかが失敗すればもう一方も cancel — **structured concurrency**。
Flow — cold stream
fun userUpdates(userId: Long): Flow<UserEvent> = flow {
while (currentCoroutineContext().isActive) {
val event = pollEvent(userId)
if (event != null) emit(event)
delay(1000)
}
}
// 消費側
suspend fun watchUser() {
userUpdates(42L)
.filter { it.type == EventType.UPDATED }
.map { it.toDto() }
.take(10)
.collect { println(it) }
}
Flow は **cold** — `.collect` を呼ぶたびに最初から再実行。hot stream が要るなら `SharedFlow` / `StateFlow`。
StateFlow — UI state holder
class UserViewModel(private val repo: UserRepository) {
private val _state = MutableStateFlow<UserState>(UserState.Loading)
val state: StateFlow<UserState> = _state.asStateFlow()
fun load(id: Long) {
viewModelScope.launch {
_state.value = UserState.Loading
_state.value = runCatching { repo.findById(id) }
.fold(
onSuccess = { UserState.Loaded(it) },
onFailure = { UserState.Error(it.message ?: "") }
)
}
}
}
Compose では `val state by viewModel.state.collectAsState()` で受けてそのまま描画。
Coroutine デバッガ
IntelliJ の `Debug` メニュー → `Coroutines Dump`。どの coroutine がどこで suspended かをツリーで表示。Java スレッドダンプとは比較にならない便利さ。
10 章 · Detekt / Konsist — 静的解析 + アーキテクチャテスト
Kotlin のコード品質を自動で守る 2 つの道具。
Detekt — コードスメル静的解析
// build.gradle.kts
plugins {
id("io.gitlab.arturbosch.detekt") version "1.23.7"
}
detekt {
toolVersion = "1.23.7"
config.setFrom("$rootDir/detekt.yml")
buildUponDefaultConfig = true
}
`detekt.yml` 抜粋:
complexity:
CyclomaticComplexMethod:
threshold: 15
LongMethod:
threshold: 60
naming:
FunctionNaming:
functionPattern: '[a-z][a-zA-Z0-9]*'
style:
MagicNumber:
ignoreNumbers: ['-1', '0', '1', '2']
CI 連携:
./gradlew detekt
結果: build/reports/detekt/detekt.html
K2 互換は 1.23 から stable、2025 年半ばの 1.24 からは K2 専用解析ルール(smart-cast hint、sealed exhaustive など)が追加された。
Konsist — アーキテクチャテスト
ArchUnit の Kotlin 版。**レイヤ依存、命名規則、アノテーション利用** をユニットテストとして検証する。
// src/test/kotlin/ArchitectureTest.kt
class ArchitectureTest {
@Test
fun `repositories should not depend on controllers`() {
Konsist.scopeFromProject()
.classes()
.withNameEndingWith("Repository")
.assertTrue { repo ->
repo.containingFile.imports
.none { it.name.contains("controller") }
}
}
@Test
fun `all use cases end with UseCase`() {
Konsist.scopeFromPackage("..usecase..")
.classes()
.assertTrue { it.name.endsWith("UseCase") }
}
}
`./gradlew test` で自動実行。新人が「controller から repository を直接呼び出す」PR を出すと CI が赤くなる。
Detekt が「ファイル内のコード品質」、Konsist が「プロジェクト全体の構造」。両者は補完関係。
11 章 · Koin / Arrow / Exposed / Kotest / MockK — ライブラリ陣営
Java の Spring / Hibernate / Mockito に対応する「Kotlin native」ライブラリたち。
Koin — DSL ベースの DI
val appModule = module {
single<UserRepository> { UserRepositoryImpl(get()) }
single<HttpClient> {
HttpClient(CIO) {
install(ContentNegotiation) { json() }
}
}
viewModel { UserViewModel(get()) }
}
fun main() {
startKoin {
modules(appModule)
}
// ...
}
リフレクションなし。Dagger のような compile-time generation もなし。KMP 互換。Compose Multiplatform でもそのまま使われる。
Arrow — Kotlin の FP 標準
sealed interface UserError {
object NotFound : UserError
data class Invalid(val reason: String) : UserError
}
fun parseAge(s: String): Either<UserError, Int> = either {
val n = s.toIntOrNull() ?: raise(UserError.Invalid("not a number: $s"))
if (n < 0 || n > 150) raise(UserError.Invalid("age out of range: $n"))
n
}
fun loadUser(id: Long): Either<UserError, User> = either {
val user = repo.find(id) ?: raise(UserError.NotFound)
user
}
fun process(id: Long, ageStr: String): Either<UserError, Result> = either {
val user = loadUser(id).bind()
val age = parseAge(ageStr).bind()
Result(user, age)
}
**`Either<L, R>`** と **`raise` DSL** の組み合わせで throw なしにエラーを合成。2.2 の context parameters と組み合わせると effect system が完成する。
Exposed — 型安全 SQL DSL
object Users : LongIdTable("users") {
val name = varchar("name", 100)
val email = varchar("email", 200).uniqueIndex()
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
}
transaction {
val newId = Users.insertAndGetId {
it[name] = "Alice"
it[email] = "alice@example.com"
}
val users = Users
.selectAll()
.where { Users.name like "A%" }
.orderBy(Users.createdAt to SortOrder.DESC)
.limit(10)
.map { it[Users.name] to it[Users.email] }
}
JPA より軽量で、Hibernate の lazy-loading の罠もない。R2DBC アダプタで coroutine 環境でも動く(1.0 から stable)。
Kotest — BDD スタイルのテスト
class UserSpec : StringSpec({
"user with valid email should be created" {
val u = User("alice@example.com")
u.isValid shouldBe true
}
"negative age should throw" {
shouldThrow<IllegalArgumentException> {
User("a@b", age = -1)
}
}
})
class PropertySpec : StringSpec({
"reverse twice is identity" {
checkAll<List<Int>> { list ->
list.reversed().reversed() shouldBe list
}
}
})
JUnit 互換、式ベースの assertion、property-based testing(QuickCheck 流)を内蔵。multiplatform。
MockK — pure Kotlin mocking
class UserServiceTest : StringSpec({
val repo = mockk<UserRepository>()
val service = UserService(repo)
"should return user from repo" {
coEvery { repo.findById(1L) } returns User(1, "Alice")
val u = service.getUser(1L)
u.name shouldBe "Alice"
coVerify(exactly = 1) { repo.findById(1L) }
}
})
Mockito が扱えない `object`、`companion object`、トップレベル関数、suspend 関数を全部 mock できる。
12 章 · Gradle Kotlin DSL — ビルド標準
2026 年時点で **新規 Kotlin プロジェクトの 99% は Gradle Kotlin DSL**(`build.gradle.kts`)。Groovy DSL はレガシー。
最小 `build.gradle.kts`
plugins {
kotlin("jvm") version "2.1.0"
kotlin("plugin.serialization") version "2.1.0"
application
}
group = "com.example"
version = "0.1.0"
repositories {
mavenCentral()
}
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
testImplementation(kotlin("test"))
testImplementation("io.kotest:kotest-runner-junit5:5.9.1")
}
application {
mainClass.set("com.example.AppKt")
}
kotlin {
jvmToolchain(21)
}
tasks.test {
useJUnitPlatform()
}
Multi-module + version catalog
`gradle/libs.versions.toml`:
[versions]
kotlin = "2.1.0"
coroutines = "1.9.0"
ktor = "3.0.0"
[libraries]
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
ktor-server-cio = { module = "io.ktor:ktor-server-cio", version.ref = "ktor" }
[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
ktor = { id = "io.ktor.plugin", version.ref = "ktor" }
各モジュールの `build.gradle.kts`:
plugins {
alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.ktor)
}
dependencies {
implementation(libs.ktor.server.core)
implementation(libs.ktor.server.cio)
implementation(libs.kotlinx.coroutines)
}
バージョンを 1 か所で管理。30 モジュール超のプロジェクトで真価を発揮する。
configuration cache + build cache
gradle.properties
org.gradle.configuration-cache=true
org.gradle.caching=true
org.gradle.parallel=true
kotlin.incremental=true
kotlin.code.style=official
設定キャッシュは 8.x から stable。ビルド時間は明確に 2〜5 倍速くなる(特にインクリメンタル)。
Maven は死んだか?
否。**Spring Boot エンタープライズ + 既存 Maven 資産の大きい組織** は依然 Maven Kotlin plugin を使う。
機能的には同等。Gradle より遅いが安定。
13 章 · 韓国 / 日本 — カカオ、トス、メルカリ、ZOZO、CyberAgent
韓国
**カカオ(Android 全社 Kotlin)**
- KakaoTalk Android コードベースの 95% 以上が Kotlin。新規 Java コード禁止。
- 100 以上のモジュールで multi-module、Gradle Kotlin DSL + version catalog。
- 社内で Detekt + カカオ独自ルール(`KakaoCodeStyle`)を配布。
- Compose 移行進行中(2026 年時点、新規画面は 100% Compose)。
**トス(Toss)— Server-side Kotlin の先駆者**
- バックエンドの新規マイクロサービスは 100% Kotlin + Spring Boot。200 以上のサービスが Kotlin。
- Coroutine + WebFlux + R2DBC + Arrow の組み合わせが標準。
- 社内 Kotlin DSL ライブラリ(`tossopen-kotlin-commons`)多数。
- トス技術ブログに「Spring の Kotlin マイグレーション」「なぜ Java ではなく Kotlin か」シリーズが多数。
**LINE(NAVER)— Kotlin Multiplatform ケース**
- LINE メッセンジャーのクライアント SDK の一部を KMP で共有。2026 年時点で本番一部導入。
日本
**メルカリ — KMP の先駆者**
- 検索 / 決済のコア SDK を KMP で再構築。Android / iOS のバグ修正が 1 か所で済む。
- 2025 年発表:「共有ビジネスロジックの 60% を KMP に移行した」。
- Compose Multiplatform 1.7+ を評価中。
**ZOZOTOWN(ZOZO)**
- Android はフル Kotlin。サーバ一部 Kotlin(Spring Boot + Coroutines)。
- 社内 "Kotlin Guild" — 隔週勉強会、ライブラリ共有。
**CyberAgent(AbemaTV、FRIDAY ほか)**
- Android 新規プロジェクトは 100% Kotlin。
- AbemaTV Android — Compose + Coroutines + Koin + Coil。
- 一部マイクロサービスで Ktor 3 を導入(ストリーミングメタデータサービス)。
**DeNA / GREE / 楽天**
- 同様パターン:Android フル Kotlin、サーバ部分的に Kotlin。
共通パターン
韓国・日本の大企業すべてに共通:
1. Android は **100% Kotlin** が既に完了。
2. サーバは **新規マイクロサービスから** Kotlin へ移行。
3. KMP は **コア SDK 中心の選択的導入**(アプリ全体 KMP はまだ稀)。
4. 社内コーディングガイドは **Detekt ベース + 自社ルール**。
5. 採用市場:Kotlin 経験者 = Android + Server 両面に魅力。
14 章 · 誰が Kotlin を選ぶべきか — Android / KMP / JVM サーバ / FP
最後に意思決定マトリクス。「Kotlin が正解か」シナリオ別の答え。
「Android アプリを書く」
→ **Kotlin がデフォルト。他の選択肢が事実上ない。**
- Android Studio が Kotlin 優先。
- Jetpack Compose の正式言語。
- Google の新ライブラリ / ドキュメントはすべて Kotlin 優先。
「iOS + Android 両方、1 チームで」
→ **KMP + Compose Multiplatform を検討。**
条件:
- iOS の新 API をその日から使う必要がない(SwiftUI / AppKit の新機能を 1〜2 か月遅れで OK)。
- ビジネスロジックが両プラットフォームで同一。
- iOS デザイナーが「これは正確に iOS-native でなければ」と固執しない。
3 つすべて OK なら KMP。1 つでも NG ならネイティブ 2 本立て。
「Spring Boot 環境で JVM サーバを書く」
→ **Kotlin が Java よりほぼ全方面で優位。**
- Null safety = NPE をコンパイル時に潰す。
- Coroutines = `CompletableFuture` より圧倒的に読みやすい。
- Data class = Lombok 不要。
- Spring 6 / Boot 3.5 = Kotlin 一級サポート。
例外:チームの 80% が Java しか知らない → 段階導入(テストコードから、新規マイクロサービスから)。
「マイクロサービスを軽量に、GraalVM native image で」
→ **Ktor 3 + Kotlin/Native、または Ktor 3 + GraalVM。**
- コールドスタート 100 ms 未満。
- メモリ 50 MB 未満。
- ラムダ / エッジ関数にぴったり。
「関数型プログラミングを本気で」
→ **Kotlin + Arrow。ただし学習曲線は急。**
- Either / IO / context parameters / raise DSL の組み合わせ。
- Scala や Haskell ほど深くはないが、JVM 陣営における「産業向き FP」の sweet spot。
「データエンジニアリング、Spark / Flink」
→ **Scala が依然優位。Kotlin は補助。**
- Spark Kotlin API は存在するが Scala ほど成熟していない。
- ただし KEDB(Kotlin Embedded DB)など新興ツールは Kotlin 優先。
「Android でも JVM でもない」
→ Kotlin は別に来なくてよい。JS / Wasm ターゲットはあるが、その領域では TypeScript / Rust がデフォルト。
参考 / References
Kotlin 言語・コンパイラ公式
- Kotlin Blog — https://blog.jetbrains.com/kotlin/
- Kotlin 2.1.0 released — https://blog.jetbrains.com/kotlin/2024/11/kotlin-2-1-0-released/
- Kotlin 2.2.0 released — https://blog.jetbrains.com/kotlin/2025/03/kotlin-2-2-released/
- Kotlin 公式ドキュメント — https://kotlinlang.org/docs/home.html
- K2 compiler announcement — https://blog.jetbrains.com/kotlin/2024/04/k2-compiler-performance-benchmarks-and-how-to-measure-them-on-your-projects/
- KEEP (Kotlin Evolution and Enhancement Process) — https://github.com/Kotlin/KEEP
- Context parameters KEEP — https://github.com/Kotlin/KEEP/blob/master/proposals/context-parameters.md
Compose Multiplatform / KMP
- Compose Multiplatform — https://www.jetbrains.com/lp/compose-multiplatform/
- Compose Multiplatform 1.7 release (iOS stable) — https://blog.jetbrains.com/kotlin/2024/10/compose-multiplatform-1-7-0-release/
- Kotlin Multiplatform 公式 — https://kotlinlang.org/docs/multiplatform.html
- KMP wizard — https://kmp.jetbrains.com/
Ktor / Spring
- Ktor 3 release — https://blog.jetbrains.com/kotlin/2024/10/ktor-3-released/
- Ktor 公式ドキュメント — https://ktor.io/docs/welcome.html
- Spring Boot Kotlin support — https://docs.spring.io/spring-framework/reference/languages/kotlin.html
- Spring Boot + Coroutines — https://docs.spring.io/spring-framework/reference/languages/kotlin/coroutines.html
kotlinx ライブラリ
- kotlinx.coroutines — https://github.com/Kotlin/kotlinx.coroutines
- kotlinx.serialization — https://github.com/Kotlin/kotlinx.serialization
- kotlinx-io — https://github.com/Kotlin/kotlinx-io
静的解析・テスト・DI・FP・ORM
- Detekt — https://detekt.dev/
- Konsist — https://docs.konsist.lemonappdev.com/
- Koin — https://insert-koin.io/
- Arrow — https://arrow-kt.io/
- Exposed — https://www.jetbrains.com/help/exposed/home.html
- Kotest — https://kotest.io/
- MockK — https://mockk.io/
Gradle / ビルド
- Gradle Kotlin DSL primer — https://docs.gradle.org/current/userguide/kotlin_dsl.html
- Version catalogs — https://docs.gradle.org/current/userguide/platforms.html
企業ケース
- Toss 技術ブログ — https://toss.tech/
- カカオ技術ブログ — https://tech.kakao.com/
- Mercari Engineering Blog — https://engineering.mercari.com/blog/
- ZOZO Technologies — https://techblog.zozo.com/
- CyberAgent Developers Blog — https://developers.cyberagent.co.jp/blog/
- LINE Engineering — https://engineering.linecorp.com/
締めくくり。Kotlin 2.x はもはや「Java より少し良い Android 用言語」ではない。**コンパイラ(K2)、UI(Compose Multiplatform)、マルチプラットフォーム(KMP)、サーバ(Spring / Ktor)、ライブラリ陣営(Koin / Arrow / Exposed / Kotest)** が揃って stable に並んだ、2026 年 JVM 陣営のデフォルト言語である。本稿がその座標を取る助けになれば。
현재 단락 (1/627)
2017 年の Google I/O で Android 公式言語になった日から、Kotlin はしばらく「Android のための Java 代替」として生きてきた。サーバ陣営は Java 17、2...