KINTO Tech Blog
Development

Kotlin Multiplatform Mobile(KMM)およびCompose Multiplatformを使用したモバイルアプリケーションの開発

Cover Image for Kotlin Multiplatform Mobile(KMM)およびCompose Multiplatformを使用したモバイルアプリケーションの開発

はじめに

こんにちは、グローバル開発部のYao, Bahng, Laiです。
普段は、 Global KINTO App のモバイルアプリエンジニアとしてアプリ開発を行っています。

数ヶ月前、Global KINTO Appの今後に関する事前アクティビティとして、Kotlin Mltiplatform Mobile (KMM)について調査しました。これについては私たちの前回の記事をご覧ください。
前回の調査の結果、KMMはプロダクトを迅速に開発するための非常に優れた解決策であることを示していました。
今回、Compose UIと一緒に機能する新しいアプローチのようなKMMが明らかになったので、私たちはKMMについてさらに調査することにしました。

この記事では、その調査に基づいて、Kotlin Multiplatform Mobile(KMM)とCompose Multiplatformを利用したアプリ開発についてお話します。

記事の本題に入る前に、まず以下の3つを説明します。

  • KMPとは?
  • KMMとは?
  • KMPとKMMの関係は?

回答は以下の通りです:

  • KMP = Kotlin Multiplatform、Kotlinを利用して、複数のプラットフォームに対応したアプリケーションを開発するための技術や、それに関連するエコシステム全体を指しております。
  • KMM = Kotlin Multiplatform for mobile、KMPの主な利用ケースの一つは、モバイルプラットフォーム間でのコード共有です。KMPに加えて、いくつかのモバイルアプリケーション開発に特化した技術を総称して、「KMM」という名称で呼ばれております。

KMPとKMMの関係を説明するためにグラフを描きました。

kotlin_universe

参考:

-- JetBrains "Kotlin brand assets | Kotlin. (n.d.-c). Kotlin Help.", "Get started with Kotlin Multiplatform for mobile | Kotlin. (n.d.). Kotlin Help." Accessed June 1, 2023

クロスプラットフォーム

KMMがクロスプラットフォームのソリューションの一つだという前提で、クロスプラットフォーム開発のメリットについて疑問に思われるかもしれません。以下にその利点を記載します。

  • コスト効率が良い:クロスプラットフォーム開発により、複数のプラットフォームで単一のコードベースを使用できるため、プラットフォーム別の開発チームが必要なくなり、アプリ開発のコストが削減されます。

  • より速いデプロイメント:単一のコードベースを活用することで、開発者は複数のプラットフォームで同時にアプリケーションを作成およびローンチできるため、開発時間が大幅に短縮され、リリースまでの時間が短縮されます。

  • メンテナンスとアップデートの簡素化:単一のコードベースを使用することで、アプリケーションのメンテナンスとアップデートが容易になり、変更を一度行うだけですべてのプラットフォームに反映されます。これにより、メンテナンスプロセスが合理化され、すべてのユーザーが最新の機能を利用できるようになります。

  • 一貫したユーザーエクスペリエンス:クロスプラットフォーム開発ツールとフレームワークを使用することで、異なるプラットフォーム間で一貫したルックアンドフィールを維持でき、統一されたユーザーエクスペリエンスが提供されます。これにより、ユーザー満足度やユーザー維持率の向上に繋がる可能性があります。

  • 共有リソースとスキル:クロスプラットフォームツールと言語に精通した開発者は、複数のプラットフォーム向けのアプリケーションを作成することができます。これにより、リソースの効率的な使用が可能となり、開発者のスキルやトレーニングへの投資のリターンを最大限に引き出すことができます。

モバイル向けクロスプラットフォーム開発ツールの歴史

cross_platform_history

  • 2009年にPhoneGapが作成され、その後Apache Cordovaに改名されました。
  • 2011年には、MonoによってXamarinが作成され、後にMicrosoftに買収されました。
  • 2015年には、Facebook(Meta)によってReact Nativeが作成されました。
  • 2010年代半ば、デザイナーのFrances BerrimanとGoogle ChromeエンジニアのAlex Russellが「プログレッシブ ウェブ アプリ」という用語を作り出し、Googleはそれを普及するためにいくつかの努力を行いました。2017年には、GoogleによってFlutterが作成されました。
  • 2021年には、JetBrainsによってKMMが作成されました。

