필사 모드: Modern Kotlin 2026 — Kotlin 2.1, Compose Multiplatform, Ktor, Exposed, KSP, and Arrow Deep Dive
EnglishPrologue — Kotlin Has Become the Standard of the Multi-Runtime Era
Spring 2026: Kotlin is no longer "the Android language." On the server, Ktor 3 and Spring Boot 3.4 Kotlin DSL split the world; on mobile, Compose Multiplatform 1.7 builds iOS, Android, desktop, and web from one codebase; on the web, Kotlin/Wasm GC is mature enough to render React-style components. After JetBrains shipped the K2 compiler GA in Kotlin 2.0 (May 2024), versions 2.1 and 2.2 followed and compile times roughly doubled in speed, while compiler plugins consolidated under KSP 2.
This article walks the 2026 Kotlin stack end to end — language, concurrency, KMP, UI, server, DB, DI, testing, web, community — in one read. Every code sample is working code; library versions are pinned to what is current as of May 2026.
One-liner to remember: **Kotlin is no longer "a better language on the JVM"; it is "the multi-platform language of the multi-runtime era."**
Chapter 1 · Kotlin 2.1 and 2.2 — What the K2 Compiler Changed
Start with the language itself. The core of Kotlin 2.0 (May 2024) was the **K2 compiler GA**. K2 is a full rewrite of the compiler with a modular front-end (parser, type checker) and back-end (IR generation). The wins:
- ~**2x** faster average compile time (3x+ on big projects)
- Better IntelliJ responsiveness (K2 mode)
- A stable compiler-plugin API (Compose, kotlinx.serialization, Anvil)
Kotlin 2.1 (November 2024) stabilized:
- `when` expressions with guard conditions
- Non-local `break` and `continue` (preview)
- Multi-dollar interpolation (`$$"..."`) for literal `$` in strings
- `kotlin.uuid.Uuid` in the standard library
Kotlin 2.2 (June 2025) promoted **context parameters** to stable and simplified `expect`/`actual`. Context parameters replace the older `context receivers` with cleaner syntax.
context(logger: Logger)
fun process(input: String) {
logger.info("processing: $input")
}
// Call site
with(myLogger) {
process("hello")
}
The other 2.2 win: **simpler `expect`/`actual`**. A plain typealias is often enough now, and matching signatures need almost no boilerplate.
Chapter 2 · Coroutines 1.10 — Structured Concurrency, Complete
`kotlinx.coroutines` is the async standard in Kotlin. As of the 1.10 release in 2026:
**Core principle — structured concurrency**: every coroutine lives inside a parent `CoroutineScope`. Cancellation of the parent cancels children; failure of a child fails the parent (unless a `SupervisorJob` is in play).
suspend fun fetchUserData(): UserData = coroutineScope {
val profile = async { fetchProfile() }
val orders = async { fetchOrders() }
val recs = async { fetchRecommendations() }
UserData(profile.await(), orders.await(), recs.await())
}
`coroutineScope` cancels the rest and rethrows if any of the three fails — that is the essence of structured concurrency.
**Picking a dispatcher**:
- `Dispatchers.Main` — UI thread (Android, Compose)
- `Dispatchers.IO` — blocking I/O (file, DB, network)
- `Dispatchers.Default` — CPU-bound (JSON parsing, image work)
- `Dispatchers.Unconfined` — almost never use this
What is new in 1.10: `CoroutineStart.UNDISPATCHED_PROCESSING`, more precise cancellation propagation, and the deprecation of `Channel.consumeEach`.
One-liner to remember: **A coroutine is not a lightweight thread — it is a lightweight function call.**
Chapter 3 · Flow, StateFlow, SharedFlow — The Reactive Default
Kotlin's reactive API has replaced RxJava in most codebases. The three types differ:
| Type | Cold/Hot | Use case |
|------|----------|----------|
| `Flow` | Cold | One-shot async streams, new emitter each subscribe |
| `StateFlow` | Hot | Always holds the latest value — UI state |
| `SharedFlow` | Hot | Multi-subscriber event broadcast |
**Flow example — `combine`, `flowOn`, `stateIn`**:
val searchQuery: StateFlow<String> = ...
val filters: StateFlow<Filters> = ...
val results: StateFlow<List<Item>> = combine(searchQuery, filters) { q, f ->
q to f
}
.debounce(300)
.mapLatest { (q, f) -> repository.search(q, f) }
.flowOn(Dispatchers.IO)
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), emptyList())
`flowOn` changes the dispatcher of **upstream** operators (downstream still runs in the collector's context). `stateIn` turns a cold Flow into a hot StateFlow with a 5-second stop timeout — short subscription gaps (like screen rotation) do not re-trigger the search.
**`mapLatest` vs `flatMapLatest`**: cancel any in-flight work when a new value arrives. Use it for "only the latest matters" cases like search autocomplete.
**SharedFlow — an event bus**:
private val _events = MutableSharedFlow<UiEvent>(extraBufferCapacity = 1)
val events: SharedFlow<UiEvent> = _events.asSharedFlow()
fun trigger(e: UiEvent) {
_events.tryEmit(e)
}
Chapter 4 · Kotlin Multiplatform — Why KMP Is Now Stable Enough
KMP was declared stable in Kotlin 1.9.20 (November 2023). As of 2026, production adopters include:
- **Cash App** — shared iOS and Android business logic, multi-year track record
- **Netflix** — selective modules shared (2024 case study)
- **McDonald's Global Mobile App** — KMP and CMP iOS adoption (2024 KotlinConf keynote)
- **Forbes**, **Philips**, **Autodesk** — KMP in production
KMP structure is simple: the **common source set (`commonMain`)** holds platform-agnostic code; the **platform source sets (`androidMain`, `iosMain`, `jvmMain`, `jsMain`)** hold per-platform implementations.
// commonMain
expect fun platformName(): String
// androidMain
actual fun platformName(): String = "Android ${Build.VERSION.SDK_INT}"
// iosMain
actual fun platformName(): String = "iOS ${UIDevice.currentDevice.systemVersion}"
Kotlin 2.2 simplified `expect`/`actual` further. More cases now collapse to a plain typealias, and default implementations can live on the `expect` side.
**What to share**:
- Models and domain logic (e.g. a `Result<Either<Failure, Success>>` core)
- Networking (Ktor Client)
- Serialization (kotlinx.serialization)
- Storage (SQLDelight, Room KMP)
- Date and time (kotlinx-datetime)
- Coroutines (KMP-first since day one)
**What not to share**: UI is a choice. Share it with Compose Multiplatform, or split via SwiftUI on iOS.
Chapter 5 · Compose Multiplatform 1.7 — What iOS Stable Means
JetBrains' Compose Multiplatform (CMP) **promoted iOS to beta in 1.6.10 (May 2024)** and **stable in 1.7 (November 2024)**. As of May 2026 the stable line is 1.7.x.
CMP brings the Android Jetpack Compose UI toolkit to **every platform** via Skia:
- **Android** — runs on the same runtime as Jetpack Compose
- **iOS** — Skia + Metal direct rendering, with UIKit interop
- **Desktop (JVM)** — Skia + OpenGL/Direct3D
- **Web (Wasm GC)** — Skia compiled to Wasm
**iOS interop**: place a CMP composable inside a SwiftUI view, or a SwiftUI view inside a CMP composable (`UIKitView`, `UIViewController` wrappers).
@Composable
fun App() {
MaterialTheme {
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
Text("Hello from CMP 1.7", style = MaterialTheme.typography.headlineMedium)
// Same code runs on iOS, Android, desktop, and web
}
}
}
**Navigation 2**: still in dev as of 2026. A KMP-native navigation API for type-safe routing and deep links defined in shared code.
Chapter 6 · Jetpack Compose 1.7 — Strong Skipping and Performance
Android's Jetpack Compose enabled **strong skipping** by default in 1.7 (September 2024). Previously only types annotated `@Stable` would auto-skip during recomposition; with strong skipping, all functions skip by default, including those that capture lambdas.
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
// With strong skipping, this function will skip recomposition
// when user is the same — even if onClick is a fresh lambda.
Card(onClick = onClick) {
Text(user.name)
}
}
**Lazy layout improvements**: `LazyColumn`, `LazyRow`, and `LazyGrid` are faster at prefetch and sticky headers.
**Compose Compiler unification**: starting Kotlin 2.0, Compose Compiler ships inside Kotlin itself — no more version-matching games.
**Baseline performance patterns**:
- Avoid re-allocating lambdas every recomposition without `remember` — strong skipping helps, but memory pressure remains
- Use `derivedStateOf` to cache derived state
- Provide explicit `key` to avoid item-reorder rebuilds
- Don't extract Modifier chains into helper functions inside composables (they re-allocate each call)
One-liner to remember: **Compose is "declarative," but that declaration runs every frame — which is why skipping equals performance.**
Chapter 7 · Ktor 3.0 — The Server-Side Default
JetBrains' Ktor 3.0 (October 2024) promoted **JVM, Native, and JS** all as server targets. Compared to Spring Boot it is smaller, lighter, and coroutine-native.
fun main() {
embeddedServer(Netty, port = 8080) {
routing {
get("/") {
call.respondText("Hello Ktor 3.0")
}
get("/users/{id}") {
val id = call.parameters["id"]
call.respondText("user: $id")
}
}
}.start(wait = true)
}
**New in 3.0**:
- **SSE (Server-Sent Events)** plugin stable — drop-in for chatbots and live notifications
- **Content negotiation** for JSON/Protobuf/XML in one line
- **OpenTelemetry** plugin out of the box
- **HTTP/3** preview
install(SSE)
routing {
sse("/stream") {
repeat(10) { i ->
send(ServerSentEvent("tick: $i"))
delay(1000)
}
}
}
**Native build**: pair `kotlin-multiplatform` with `ktor-server-cio` to produce a single Linux/macOS binary — cold start on Lambda or Cloud Run becomes dramatically shorter.
Chapter 8 · Exposed 0.56 — The Kotlin ORM Standard
JetBrains' Exposed in 0.56 (2025) stabilized coroutine integration and R2DBC support. It offers two APIs:
**DSL API** — a builder that reads almost like SQL:
object Users : IntIdTable() {
val name = varchar("name", 50)
val email = varchar("email", 100).uniqueIndex()
val createdAt = datetime("created_at").defaultExpression(CurrentDateTime)
}
transaction {
Users.insert {
it[name] = "Alice"
it[email] = "alice@example.com"
}
Users.selectAll()
.where { Users.name like "A%" }
.map { it[Users.name] }
}
**DAO API** — entity-object mapping:
class User(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<User>(Users)
var name by Users.name
var email by Users.email
}
transaction {
val alice = User.new {
name = "Alice"
email = "alice@example.com"
}
}
**Alternatives**: **Komapper** (faster, compile-time codegen), **Ktorm** (lighter DSL), **JOOQ** (enterprise standard, Kotlin-friendly).
Chapter 9 · KSP 2.x — KAPT Is Dead
KSP (Kotlin Symbol Processing) replaces KAPT as the annotation-processor framework. KAPT was slow because it generated Java stubs to satisfy the Java annotation-processing API. KSP reads Kotlin compiler IR directly and is **about 2x faster**.
**KSP 2.x** (GA in 2024) runs on the K2 compiler. Most major annotation processors have migrated:
- **Room** — recommended on KSP
- **Dagger** / **Hilt** — stable on KSP
- **Moshi** — KSP only
- **kotlinx.serialization** — uses a compiler plugin (independent of KSP)
- **kotlin-inject** — KSP-based
- **AutoValue/AutoFactory** — ported to KSP
// build.gradle.kts
plugins {
id("com.google.devtools.ksp") version "2.1.0-1.0.29"
}
dependencies {
ksp("androidx.room:room-compiler:2.7.0")
}
If your project still uses KAPT, migrate — build time often drops by half overnight.
Chapter 10 · Arrow 2.0 — Typed Errors and the Raise DSL
Arrow is Kotlin's functional-programming library. Arrow 2.0 (January 2024) promoted the **`Raise` DSL** to stable, ushering in a new model for typed errors.
The older `Either<Failure, Success>` style required monad comprehension or chained `flatMap`:
// Arrow 1.x style
fun process(input: String): Either<Error, Result> = either {
val parsed = parse(input).bind()
val validated = validate(parsed).bind()
compute(validated).bind()
}
Arrow 2.0's `Raise` expresses the same semantics as a **function context**:
context(raise: Raise<Error>)
fun parse(input: String): Parsed = ...
context(raise: Raise<Error>)
fun process(input: String): Result {
val parsed = parse(input) // no bind needed
val validated = validate(parsed)
return compute(validated)
}
// Call site — catch once
val result: Either<Error, Result> = either {
process(userInput)
}
**Wins of `Raise`**:
- No more `bind()` calls — code flattens out
- Free movement between `Either`, `Result`, and `Option`
- Pairs naturally with Kotlin 2.2 context parameters (stable)
Arrow 2 also ships **optics** (deep immutable updates) and **typed FP utilities** (traverse, sequence, zip).
Chapter 11 · kotlinx.serialization 1.7 — JSON, Protobuf, CBOR Unified
JetBrains' serialization library in 1.7 (2024) covers **compile-time codegen** and **multiplatform** at once. No reflection means it works on Kotlin/Native and Wasm.
@Serializable
data class User(val id: Int, val name: String, val email: String)
val user = User(1, "Alice", "alice@example.com")
val jsonStr = Json.encodeToString(user)
val parsed = Json.decodeFromString<User>(jsonStr)
**1.7 highlights**: Protobuf, CBOR, and HOCON formats alongside JSON; `Json.encodeToStream` for streaming; improved polymorphic serialization.
@Serializable
sealed interface ApiResponse {
@Serializable @SerialName("success") data class Ok(val data: User) : ApiResponse
@Serializable @SerialName("error") data class Err(val code: Int, val message: String) : ApiResponse
}
val response: ApiResponse = Json.decodeFromString<ApiResponse>(jsonStr)
Ktor, Retrofit, and OkHttp all ship `kotlinx.serialization` converters as first-class citizens.
Chapter 12 · Dependency Injection — kotlin-inject, Koin 4, Anvil
Dagger 2 remains the JVM standard, but Kotlin and KMP have multiplied the options.
**kotlin-inject** (KSP-based, KMP-capable):
@Inject class UserService(private val repo: UserRepository)
@Component abstract class AppComponent {
abstract val userService: UserService
}
**Koin 4** (runtime DSL, easiest to learn):
val appModule = module {
single<UserRepository> { UserRepositoryImpl(get()) }
factory { UserService(get()) }
}
startKoin { modules(appModule) }
**Dagger Anvil** (Square): layers a Kotlin DSL on top of Dagger to reduce boilerplate; 2.5 added KSP support.
Decision rules:
- **Small app or KMP** → Koin 4
- **Compile-time verification matters** → kotlin-inject (KMP) or Dagger Anvil (Android)
- **Legacy large Android** → Dagger / Hilt
Chapter 13 · Kotlin/Native and iOS Interop
Kotlin/Native is the LLVM-based backend that compiles to machine code without a JVM. It targets iOS, macOS, Linux, Windows, and Wasm.
**iOS interop**: bidirectional with Objective-C and Swift. Since Swift 5.10, the (still experimental) `swift-export` feature produces a more idiomatic Swift API.
// Kotlin
class Greeter {
fun greet(name: String): String = "Hello, $name"
}
// In Swift
let greeter = Greeter()
let msg = greeter.greet(name: "Alice")
**Memory model**: Kotlin/Native switched to a **new memory model** in 2022. The earlier "freeze" rules are gone — multi-threaded code matches JVM semantics, and coroutines are thread-safe by default.
**Constraints**:
- iOS builds require macOS (Xcode)
- KMP `cinterop` wraps C headers but is verbose
- Kotlin/Native build time exceeds JVM build time (LLVM compilation cost)
Chapter 14 · Android 16 — SDK 35, Predictive Back, Material 3 Expressive
As of May 2026, Android 15 (API 35) is stable; Android 16 is in dev preview. What Kotlin developers should know:
**SDK 35 (Android 15)**:
- **Predictive Back** — the system back gesture previews the next screen; `OnBackPressedDispatcher` API changes
- **Edge-to-edge enforced** — content extends behind system bars when `targetSdk = 35`
- **15-second background task limit** — schedule heavy work with WorkManager
- **Foreground service types** are stricter
**Material 3 Expressive (Android 16 preview)**:
- More expressive motion and color
- New components: `LoadingIndicator`, `WavyProgress`, `ToolbarScaffold`
- Arriving in Compose via `androidx.compose.material3:1.4.x`
**Toolchain**:
- Android Studio Ladybug+ (October 2024 onward)
- Kotlin 2.x recommended
- Compose Compiler ships with Kotlin (no separate version pinning)
Chapter 15 · Server Side — Spring Boot, Micronaut, Helidon Nima
Kotlin is a first-class citizen on JVM servers. As of 2026 the main frameworks:
**Spring Boot 3.4** (November 2024): Kotlin DSL support, Virtual Threads (Loom) integration, GraalVM Native Image stable.
@SpringBootApplication
class Application
@RestController
class UserController(private val userService: UserService) {
@GetMapping("/users/{id}")
fun get(@PathVariable id: Long): User = userService.findById(id)
}
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
**Micronaut 4.7**: AOT compilation plus Kotlin Symbol Processing. Cold start is ~5x shorter than Spring Boot.
**Helidon Nima** (Oracle): a synchronous-style server running on Virtual Threads. Kotlin coroutine synergy requires wrappers, but the model — "write sync, run async" — is appealing.
**Decision rules**:
- Reuse existing Spring assets → Spring Boot 3.4 + Kotlin
- Native Image builds → Micronaut or Quarkus
- KMP server or lightweight microservices → Ktor 3
Chapter 16 · Gradle Kotlin DSL — Build Scripts in Kotlin
`build.gradle.kts` is effectively the standard. Compared to the Groovy DSL:
plugins {
kotlin("jvm") version "2.1.0"
kotlin("plugin.serialization") version "2.1.0"
id("com.google.devtools.ksp") version "2.1.0-1.0.29"
}
dependencies {
implementation("io.ktor:ktor-server-core:3.0.0")
implementation("io.ktor:ktor-server-netty:3.0.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.0")
testImplementation(kotlin("test"))
testImplementation("io.kotest:kotest-runner-junit5:5.9.0")
}
tasks.test {
useJUnitPlatform()
}
**Version catalogs** (`libs.versions.toml`) are recommended: centralize dependency versions, enforce consistency across modules.
**Configuration cache**: default since Gradle 8.x. After the first run, subsequent runs reuse the task graph for 30–70% speed-up.
Chapter 17 · Testing — JUnit 5, Kotest, MockK, Turbine
The 2026 Kotlin testing stack:
**JUnit 5 + `kotlin.test`**: the most common baseline. `@Test`, `@BeforeEach`, `@DisplayName` work as expected.
**Kotest 5.9**: BDD-style suites plus property-based testing.
class UserSpec : StringSpec({
"should return name in uppercase" {
User("alice").nameUpper() shouldBe "ALICE"
}
"all positive numbers double" {
checkAll<Int> { n ->
if (n > 0) (n * 2) shouldBeGreaterThan n
}
}
})
**MockK 1.13**: similar to Mockito but Kotlin-native. `coEvery` mocks coroutines naturally.
val repo = mockk<UserRepository>()
coEvery { repo.findById(1) } returns User(1, "Alice")
val service = UserService(repo)
runTest {
service.getName(1) shouldBe "Alice"
}
**Turbine** (Cash App): the standard for testing Flow.
runTest {
myFlow.test {
awaitItem() shouldBe "first"
awaitItem() shouldBe "second"
awaitComplete()
}
}
Chapter 18 · KMP Library Ecosystem — Datetime, IO, Crypto
After KMP went stable, JetBrains tidied up its standard library.
- **kotlinx-datetime** (0.6+) — multiplatform date/time, familiar if you know `java.time`
- **kotlinx-io** (0.5+) — `Source` and `Sink` IO, the spiritual successor to Okio
- **kotlinx-coroutines** — KMP-first from day one
- **kotlinx-serialization** — KMP-only by design
- **ktor-client** — multiplatform HTTP client
- **SQLDelight 2.x** — type-safe SQL, multiplatform
- **Multiplatform Settings** — per-platform key-value (SharedPreferences on Android, NSUserDefaults on iOS, etc.)
- **Compose Multiplatform** — the UI toolkit above
val now: Instant = Clock.System.now()
val zoned = now.toLocalDateTime(TimeZone.of("Asia/Seoul"))
val plus3h = now.plus(3.hours)
Chapter 19 · Kotlin/Wasm — New Possibilities for the Web
Kotlin 1.9.20 introduced the **Kotlin/Wasm** target. With the Wasm GC proposal stabilizing in Chrome and Firefox in 2024, Kotlin can now produce a Wasm binary without going through JavaScript.
**Why it matters**: Kotlin/JS produced large bundles and had a wide interop surface. Wasm GC puts a JVM/V8-style garbage collector inside the browser — Kotlin and Compose object models run with no translation.
**Status (May 2026)**: Kotlin/Wasm itself is alpha, but **Compose Multiplatform for Web** is nearly stable on the Wasm backend. JetBrains' live Compose Image Viewer demo is the proof.
**KVision**, **Kobweb**: full-stack Kotlin web frameworks built on Wasm/JS. Kobweb sits on Compose, KVision uses a React-like model.
// Compose for Web (Wasm GC)
@Composable
fun App() {
var count by remember { mutableStateOf(0) }
Column {
Text("Count: $count")
Button(onClick = { count++ }) { Text("Increment") }
}
}
Chapter 20 · Korean Kotlin Community — Kotlin Seoul and Kotlin Days Korea
Seoul has a lively Kotlin scene:
- **Kotlin Seoul** — regular meetups and side projects; one of JetBrains' recognized KUGs
- **Kotlin Days Korea** — annual conference run with JetBrains; held every year since 2023
- **Korean Android Developers** — Android and Kotlin community overlap
- **GDG Seoul Android** — Google Developer Group chapter
Learning resources: JetBrains Academy in Korean, the Korean translation of "Kotlin in Action" 2nd edition, and the translated "Kotlin Coroutines: Deep Dive."
The Kotlin hiring market in Korea is growing fast — beyond Android, in server (Ktor, Spring Boot Kotlin) and in fintech (KMP). As of 2026, Naver, Kakao, Toss, and Coupang all run Kotlin server stacks in production.
Chapter 21 · Japanese Kotlin Community — Kotlin Fest and DroidKaigi
Tokyo is equally active:
- **Kotlin Fest** — Japan's largest annual Kotlin conference; founded 2018, revived in 2024
- **DroidKaigi** — Android-focused, but more than half the sessions are Kotlin, and KMP/CMP talks grow yearly
- **JetBrains Tokyo** — JetBrains Japan's recurring events
- **Kotlin Tokyo** — a JetBrains-recognized KUG
Companies in production with Kotlin and KMP include **Cyberagent**, **DeNA**, **Mercari**, **Yahoo! Japan**, and **LINE**. Mercari's 2022 KMP rollout case study was presented at KotlinConf.
Learning resources: the Japanese edition of "Kotlin in Action," Wantedly and Mercari engineering blogs' Kotlin series, and the DroidKaigi video archive.
Chapter 22 · 2026 Kotlin Adoption Matrix — What to Use Where
To close, a plain matrix of **"build X, pick Y."**
| What you're building | Recommended stack |
|---------------------|------------------|
| Android-only app | Kotlin 2.x + Jetpack Compose 1.7 + Hilt/Koin + Room + Coroutines/Flow |
| iOS + Android (split UI) | KMP commonMain (Ktor Client + Serialization + SQLDelight) + native SwiftUI and Compose |
| iOS + Android + Desktop | Compose Multiplatform 1.7 + KMP commonMain |
| Server microservice | Ktor 3 or Spring Boot 3.4 Kotlin |
| Data-intensive server | Spring Boot + Exposed/JOOQ + Coroutines |
| Native CLI | Kotlin/Native + ktor-client + clikt |
| Full-stack web | Kobweb (Compose for Web) or KVision |
| Project with annotation processors | KSP 2.x (avoid KAPT) |
| FP-style domain model | Arrow 2 (Raise + Optics) |
One-liner to remember: **Kotlin is no longer a tool — it's an ecosystem. Whatever you're building, there is a Kotlin tool in the right slot already.**
Epilogue — The Era When Multiplatform Actually Works
Kotlin in 2026 has long outgrown its first identity as "a better Java on the JVM." K2 GA freed compile times, Compose Multiplatform 1.7 made iOS stable, and Wasm GC closed the last piece of the web puzzle. KSP 2 and Arrow 2 set the standard for compiler extensions and typed FP, and Ktor 3 settled into server-side life.
For someone touching Kotlin for the first time, learning Coroutines and Flow is the fastest way in. From there: Compose if you're on Android, Ktor if you're on the server, and the kotlinx-* KMP libraries if you're aiming at multiple platforms.
Closing line: **"Write once, runs everywhere" was often a lie — but in 2026 KMP, scoped to business logic, it is mostly true.**
References
1. [Kotlin Blog — Kotlin 2.0 Released](https://blog.jetbrains.com/kotlin/2024/05/kotlin-2-0-0-is-out/)
2. [Kotlin Blog — Kotlin 2.1.0 Released](https://blog.jetbrains.com/kotlin/2024/11/kotlin-2-1-0-released/)
3. [Kotlin Blog — Kotlin 2.2.0 Released](https://blog.jetbrains.com/kotlin/2025/06/kotlin-2-2-0-released/)
4. [Kotlin Multiplatform Stable Announcement](https://blog.jetbrains.com/kotlin/2023/11/kotlin-multiplatform-stable/)
5. [Compose Multiplatform 1.7 — iOS Stable](https://blog.jetbrains.com/kotlin/2024/11/compose-multiplatform-1-7-0-release/)
6. [Jetpack Compose 1.7 Release Notes](https://developer.android.com/jetpack/androidx/releases/compose)
7. [Kotlin Coroutines Documentation](https://kotlinlang.org/docs/coroutines-overview.html)
8. [Ktor 3.0 Release](https://blog.jetbrains.com/kotlin/2024/10/ktor-3-0-released/)
9. [Exposed — Kotlin SQL Framework](https://github.com/JetBrains/Exposed)
10. [KSP 2 Documentation](https://kotlinlang.org/docs/ksp-overview.html)
11. [Arrow 2.0 — Typed Errors](https://arrow-kt.io/learn/typed-errors/)
12. [kotlinx.serialization Guide](https://github.com/Kotlin/kotlinx.serialization)
13. [kotlin-inject](https://github.com/evant/kotlin-inject)
14. [Koin 4 Documentation](https://insert-koin.io/)
15. [Spring Boot 3.4 Release Notes](https://spring.io/blog/2024/11/21/spring-boot-3-4-0-available-now)
16. [Kotlin Multiplatform Libraries List](https://kotlinlang.org/docs/multiplatform-libraries.html)
17. [Kotlin/Wasm Documentation](https://kotlinlang.org/docs/wasm-overview.html)
18. [SQLDelight 2.x](https://github.com/cashapp/sqldelight)
19. [Kotest Documentation](https://kotest.io/)
20. [Turbine — Flow Testing](https://github.com/cashapp/turbine)
21. [Android 15 Behavior Changes](https://developer.android.com/about/versions/15/behavior-changes-15)
22. [Material 3 Expressive — Android Developers](https://developer.android.com/jetpack/compose/designsystems/material3)
현재 단락 (1/418)
Spring 2026: Kotlin is no longer "the Android language." On the server, Ktor 3 and Spring Boot 3.4 K...