Kotlin Multiplatform(KMP)は、JetBrainsが開発するオープンソースの技術で、Kotlinで書いたコードをAndroid・iOS・デスクトップ・Web・サーバーで共有します。FlutterやReact Nativeとの最大の違いは、共有する範囲を開発者が決められることです。通信やデータ処理などのロジックだけを共有して画面は各OSのネイティブで書くことも、Compose MultiplatformでUIまで共有することもできます。この記事では、KMPの仕組み、ターゲットごとの安定度、FlutterとReact Nativeとの選び分け、導入に必要な環境と採用を見送る条件を、2026年11月時点の公式ドキュメントとリリース情報にもとづいて整理します。
まとめ:KMPの要点と採用判断
- KMPはロジックの共有が基本で、UIの共有は選択制です。Android・iOS・デスクトップ(JVM)・サーバー(JVM)・Kotlin/JSはStable、Kotlin/Wasm・watchOS・tvOSはBetaです。
- 既存のネイティブアプリがあり、両OSで同じ挙動にしたいロジックが厚いなら、KMPが最も無理のない選択です。
- ゼロから作り、見た目を完全に揃えたいならFlutterが先に候補になります。KMPでUIまで共有する場合はCompose MultiplatformとFlutterの比較になります。
- Webを本番の主戦場にする案件では慎重に判断してください。Compose MultiplatformのWebはBetaで、JetpackのKMP対応ライブラリもWebはCIでテストされない「Tier 3」の扱いです。
- 2026年11月時点の版はKotlin 2.4.21、Compose Multiplatform 1.12.2です。AGP 9以降ではAndroid向けの設定が変わるため、従来のAndroidプラグインを使うKMPモジュールを更新する場合は移行が必要です。
KMPがコードを共有する仕組み
ターゲットごとに異なる共通コードのコンパイル先
KMPは、共通コードを1つの実行環境に載せて各OSで動かす方式ではありません。共通のKotlinコードはターゲットごとのコンパイル時に取り込まれ、Android・デスクトップ・サーバー向けはJVMバイトコードに、iOS向けはKotlin/Nativeでネイティブバイナリに、Web向けはJavaScriptかWebAssemblyになります。iOSでも仮想マシンやJavaScriptの実行環境を挟まず、共有したコードはネイティブコードとして動きます。Android Developersの公式ページも、KMPの利点として「重複の排除」「全面的な書き換えが不要」「ネイティブ性能」の3つを挙げています。
呼称にも触れておきます。AndroidとiOSに絞った呼び名だったKMM(Kotlin Multiplatform Mobile)はJetBrainsが2023年7月31日に非推奨とし、現在は対象の組み合わせを問わずKMPに統一されています。KMP自体は2023年11月のKotlin 1.9.20でStableになり、2024年5月にはGoogleがAndroidでの公式サポートを表明しました。
expect/actual宣言とBetaのままのexpect class
共通コードから各OS固有のAPIを呼ぶ仕組みが、expected/actual宣言です。共通ソースセットに expect 付きで実装のない宣言を置き、各プラットフォームのソースセットに同じパッケージで actual 付きの実装を書きます。iOS側だけ実装を忘れると、ビルドエラーで止まります。
// 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 は2026年11月時点でもBetaです。公式ドキュメント(expected and actual declarations)は、使うとコンパイラがBetaの警告を出し、抑止するにはコンパイラオプション -Xexpect-actual-classes が要ると説明しています。単純な用途でクラスを使うことも勧めていません。クラスにすると1プラットフォーム1実装に固定され、テストで差し替えにくくなるためです。共通側をインターフェースで宣言し、実装を依存性注入で渡すと、テスト用の偽物や同一プラットフォーム内の別実装へ差し替えやすくなります。
commonMain・androidMain・iosMainのソースセット階層
コードの置き場はソースセットで分かれます。Kotlin Gradleプラグインにはデフォルトの階層テンプレートがあり、宣言したターゲットに応じて iosMain・appleMain・nativeMain などの中間ソースセットが自動で作られます。AndroidとiOSを対象にした共有モジュールは、次の形が基本です。
shared/
src/
commonMain/ 共通のビジネスロジック
androidMain/ Android固有の実装
iosMain/ iOS実機とシミュレータで共通の実装
commonTest/ 全ターゲット共通のテスト(kotlin.test)
build.gradle.kts
各ソースセットは、そこからコンパイルされる全ターゲットで使えるAPIにしかアクセスできません。commonMain に android.os のようなAndroid専用APIを書くとエラーになります。iOS実機(iosArm64)とシミュレータ(iosSimulatorArm64)の実装は iosMain に1つ書けば足ります。
共有範囲の3段階とCompose Multiplatformの位置づけ
kotlinlang.orgのKMPページは、共有の度合いを「ロジックの一部」「ロジック全体(UIはネイティブ)」「ロジックとUI」の3つに分けています。段階ごとの向き不向きは次のとおりです。
- ロジックの一部:通信・認証・課金判定など1モジュールだけを共有します。既存アプリへの試験導入はここから始めるのが定石です。
- ロジック全体+ネイティブUI:データ層とビジネスロジックを共有し、画面はJetpack ComposeとSwiftUIで書きます。両OSの操作感を崩さずに、仕様のズレによる不具合を減らせます。
- ロジックとUI:Compose MultiplatformでUIまで共有します。iOS向けは2025年5月6日公開の1.8.0でStableになりました。詳細はCompose Multiplatformとは?KMPとの違いとiOS対応の現在地・採用判断を解説で扱っています。
迷ったら2段階目を基準に考え、UI共有はデザインを両OSで揃える必要があるときに足す、という順番で判断すると失敗が少なくなります。Googleも、UIから遠いビジネスロジックほど共有の価値が高いと説明しています。
FlutterとReact Nativeとの比較
3者の違いは、どの層を共通化するかに集約されます。Flutterは独自エンジンで画面まで描き、React NativeはJavaScriptからネイティブのUI部品を操作します。どちらもUIの共通化が前提で、KMPはそこを開発者の選択に委ねています。
| 観点 | Kotlin Multiplatform | Flutter 3.47.9 | React Native 0.88.1 |
|---|---|---|---|
| 共通化する層 | ロジック(UIは選択制) | ロジック+UI | ロジック+UI |
| 言語 | Kotlin | Dart | JavaScript/TypeScript |
| UIの描画 | ネイティブ or Compose | 独自エンジン | ネイティブ部品 |
| 既存アプリへの導入 | 共有モジュールを追加 | 画面全体・一部(add-to-app) | 画面・ビュー単位 |
| Web対応 | JSはStable/WasmはBeta | 対応 | react-native-webで別途 |
| OS間の見た目 | ネイティブUIならOS差あり | 統一可能・OS別の調整も可能 | 部品由来の差が残る |
版は2026年11月1日時点の最新安定版です(Flutterは10月29日、React Nativeは10月27日公開)。
KMPとFlutterの選び分け
まず既存資産、UI共有の必要性、両OSの保守体制を確認します。すでにKotlinのAndroidアプリとSwiftのiOSアプリがあるなら、KMPは共有モジュールを足すだけで画面を作り直さずに済みます。Flutterにもadd-to-appで既存アプリの画面全体や画面の一部へ組み込む方法がありますが、エンジンの初期化や状態の受け渡しを自分で設計することになります。逆に新規開発で、少人数のチームが両OSを同じ見た目で出したいなら、Flutterを候補にし、Dartの習熟度や必要なネイティブ連携を含めて初期開発の工数を比較します。
人材も現実的な制約です。AndroidエンジニアがKotlinを書けるなら、KMPの共有モジュールに新しい言語の学習は要りません。Androidアプリ開発の言語はKotlinとJavaのどちらか?選定基準と環境まで解説で触れているとおり、Androidの新規開発はKotlinが前提になっているため、Android側の負担は小さく済みます。
KMPとReact Nativeの選び分け
React Nativeが向くのは、WebフロントエンドのReact資産と人材をモバイルにも回したい組織です。KMPは逆に、Kotlinを書けるAndroidチームが中心になります。FlutterとReact Nativeの2者の違いはFlutterとReact Nativeの違いの比較で詳しく比べています。
ターゲット別の安定度とJetpackライブラリのTier
KMPコアとCompose Multiplatformの安定度
すべてのターゲットが同じ成熟度ではありません。JetBrainsの公式表(Supported platforms)は2026年11月時点で次のとおりです。
| ターゲット | KMPコア | Compose Multiplatform |
|---|---|---|
| Android | Stable | Stable |
| iOS | Stable | Stable |
| デスクトップ(JVM) | Stable | Stable |
| サーバー(JVM) | Stable | 対象外 |
| Web(Kotlin/JS) | Stable | 対象外 |
| Web(Kotlin/Wasm) | Beta | Beta |
| watchOS/tvOS | Beta | 対象外 |
JetBrainsはBetaを「使ってよいが、移行の手間を最小限にするよう努める」段階と定義しています。WebでロジックだけをKotlin/JSで共有するなら保守的な案件でも選べますが、Compose MultiplatformでUIごとWebに載せる構成はKotlin/Wasm経由になり、Betaに入ります。
JetpackのKMP対応ライブラリとTier 1〜3
上の表だけでは見落としやすいのが、ライブラリ側の対応度です。Android Developersの一覧では、Room・DataStore・Lifecycle・ViewModel・Paging・SavedState・SQLite・Navigationなど14のJetpackライブラリがKMPに対応しています。ただしGoogleはプラットフォームを3段階に分けています。
| Tier | 対象 | CIでのテスト | 互換性の追跡 |
|---|---|---|---|
| Tier 1 | Android・JVM・iOS | ホスト+デバイス | あり |
| Tier 2 | macOS・Linux | ホスト側のみ | なし |
| Tier 3 | watchOS・tvOS・Windows・JavaScript・Wasm | なし | なし |
つまりKotlin/JSのコアがStableでも、その上でJetpackのライブラリを使う部分はGoogleのCIでテストされていません。RoomはWebを対象外としています。Webを含めて永続化層まで共有する計画なら、Jetpackの代わりにSQLDelightなど他のライブラリの対応状況も確かめておく必要があります。AndroidとiOSの2プラットフォームに限れば、どちらもTier 1なので、この点は気にしなくて構いません。
Kotlin 2.4.21とCompose Multiplatform 1.12.2の版の関係
KMPはKotlin本体に含まれる技術なので、版はKotlinのリリースに追随します。JetBrains/kotlinのリリースでは、最新の安定版が2026年10月8日公開の2.4.21で、次の2.5.0は10月21日時点でBeta2です。Kotlinの版を上げずにKMPの機能だけを新しくすることはできないため、古いKotlinで止まっているAndroidプロジェクトでは、導入の第一歩がKotlinの更新になります。言語側の変更点はKotlinとは?Javaとの違いとK2コンパイラ・2.4系の現在地を実装者目線で解説にまとめています。
Compose Multiplatformは別のリリースサイクルで、最新の安定版は2026年10月15日公開の1.12.2、次の1.13.0は10月23日にbeta01が出ています。UI共有を使う場合は、Kotlinとの対応表を見てから両方の版を決めてください。
KMPを始める環境とプロジェクト構成
IDEとKMPプラグイン、macOSとXcode
開発はIntelliJ IDEAかAndroid Studioで行います。公式クイックスタートは以前のように最低バージョンを示さず、どちらも最新の安定版を使うよう求めています。Kotlin Multiplatformプラグインが動くのは、IntelliJ IDEAならWindows・Linuxで2025.2.2以降(macOSは2025.1.1.1以降)、Android StudioならWindows・LinuxでOtter 2025.2.1以降(macOSはNarwhal 2025.1.1以降)です。このプラグインを入れ、Android SDKの場所を環境変数 ANDROID_HOME に設定すれば、ウィザードからAndroid・iOS・デスクトップ・Web・サーバーのターゲットを選んでプロジェクトを作れます。
iOSアプリのビルドには、Xcodeを入れたmacOSマシンが必須です。これはAppleのツールチェーンの制約なので、WindowsやLinuxだけのチームではiOSターゲットをビルドできません。IDEは内部でXcodeを呼んでiOSフレームワークを作るため、Xcodeを更新したら一度手動で起動し、追加ツールのダウンロードを済ませておきます。設定が足りないときは、KMPプラグインのプリフライトチェックが警告を出します。
build.gradle.ktsのターゲット宣言とAGP 9対応
共有モジュールの build.gradle.kts では、対象をターゲットとして宣言します。以下は、ルート側でKotlin・Android-KMPプラグインのバージョンとリポジトリを設定済みのプロジェクトに追加する抜粋です。AGP 9以降の書き方では、Android向けに com.android.kotlin.multiplatform.library プラグインと、kotlin {} 内の android {} ブロックを使います。
plugins {
kotlin("multiplatform")
id("com.android.kotlin.multiplatform.library")
}
kotlin {
listOf(iosArm64(), iosSimulatorArm64()).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "Shared"
isStatic = true
}
}
android {
namespace = "com.example.app.shared"
compileSdk = 36 // 値は例。実際はバージョンカタログから参照する
minSdk = 24
}
}
ここが既存プロジェクトで最も手間のかかる変更点です。JetBrainsの移行ガイドによれば、AGP 9.0以降のKMPプラグインは com.android.application や com.android.library と併用できず、従来の androidTarget {}+トップレベルの android {} の構成は上の形へ書き換えが必要です。なお、移行ガイドの例にある kotlin {} 内の androidLibrary {} は、Android Developersの設定ガイドでAGP 9.1.0-alpha09から非推奨とされ、AGP 8.12.0以降は android {} を使うよう案内されています。gradle.properties に android.enableLegacyVariantApi=true を足せば当面は旧APIで動きますが、この逃げ道はAGP 10で削除される予定です。2026年11月時点のAGPの最新安定版は9.5.0で、AGP 10はまだ出ていません。新規に導入するなら、最初から新しい書き方で始めてください。
iOSアプリへの組み込み方式とSwift export
共有モジュールはiOSフレームワークとして書き出し、Xcodeプロジェクトから読み込みます。baseName に付けた名前がフレームワーク名になり、Swiftからは import Shared で呼び出せます。組み込み方は次の2系統です。
- ローカル統合:Xcodeのビルドフェーズにスクリプトを入れ、Kotlinのビルドをアプリのビルドに含めます。CocoaPodsへの依存がなければこれが既定です。共通コードの変更がすぐにアプリへ反映されます。
- リモート統合:XCFrameworkを作り、Swift Package ManagerかCocoaPodsで配布します。iOSチームとAndroidチームが別組織で動く場合は、版の付いた成果物として受け渡すほうが摩擦が小さくなります。
現在の既定では、KotlinのコードはObjective-Cのヘッダを経由してSwiftから見えます。そのためSwift側で型名が崩れたり、Kotlinのsealed classやenumの網羅性が失われたりします。これを解消するSwift exportは開発中ですが、公式ドキュメントは安定版Kotlin 2.4系のSwift exportをAlphaとし、互換性のない変更が入りうると明記しています。一方、Kotlin 2.5.0-Beta2ではSwift exportのBeta化が案内されています。本番ではまだObjective-C経由を前提に、Swift側の書き心地を改善するSKIEのようなツールを併用する構成が現実的です。
本番採用の事例と公開されている導入の課題
海外・国内の採用事例
Android Developersの事例一覧にはGoogle Docs、Duolingo、Cash App、Forbes、Zomato、Swiggy、Wrikeなどが並びます。JetBrainsの製品ページによれば、ForbesはiOSとAndroidでロジックの80%以上を共有しています。国内ではSansanが名刺アプリへの導入を公開しており、Sansanの技術ブログでは、導入前の試算として全体の開発効率が11%、基盤とCI/CDが整えば最大22%向上すると見込んでいたと書かれています。導入は1画面から始めています。
導入事例で報告されている課題
Sansanの記事が挙げているのは、Kotlin/Nativeに対応したライブラリしか使えないため、AndroidでおなじみのJUnit・AssertJ・MockKが共有コードのテストに使えないこと、iOS向けビルドの後にXcodeの型認識が不安定になること、iOSエンジニアにKotlinの学習とXcode以外のIDEの併用が求められることです。サイボウズの技術ブログ(2024年8月)は、新卒研修の2週間の開発で、周辺ライブラリのKMP対応不足やiOS向けビルドの不安定さを報告しています。本番運用の実績とは区別して読む必要があります。どちらも2024年時点の記録ですが、テスト基盤とiOS側の保守体制は今も導入前に決めておくべき論点です。
KMPを含めたスマホアプリの技術選定から相談したい場合は、一創のスマホアプリ開発で、既存アプリの構成に合わせた進め方を提案しています。
KMPを採用しないほうがよい条件
次のいずれかに当てはまるなら、KMPは見送るか、時期をずらすほうが総コストは下がります。
- 出荷するのが1プラットフォームだけ:共有する相手がいないので減る実装はなく、マルチプラットフォーム構成のビルドとCIの手間だけが増えます。
- 画面表示が中心でロジックが薄い:共有できる部分が小さく、Kotlin/Nativeのビルド時間とデバッグの手間だけが残ります。
- iOS側で共有モジュールを保守する人がいない:ビルドエラーの切り分けがAndroid担当に集中します。誰がiOS側でKotlinを読むかを先に決めてください。
- WebのUI共有にStableが必須:Compose MultiplatformのWebはBeta、JetpackのWeb対応はTier 3です。
- AGP 9への移行に工数を割けない時期:移行とKMP導入を同時に進めると、ビルド基盤の変更が二重になります。
反対に、決済・同期・オフラインキャッシュ・課金判定のように、両OSで完全に同じ挙動にしたいロジックが厚いアプリでは効果がはっきり出ます。共通ロジックを一か所で修正でき、別実装の更新漏れを減らせるためです。ただし、プラットフォーム固有実装や依存ライブラリによる挙動差は残るため、両OSでのテストは必要です。HTTP通信に使うKtorのように、KMPに対応した主要ライブラリが揃っている領域から共有を始めると、立ち上がりが安定します。クロスプラットフォーム開発全体の選択肢はクロスプラットフォームアプリ開発の4方式の違いで比べています。
よくある質問
KMMとKotlin Multiplatformは違うものですか?
同じ技術です。KMM(Kotlin Multiplatform Mobile)はAndroidとiOSに絞ったときの呼び名で、JetBrainsが2023年に非推奨にしました。現在はモバイル以外のターゲットも含めてKotlin Multiplatform(KMP)と呼びます。
Kotlin MultiplatformでWebアプリは作れますか?
作れますが、方式で成熟度が違います。Kotlin/JSでロジックを共有する構成はStableです。Compose MultiplatformでUIごとWebに載せる構成はKotlin/Wasm経由になり、KMPコアもCompose MultiplatformもBetaです。業務システムなら、まずKotlin/JSでロジック共有だけを試す進め方が安全です。
iOSの画面はSwiftUIのまま使えますか?
使えます。KMPはUIの共有を強制しません。共有モジュールはiOSフレームワークとしてSwiftから呼べるので、画面はSwiftUIやUIKitで書いたまま、ビジネスロジックだけを共通化できます。
Android Studioだけで開発できますか?
Androidとロジック共有まではAndroid StudioとKotlin Multiplatformプラグインで完結します。iOSアプリのビルドと実行にはXcodeが必要なので、macOSマシンが要ります。Windows環境ではiOSターゲットをビルドできません。
KMPとFlutterはどちらを選ぶべきですか?
既存のネイティブアプリに段階的に組み込みたいならKMP、ゼロから作って両OSの見た目を揃えたいならFlutterです。Flutterもadd-to-appで既存アプリの画面全体や一部に組み込めますが、FlutterエンジンとDartのコードを抱えることになります。KMPの共有モジュールはAndroidのライブラリとiOSのフレームワークとして入るので、既存アプリの構成を大きく変えずに済みます。