つまり、現時点ではKMMが最新のクロスプラットフォームのソリューションです。

ロゴ出典:

-- Apache "Artwork - Apache Cordova. (n.d.)." Accessed June 1, 2023
-- Microsoft "Conceptdev. (n.d.). Xamarin documentation - Xamarin. Microsoft Learn" Accessed June 1, 2023
-- Meta "Introduction · React native." Accessed June 1, 2023
-- Google "Progressive web apps. (n.d.). web.dev." Accessed June 1, 2023
-- Google "Flutter documentation. (n.d.)." Accessed June 1, 2023
-- JetBrains "Kotlin Multiplatform for Cross-Platform development" Accessed June 1, 2023

なぜKMMが他と違うのか?

kmm_merits

  • 共有ビジネスロジック:KMMは、ビジネスロジック、ネットワーク、データストレージに関連するコードをプラットフォーム間で共有できるようにすることで、コードの重複を減らし、AndroidとiOS間の一貫性を維持します。

  • 真のネイティブUI:KMMは、UI開発にプラットフォーム固有のツールや言語(例:Android用のXML、iOS用のSwiftUIやUIKit)を使用し、他のクロスプラットフォームソリューションと比較してよりネイティブなルックアンドフィールを実現します。

  • パフォーマンス:Kotlinコードは各プラットフォーム用のネイティブバイナリにコンパイルされるため、ネイティブ開発と同等の高性能なアプリケーションが実現されます。

  • シームレスな統合:KMMは既存のプロジェクトに統合できるため、開発者は段階的に採用し、アプリを完全に書き換えることなくKotlinへの共有ロジックを移行できます。

  • ネイティブライブラリとの相互運用性:KMMは、AndroidとiOSの両方のネイティブライブラリとシームレスに相互運用できるため、開発者は既存のライブラリやフレームワークを簡単に活用できます。

  • Kotlin言語の利点:Kotlinは、モダンで簡潔な言語であり、冗長なコードを減らしながら、既存同等の機能を提供でき、JetBrainsからツールサポートも提供されています。

上記のポイントについて、以下に詳しく説明いたします。

① Shared Business Logic 共有ビジネスロジックについて

shared_business_logic

  • 新しいプロジェクトでデータ、ビジネス、プレゼンテーション層を実装する際、KMMを使用します。
  • 柔軟性:KMMは、共有したいコードの範囲を開発者が決定できるため、必要に応じてプラットフォーム固有のコードとバランスの取れた柔軟な実装が可能です。
  • 整合性の担保:UIの違いはQAテストで容易に発見できますが、ロジック部分でAndroid/iOSの不整合を発見することは難しいです。 KMMを使用することで同じコードを用いることができるので、整合性を担保することができます。

② Truly Native UI 真のネイティブUIについて

  • KMMはネイティブなUIをサポートし、ネイティブなUIコンポーネントを使用し、プラットフォーム固有のデザインパターンに従います。
    • Android:xml、Jetpack Composeなど
    • iOS:UIKit、SwiftUIなど
  • UIパフォーマンス:KMMはネイティブUIコンポーネントを使用し、Kotlinコードが各プラットフォーム用のネイティブバイナリにコンパイルされるため、パフォーマンスは一般的にネイティブアプリケーションと同等です。
  • 容易なプラットフォームの更新:KMMを使用すると、開発者は新しいプラットフォーム機能やデザインの更新を簡単に行うことができます。各プラットフォームのネイティブUIフレームワークを使用しているためです。

③ Performance パフォーマンスについて

  • JavaScriptブリッジは不要で、サードパーティーのライブラリに依存しません。
  • 独立したレンダリングエンジンを使用する必要はなく、システムデフォルトのレンダリングエンジンを使用するため、他のクロスプラットフォームソリューションと比較してリソース消費が少なくなります。
  • ネイティブコードのコンパイル:KMMは、Kotlinコードを各プラットフォームのネイティブバイナリにコンパイルします。このネイティブコードのコンパイルにより、アプリはより効率的に実行され、パフォーマンスが向上します。
    • Android:標準のKotlin/JVM
    • iOS:Kotlin/Nativeコンパイラ(Objective-C)

