Kotlin Multiplatform(KMP)は、JetBrainsが開発するオープンソース技術で、Android・iOS・デスクトップ・Web・サーバーの間でKotlinのコードを共有しながら、各プラットフォームのネイティブな利点を保てる点が特徴です。2023年11月のKotlin 1.9.20でStable(正式版)となり、2024年5月にはGoogleがAndroid公式のサポートを表明しました。なお、モバイル向けの呼称だったKMM(Kotlin Multiplatform Mobile)は2023年7月31日に非推奨となり、現在は対象プラットフォームの組み合わせにかかわらずKMPに統一されています。この記事では、KMPが共通コードを各OSのバイナリへ変換する仕組み、共有できる範囲と安定度、導入に必要な要件、そして採用を見送るべき条件までを公式ドキュメントの一次情報にもとづいて整理します。
まとめ
- KMPはKotlinのコードを複数プラットフォームへ共有する技術で、UIまで共有するかどうかは選択制です。ロジックだけ共有してUIはSwiftUI・UIKitのままにもできます。
- 共通コードから各OS固有のAPIを呼ぶ仕組みがexpected/actual宣言(
expect/actualキーワード)です。ただしexpect classはBeta扱いで、公式はインターフェースと依存性注入を優先するよう推奨しています。 - 安定度はプラットフォームごとに異なります。Android・iOS・デスクトップ(JVM)・サーバー(JVM)・Kotlin/JSがStable、Kotlin/Wasm・watchOS・tvOSはBetaです(2026年8月時点の公式表)。
- Android Gradle Plugin 9.0からは
com.android.libraryとKMPプラグインを併用できません。Android-KMPライブラリプラグインへの移行が必要で、既存プロジェクトの移行計画が導入判断の実務的な争点になります。 - 単一プラットフォームしか出荷しない、あるいはUI主体でロジックが薄いアプリでは、共有によるコスト削減より構成の複雑さが上回ります。
Kotlin Multiplatformが共通コードを各OSのバイナリへ変換する仕組み
KMPは共通のKotlinコードを1つの中間表現に閉じ込めて実行時に振り分ける方式ではありません。共通コードは各ターゲットのコンパイル時に取り込まれ、Android向けはJVMバイトコード、iOS向けはKotlin/Nativeによるネイティブバイナリとして生成されます。仮想マシンを挟まないため、iOSでもネイティブに近い実行性能が得られる、というのがJetBrainsの説明です。Kotlin言語そのものの特徴とK2コンパイラを押さえておくと、この構造は理解しやすくなります。
expected/actual宣言の使い分けとBeta扱いのexpect class
共通コードからプラットフォーム固有のAPIを呼びたい場合に使うのが、expected/actual宣言です。共通ソースセット側で expect キーワードを付けて実装を持たない宣言を置き、各プラットフォームのソースセットで同じパッケージに actual 付きの実装を用意します。コンパイル時に両者が突き合わされ、宣言の欠落やシグネチャ不一致はビルドエラーとして検出されます。
// commonMain/kotlin/Platform.kt
expect fun platformName(): String
// androidMain/kotlin/Platform.android.kt
actual fun platformName(): String =
"Android " + android.os.Build.VERSION.SDK_INT
// iosMain/kotlin/Platform.ios.kt
import platform.UIKit.UIDevice
actual fun platformName(): String =
UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
注意したいのは expect class の扱いです。公式ドキュメントはexpected/actualクラスをBetaと明記し、コンパイラも警告を出します(抑止する場合は -Xexpect-actual-classes をコンパイラオプションへ追加)。さらに「インターフェースで足りる場面でクラスを使うのは推奨しない」と踏み込んでいます。クラスで実装すると1プラットフォームにつき1実装へ設計が固定され、テスト用の差し替えが難しくなるためです。共通側はインターフェースで宣言し、実装の注入で解決するのが安全側の設計になります。
ソースセット階層とデフォルト階層テンプレート
iOSの実機向けターゲットとシミュレータ向けターゲットのように、コードをほぼ共有できる組み合わせは珍しくありません。この中間層を受け持つのがソースセット階層です。Kotlin Gradleプラグインにはデフォルト階層テンプレートが組み込まれており、宣言したターゲットに応じて iosMain や appleMain、nativeMain といった中間ソースセットが自動で用意されます。watchOSターゲットを追加すれば watchosMain が作られ、宣言していないターゲットの階層は無視されます。Android・iOSを対象にした共有モジュールのディレクトリは、次のような形になります。
shared
src
commonMain 共通のビジネスロジック
androidMain Android固有の実装
iosMain iOS実機・シミュレータ共通の実装
commonTest 全ターゲット共通のテスト
build.gradle.kts
この階層には安全装置としての意味もあります。各ソースセットは、そこからコンパイルされる全ターゲットで利用できるAPIにしかアクセスできません。Windows固有のAPIを書いたコードがmacOS向けにコンパイルされてリンクエラーや未定義動作を起こす、といった事態を型システムの段階で防ぐ設計です。中間ソースセットに actual 実装を置けるため、iOS実機とシミュレータで同じ実装を二重に書く必要もありません。
対応プラットフォーム別の安定度とBetaが残る範囲
「KMPはStable」という表現は、コア技術としての安定宣言であって、すべてのターゲットが同じ成熟度にあるという意味ではありません。JetBrainsは公式ドキュメントでプラットフォームごとの安定度を公開しています。以下は2026年8月時点の内容です。
| プラットフォーム | KMPコア技術 | Compose Multiplatform |
|---|---|---|
| Android | Stable | Stable |
| iOS | Stable | Stable |
| デスクトップ(JVM) | Stable | Stable |
| サーバーサイド(JVM) | Stable | 対象外 |
| Web(Kotlin/JS) | Stable | 対象外 |
| Web(Kotlin/Wasm) | Beta | Beta |
| watchOS | Beta | 対象外 |
| tvOS | Beta | 対象外 |
実務上の分かれ目はWebとウェアラブルです。Web向けにロジックを共有するだけならKotlin/JSがStableなので保守的な案件でも選べますが、Compose MultiplatformでUIごとWebへ載せる構成はKotlin/Wasm経由となりBetaに入ります。watchOS・tvOSも同様に、Betaは「移行時の変更をできる限り小さくするが、100%固まってはいない」という水準です。Betaのターゲットを含めるなら、Kotlinの更新に伴う移行作業が生じ得る前提で計画してください。
ロジックのみ共有かUIまで共有かの判断基準
KMPの設計思想は「何を共有するかを開発者が決められる」点にあります。共有の度合いは大きく3段階です。ネットワーク処理やローカルストレージなど独立したモジュールだけを共有する段階、ビジネスロジック全体を共有してUIは各OSネイティブのまま保つ段階、そしてCompose MultiplatformでUIまで共有する段階です。既存アプリへ後から段階的に導入できるのは、この選択肢の広さによるものです。
Googleは公式ドキュメントで、UIから最も遠いビジネスロジックの共有に価値が集中すると説明しています。同じ処理をプラットフォームごとに二重実装する保守コストがそのまま消えるためです。実際、GoogleはGoogle DocsのAndroid・iOS・Web版でビジネスロジックをKMPで共有していると公表しています。
一方でUI共有まで踏み込む場合は、iOS向けのCompose Multiplatformが2025年5月のバージョン1.8.0でStableとなり、選択肢として現実的になりました。ただしUIを共有するかどうかは、既存のSwiftUI資産やデザイン要件によって判断が変わります。UI層の詳細はCompose MultiplatformとKMPの違いおよびiOS対応の現在地を参照してください。KMP側だけを使い、iOSのUIはSwiftUIやUIKitで書き続ける構成も、公式が正面から支持する使い方です。
導入時に必要な環境とプロジェクト構成の骨子
IDEとXcodeのバージョン要件
KMPはIntelliJ IDEAとAndroid Studioの両方で開発できます。公式クイックスタートが求める最低バージョンは、IntelliJ IDEA 2025.2.2、またはAndroid Studio Otter 2025.2.1です。加えてKotlin Multiplatform IDEプラグインを導入し、ANDROID_HOME 環境変数を設定します。iOSアプリを作るならXcodeを入れたmacOSマシンが必須で、IDEが内部でXcodeを呼び出してiOSフレームワークをビルドします。Xcodeを更新したときは手動で一度起動し、追加ツールのダウンロードを済ませる必要があります。Kotlin Multiplatform IDEプラグインは、Xcodeがこの状態になっていない場合にプリフライトチェックで警告します。
build.gradle.ktsでのターゲット宣言とAGP 9.0対応
共有モジュールの build.gradle.kts では、対象プラットフォームをターゲットとして宣言します。iOS向けには実機用の iosArm64 とシミュレータ用の iosSimulatorArm64 を並べ、生成するフレームワーク名を指定するのが基本形です。
plugins {
kotlin("multiplatform")
id("com.android.kotlin.multiplatform.library")
}
kotlin {
listOf(iosArm64(), iosSimulatorArm64()).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "Shared"
isStatic = true
}
}
androidLibrary {
namespace = "com.example.app.shared"
compileSdk = 36 // 値は例。実際はバージョンカタログから参照する
minSdk = 24
}
}
baseName に指定した名前がiOS側のフレームワーク名になり、Swiftからは import Shared として読み込みます。次に説明する統合方式を選ぶ際も、この名前が起点になります。
ここが2026年時点で最も注意を要する変更点です。Android Gradle Plugin 9.0以降、KMPプラグインは com.android.application および com.android.library と互換性がなくなりました。従来の androidTarget {} + android {} ブロックという構成は、KMP専用に用意された com.android.kotlin.multiplatform.library プラグインと androidLibrary {} ブロックへ移行する必要があります。Androidのエントリポイントが共有モジュール内にある場合は、別モジュールへ切り出す作業も伴います。gradle.properties に android.enableLegacyVariantApi=true を追加すれば当面は旧APIで動かせますが、この退避策はAGP 10で使えなくなる予定です。AGP 9.0.0はAndroid Studio Otter 3 Feature Drop 2025.2.3からサポートされています。
iOSアプリへ組み込む統合方式の選び方
共有モジュールはiOSフレームワークとして書き出し、Xcodeプロジェクトから依存として読み込みます。方式はローカル統合とリモート統合に分かれます。
- ローカル|ダイレクト統合:Xcodeのビルドフェーズにスクリプトを組み込み、Kotlinのビルドをそのままアプリのビルド工程に含めます。CocoaPods依存がなければこれが既定で、KMP IDEプラグイン利用時も自動で適用されます。
- ローカル|ローカルSwiftパッケージ:モノレポでSwift Package Managerを使っている構成向けです。
- ローカル|ローカルpodspecによるCocoaPods統合:KMP側でCocoaPods依存を取り込んでいる場合はこの方式になります。
- リモート|XCFramework+SwiftPMまたはCocoaPods:共有コードを通常のサードパーティ依存として配布し、アプリ側のコードベースと切り離したい場合に選びます。
共通コードの変更を即座にアプリへ反映したいならローカル統合、共有コードをバージョン管理された成果物として扱いたいならリモート統合、という切り分けになります。iOSチームとAndroidチームが別組織で動いている場合は、後者のほうが運用の摩擦が小さくなります。なお共通ロジックのテストは commonTest ソースセットに置き、kotlin.test を使って全ターゲット共通に実行できます。
本番採用の実例とAndroidXライブラリの対応範囲
Google DocsやDuolingoなど公開されている採用事例
KMPはスタートアップから大企業まで本番投入が進んでいます。JetBrainsが名前を公開している採用企業には、Google、Duolingo、Forbes、Philips、McDonald’s、Bolt、H&M、Baidu、Kuaishou、Bilibiliが含まれます。Google側の資料ではCash App、Zomato、Swiggy、Wrike、JioHotstarなども挙げられています。JetBrainsが2024年第2四半期に実施したKMPサーベイでは、導入後にチーム間の連携が改善したとの回答が55%、性能と品質が改善したとの回答が65%と報告されています。数値は自社サーベイであるため、参考値として扱うのが妥当です。
KMP対応済みのJetpackライブラリと対象外の領域
Google公式サイトは、Jetpack(AndroidX)のうちKMP対応済みのライブラリを一覧で公開しています。annotation、collection、datastore、lifecycle、viewmodel、paging、savedstate、sqlite、navigationはAndroid・iOS・JVM・Webに対応します。RoomはAndroid・iOS・JVMに対応する一方、Webは対象外です。Compose関連やnavigationのiOS・JVM・Web対応分はJetBrainsが提供しています。
この一覧は「共有コードでAndroidと同じライブラリをそのまま使えるか」を判断する材料になります。RoomとDataStoreが共有側で使えるということは、Webを除けば永続化層を共通化できるという意味です。逆に一覧にないAndroid固有ライブラリに依存した処理は、expected/actual宣言で各プラットフォームに逃がすか、設計そのものを見直す必要があります。なおKMP開発で実際に使われる主要ライブラリはAndroidX以外にもあり、HTTP通信はKtor、JSONなどのシリアライズはkotlinx.serialization、非同期処理はkotlinx.coroutines、SQLを直接扱う場合はSQLDelightが代表的な選択肢です。
Kotlin Multiplatformのデメリットが上回る4つの条件
KMPが常に有利とは限りません。次の条件に当てはまる場合は、導入しないほうが総コストは下がります。
第一に、出荷対象が単一プラットフォームに限られるケースです。共有コードの恩恵はプラットフォーム数に比例しますが、ビルド構成の複雑さとCI設定の手間は最初の1つ目から発生します。Androidだけを作るなら通常のAndroidプロジェクトのほうが速く、Androidアプリ開発におけるKotlinとJavaの選定基準の範囲で判断すれば十分です。
第二に、ロジックが薄くUIと画面遷移が主体のアプリです。共有できるのは主にビジネスロジックであり、UI比率が高いアプリでは共有できる部分が小さく、Kotlin/Nativeのビルド時間やデバッグの手間だけが残ります。
第三に、iOSチームがKotlinに触れない体制です。KMPはiOS側のビルドにXcodeとKotlin/Nativeの両方が絡むため、iOSエンジニアが共有コードの構造を把握していないと、ビルドエラーの切り分けがAndroid側の担当者に集中します。導入前に、iOS側で誰が共有モジュールを保守するかを決めておくことが前提条件になります。
第四に、AGP 9.0への移行余力がない既存プロジェクトです。前述のとおりAndroid Gradle Pluginの互換性が切れており、モジュール分割を含む移行作業が発生します。移行工数を確保できない時期に新規導入を重ねると、ビルド基盤の変更が二重になります。
FlutterやReact Nativeとの比較を軸に判断したい場合は、Kotlin MultiplatformとFlutter・React Nativeの比較と導入判断で観点ごとに整理しています。技術選定の前段としてクロスプラットフォームアプリ開発のメリットとデメリットも参考になります。
よくある質問
Kotlin Multiplatformの最新バージョンはどれですか?
KMPはKotlin本体に含まれる技術のため、バージョンはKotlinのリリースに追随します。JetBrains/kotlinの公式リポジトリでは、2026年7月14日にKotlin 2.4.10が公開されています。UI共有に使うCompose Multiplatformは別リリースサイクルで、2026年6月2日に1.11.1が公開されました。更新頻度が高いため、着手時点の最新版は公式リリースページで確認してください。
Kotlin MultiplatformでWebアプリは作れますか?
作れますが、対象がKotlin/JSかKotlin/Wasmかで成熟度が変わります。Kotlin/JSによるWeb対応はStableで、既存のJavaScriptエコシステムと組み合わせてロジックを共有できます。一方、Compose MultiplatformでUIごとWebに載せる構成はKotlin/Wasm経由となり、KMPコア・Compose Multiplatformとも安定度はBetaです。業務システムの本番投入を前提にするなら、まずロジック共有のみをKotlin/JSで試す進め方が現実的です。
iOSのUIはSwiftUIのまま使えますか?
使えます。KMPはUI共有を強制しません。共有モジュールはiOSフレームワークとして書き出され、Swift側から通常のライブラリと同様に呼び出せるため、画面はSwiftUIやUIKitで実装したままビジネスロジックだけを共通化できます。JetBrainsもUIを完全にネイティブで作る構成、Compose Multiplatformで統一する構成、両者を混在させる構成の3つを併記しています。
Android Studioだけで開発できますか?
Androidとロジック共有までならAndroid Studio Otter 2025.2.1以上とKotlin Multiplatform IDEプラグインで完結します。ただしiOSアプリをビルドして実機やシミュレータで動かす工程にはXcodeが必要で、Xcodeが動作するmacOSマシンが要ります。Windows環境でiOSターゲットをビルドすることはできません。
Flutterとどちらを選ぶべきですか?
共有範囲の考え方が異なります。Flutterは独自の描画エンジンでUIまで一括して共有する方式、KMPはロジック共有を基本にUI共有を任意で選ぶ方式です。既存のネイティブアプリへ段階的に組み込みたい場合や、各OSのUI作法を維持したい場合はKMPが向きます。描画性能・人材確保・エコシステムなど観点ごとの詳細な比較は、前掲のFlutter・React Nativeとの比較記事にまとめています。