④ Seamless Integration シームレスな統合について

  • ネイティブモジュールをブリッジする必要はなく、既存のコードを書き換える必要もありません。
  • 段階的な採用:KMMは、既存のネイティブAndroidおよびiOSプロジェクトに徐々に導入できます。これにより、チームはビジネスロジック、ネットワーク、データストレージコードを段階的にプラットフォーム間で共有でき、完全な技術切り替えに関連するリスクを軽減できます。
  • iOSでKMMモジュールを利用する複数のアプローチ
    • CocoaPods Gradleプラグインとgitサブモジュール
    • Framework
    • Swift Package Manager(SPM):Kotlin 1.5.30から、Swift Package Managerを使用してiOSプロジェクトでKMMモジュールを利用できます

⑤ Interoperability with Native Libraries ネイティブライブラリとの相互運用性について

  • ネイティブAPIおよびライブラリへのアクセス:KMMはネイティブAPIとライブラリへ直接アクセスできるので、センサーやBluetoothなどのプラットフォーム固有の機能やハードウェアコンポーネントと簡単に統合することができます。
  • プラットフォーム固有のコードとのシームレスな統合:KMMは、必要に応じてプラットフォーム固有のコードを記述できるようになっています。これは複雑なネイティブライブラリを扱う場合や、共有Kotlinコードを通して利用できない機能にアクセスが必要な場合に有効です。
  • Kotlin/Native:KMMは、iOS向けにKotlin/Nativeを使用します。これにより、Objective-CおよびSwiftコードとのシームレスな相互運用性が実現されます。これは、既存のiOSライブラリやフレームワークを追加のブリッジングやラッピングコードなしで使用できることを意味します。

⑥ Kotlin Language Benefits Kotlin言語の利点について

kotlin_language_benefits

  • 言語機能:モダンで静的型付け、null安全、拡張関数、データクラス、スマートキャスト
    Javaとの相互運用性
  • ツールおよびサポート:Kotlinは、優れたツールサポートを提供し、Android StudioおよびIntelliJ IDEAでの第一級の統合が行われています。
  • 業界による採用:Kotlinは、Android開発の公式プログラミング言語になって以来、急速に採用が進んでいます。多くのバックエンド開発者もKotlinを使用しています。

KMMを利用しているのは、どのような方々でしょうか

実際に複数の企業がKotlin Multiplatform Mobile(KMM)をモバイルアプリ開発に採用しています。いくつかの注目すべき例を挙げます。

  • Netflix:Netflixは、AndroidアプリとiOSアプリ間でコードを共有するために、一部の内部ツールでKMMを使用しています。
  • VMware:VMwareは、Workspace ONE Intelligent Hubアプリ(AndroidおよびiOS向けの従業員管理ツール)のクロスプラットフォーム開発にKMMを使用しています。
  • Yandex:ロシアの多国籍技術企業であるYandexは、Yandex MapsやYandex Diskを含むいくつかのモバイルアプリでKMMを採用しています。
  • Quizlet:オンライン学習プラットフォームであるQuizletは、AndroidアプリとiOSアプリ間でコードを共有するためにKMMを使用し、開発効率を向上させています。

これらの企業は、多様な業界を代表しており、KMMの採用は、異なるコンテキストでの技術の柔軟性と有用性を示しています。KMMがさらに普及するにつれて、より多くの企業がクロスプラットフォームのモバイル開発のニーズに対応するためにKMMを採用することが予想されます。

参考:

-- JetBrains "Case studies. (n.d.). Kotlin Multiplatform." Accessed June 1, 2023

KMMプロジェクトを簡単に作成する方法

上記のメリットを考慮した上で、KMMプロジェクトを作成して試してみたいと思われますか?以下に方法をご案内いたします。

  • 最新のAndroid Studioをダウンロードします。
  • Android Studioで、ファイル|新規|新規プロジェクトを選択します。
  • プロジェクトテンプレートのリストでKotlin Multiplatform Appを選択し、Nextをクリックします。
    wizard-1
  • 最初のアプリケーションに名前を付け、Nextをクリックします。
    wizard-2
  • iOSフレームワーク配布リストで、Regular frameworkオプションを選択します。
    wizard-3
  • アプリケーションと共有フォルダのデフォルトの名前を維持します。Finishをクリックします。

-- JetBrains "Create your first cross-platform app | Kotlin. (n.d.). Kotlin Help." Accessed June 1, 2023

KMMを使用したモバイルアプリのアーキテクチャ

以下のグラフは、KMMの標準的なパターンの一つの例です。

kmm_architecture_standard

このアーキテクチャは、KMMの特性であるコード共有を最大限に活用しています。キャッシュ、データベース、ネットワーク、ユースケース、ビューモデルを含むデータ永続化は、すべてKMMで実装されています。
UIについては、AndroidとiOSの両方でネイティブUIコンポーネントを使用しています。XMLやUIKitなどの古いフレームワークから、Jetpack ComposeやSwiftUIを含めた新しいフレームワークもサポートされています。

このアーキテクチャではKotlinで書かれたビジネスロジックモジュールをSDKとしてiOSにインポートすることができます。これにより、iOS開発者はUI開発に集中でき、効率的な開発が実現できます。
下記はFAQリストを表示する簡単な画面のiOS側の実装になります。共通のUI Utility Classを除くと実装が必要なものはこれで終わりです。

#FaqView.swift
struct FaqView: View {
    
    private let viewModel = FaqViewModel()
    @State var state: FaqContractState
    
    init() {
        state = viewModel.createInitialState()
    }
    
    var body: some View {
        NavigationView {
            listView()
        }
        .onAppear {
            viewModel.uiState.collect(collector: Collector<FaqContractState> {
                self.state = $0
            }
            ) { possibleError in
                print("finished with possible error")
            }
        }
    }
    
    private func listView() -> AnyView {        
        manageResourceState(
            resourceState: state.uiState,
            successView: { data in
                guard let list = data as? [Faq] else {
                    return AnyView(Text("error"))
                }
                return AnyView(
                    List {
                        ForEach(list, id: \.self) { item in
                            Text(item.description)
                        }
                    }
                )
            },
            onTryAgain: {
                viewModel.setEvent(event: FaqContractEvent.Retry())
            },
            onCheckAgain: {
                viewModel.setEvent(event: FaqContractEvent.Retry())
            }
        )
    }
}

それがKMMの全てではありません。KMMにはさらなる可能性があります!

UIコードを共有するアーキテクチャ

ビジネスロジックコードだけでなく、KMMはCompose Multiplatformを使用してUIコードも共有することができます。

kmm_architecture_aggresive

先述のように、KMMは主に共有ビジネスロジックコードの実装に使用されますが、共有UIにも対応しています。Compose Multiplatformは、Kotlinで複数のプラットフォーム間でUIを共有するための宣言的フレームワークです。Jetpack Composeをベースに、JetBrainsとオープンソースの貢献者によって開発されました。KMMとCompose Multiplatformを組み合わせることで、Kotlin言語を使用してロジックコードとUIを両方構築できます。

参考:

-- JetBrains "Kotlin brand assets | Kotlin. (n.d.-c). Kotlin Help.", "Compose multiplatform UI framework | JetBrains. (n.d.). JetBrains: Developer Tools for Professionals and Teams." Accessed June 1, 2023

KMMのアーキテクチャの異なるパターンの比較

モバイルプロジェクトを開発すると仮定し、各クライアントの工数は次のとおりです:
UI:2人、Presentation:1人、Business/Domain:1人、Data/Core:1人

cost_reduction

ここから削減できる工数はKMMによって書かれたコードの割合に基づきます。

パターン A B C D
UI 2*2 2*2 2*2 2
Presentation 1*2 1*2 1 1
Business/Domain 1*2 1 1 1
Data/Core 1 1 1 1
合計 9 8 7 5
工数コスト -10% -20% -30% -50%

KMMを用いることで最大で50%もの工数を削減することができます。

他のクロスプラットフォームソリューションと比較して、KMMの最大の利点は、KMMが柔軟にコード共有できることです。
KMMでどれだけのコードを共有するかは、完全に私たち自身で決定できます。
他のクロスプラットフォームソリューションではここまでの柔軟性がないため、こうはいきません。

まとめ

KMMの欠点

kmm_demerits

もちろん、すべてのツールにはデメリットがあります。KMMにもデメリットがあります。

  • 限られたプラットフォームのサポート: Kotlin Multiplatform Mobileは複数のプラットフォームを対象とできますが、すべてのプラットフォームをサポートしているわけではありません。たとえば、現時点ではWebやデスクトップアプリケーションをサポートしていません。

  • 学習コスト: Kotlinに慣れていない場合、マルチプラットフォーム開発に効果的に使用するための学習コストが必要です。

  • フレームワークの互換性: Kotlin Multiplatform Mobileはさまざまなフレームワークと共に使用できますが、すべてのフレームワークと互換性があるわけではありません。これにより、オプションが制限され、特定の制約内で作業する必要があるかもしれません。

  • メンテナンスのオーバーヘッド: マルチプラットフォームのコードベースを維持することは、各プラットフォームごとに別々のコードベースを維持するよりも複雑になる可能性があります。これにより、テスト、デバッグ、メンテナンスにおいて追加のオーバーヘッドが生じる可能性があります。

  • ツールの制限: 一部のツールやライブラリがKotlin Multiplatform Mobileと互換性がない場合があり、開発がより困難になるか、代替のソリューションを探す必要があるかもしれません。

応用

上記の通り、メリットやデメリットを含めて、さまざまな状況に応じてKMMのアーキテクチャをプロジェクトに統合することが検討できます。

パターン A B C D
一般的な既存プロジェクト ?
シンプルな既存のプロジェクト
複雑な既存プロジェクト
新しいプロジェクト
プロトタイプ

技術的な利点を一旦ここまでとして、実開発プロセスの話題に戻ります。多くモバイル開発チームと同様、私たちのチームも規模が小さいです。限られたエンジニアリソースの中で、バージョン1.0から2.0へのアップグレードといった比較的大規模な変更に直面した場合、我々は他の部署やオンサイトまたオフショアのアウトソーシングチームと連携し、リリースの迅速化を確実にする必要があります。

しかし、この過程に置いて、以下のような複数の問題が存在します:

  1. 異なるチーム間のシームレスな連携が難しい。
  2. 開発者が増え、異なるオフィスに所属する異なるチームとなると、コミュニケーションコストが上昇します。
  3. 異なるチーム間での一貫性を維持することが難しくなります。
  4. 外部チームとの連携において、機密情報のセキュリティ管理が難しくなります。

KMMはコアモジュールの開発を行い、プロトコルを定義し、UIとロジックを分離した開発というアプローチを取ることで、これらの問題をほぼ全て解決することができます:

  1. 各チームが自分のパートに専念することが可能になります。協力作業を大幅に容易にすることができます。
  2. コミュニケーションに必要な時間やコストを削減することができます。
  3. コアモジュールはKMMチームが開発することで、同じ基盤で開発を行うことで、ほとんどの不整合が事前に解消されます。
  4. KMMは一つのコードベースをサポートしているものの、UI層とロジック層が分離しているため、複数のリポジトリを利用することも可能です。コアモジュールはKMMチームが開発し、SDKは外部チームに提供します。これにより、ソースコードが外部チーム公開しする必要がなく、機密情報の漏洩リスクを減らすことができます。これは他のクロスプラットフォーム技術のソリューションでは達成が難しいです。

access_control

結論として、KMMは技術的な利点だけでなく、部門や会社を超えた協力作業にも多大な利点をもたらしてくれると言えます。

最後に

新プロジェクトにおけるKMMの重要性と、大幅な工数削減の可能性を考慮し、すでに次のメジャーリリース向けの新プロジェクトにKMMを統合しました。私たちは引き続きKMMに関連する新たな技術やツールに留意し、さらなる効率向上を図るための可能性を探し続けます。

Facebook

関連記事 | Related Posts

We are hiring!

【iOS/Androidエンジニア】モバイルアプリ開発G/東京・大阪

モバイルアプリ開発GについてKINTOテクノロジーズにおける、モバイルアプリ開発のスペシャリストが集まっているグループです。KINTOやmy routeなどのサービスを開発・運用しているグループと協調しながら品質の高いモバイルアプリを開発し、サービスの発展に貢献する事を目標としています。

【部長・部長候補】/プラットフォーム開発部/東京

プラットフォーム開発部 について共通サービス開発GWebサービスやモバイルアプリの開発において、必要となる共通機能=会員プラットフォームや決済プラットフォームの開発を手がけるグループです。KINTOの名前が付くサービスやTFS関連のサービスをひとつのアカウントで利用できるよう、様々な共通機能を構築することを目的としています。