KMP導入によるチーム統合と開発プロセス改善を振り返る

Android, iOS, KMP, チームビルディング

はじめに

こんにちは、株式会社レコチョクの長島です。iOSアプリの開発などをしています。現在はプロダクト開発第2グループに所属しております。

以前、ある音楽プラットフォームアプリの大規模改修をする際、Kotlin Multiplatform(以下KMP)という技術を採用しました。
KMPは所謂マルチプラットフォーム技術ですが、実際に運用してみると、期待通りの効果もあれば想定外の課題も見えてきました。
この記事では、KMP導入を軸としたiOS/Androidチームの統合とプロセス改善により、どのような結果が得られたのかを紹介します。

なお、KMPを導入したアプリに関する記事としては「【iOS】Kotlin MultiplatformでApp Clip対応アプリを2か月で作ったので振り返る」なども存在しています。ご興味がある方はそちらもご覧ください。

背景

システム全体の課題

自分が関わっていたアプリは、長きに渡って開発されていたため、技術的負債が多く存在してしまっている状態でした。
中でも、「APIの数が膨大かつインターフェースの実際の動きが仕様書と異なる部分がある」という課題が存在し、開発効率が落ちていました。
こうした負債解消と将来的なエンハンス対応のため、2023年末から大規模なリアーキテクチャの計画が行われることになりました。

様々な案が出ている中で、APIチーム側からBFF(Backend For Frontend)の導入提案がありました。
BFFはフロントエンド専用のバックエンド層として、複数のAPIを集約し整形する仕組みです。これにより膨大なAPIや定義書との不一致を解消できる見込みがあったため、アプリチームとしても検討を進めていました。

なぜ共通化を選択したのか

BFF導入に伴い、アプリ側では数多くのAPI定義を新しいものに置き換える必要がありました。
しかし、この置き換えをiOS/Androidで別々に実装すると次の図のような状態となります。

これでは、通信処理・データ変換・エラーハンドリングなどで実装差異が生まれやすく、開発する内容としても重複してしまいます。

そこで、社内ですでに開発実績があるKMPを導入し、API処理を中心にDomain/Infrastructure層から段階的に共通化していく方針で進めることを決めました。
この共通化が実現すれば次の図のような構成になり、実装をiOS/Android別々に行う必要がなくなり、実装差異の解消や開発効率の向上が期待できます。

改めて、KMP導入の目的・目標として位置づけたのは次の2つです。

  • 実装差異の解消
    • API通信処理を中心に、Domain/Infrastructure層の計画部分をコードレベルで統一化する
  • 開発効率の向上
    • 開発およびレビュー等にかかる工数を短縮する

実践:どう活用したか

KMPの導入が決定した後、実際の開発に入っていきました。ですが今までと全く同じ開発フローを使うことは出来ません。
もしiOS/Androidのチームが今まで通りに分離したままKMPだけを導入しても、誰が運用するのかという時点で詰まってしまいます。
そのため、元々は分離していた2つのチームが協力できるように工夫を加えました。

iOS/Androidチームの統合

導入前は、図のようにiOSチームとAndroidチームが完全に分離されており、設計・実装・テストなどすべての工程が独立して進められていました。
同じプロダクトを開発しているものの、チーム間のコミュニケーションが少ない状態になっていました。

しかし、KMPの導入によって、これまで各OS別で開発していた部分を横断するように技術が加わることになりました。この変化を受けて、新たに生まれる共通部分の運用方法について話し合いました。
その結果として、それまで領域別に分かれていたミーティングのほとんどにおいてiOS・Android両チームのエンジニアが合同で参加し、共通事項について一緒に合意を取る体制に移行しました。
また、プルリクエストのレビュー体制も見直し、KMP関連の変更は両チームのエンジニアのうち最低1名ずつが確認するというルールを設けました。

基本的には、次の図のように全員がアプリチームとして動けるようになった形です。

モノレポ構成でのKMP実装

アーキテクチャと併せて、KMPのリポジトリ構成について考える必要がありました。具体的には、次の2つの選択肢が検討されました。
1. KMP共通コードのみを別リポジトリでライブラリ化し、既存のiOS/Androidリポジトリはそのまま維持する
2. iOS/Androidのアプリも含め全てを単一のリポジトリ(モノレポ)に統合する

別リポジトリでライブラリ化する場合には次のメリット・デメリットが存在します。

  • メリット
    • ライブラリのimportで対応できるため、現在のリポジトリ構成を維持したまま開発できる
    • KMP部分の変更とアプリ側の変更を分離できる
  • デメリット
    • iOS/Androidアプリと連動したデバッグがしにくい
    • ライブラリのバージョン管理とリリースフローが必要になる

単一のリポジトリ(モノレポ)で管理する場合は次の通りです。

  • メリット
    • KMPでの変更を即座にアプリで確認可能でデバッグが容易
    • 共通コードとアプリコードが同じリポジトリにあり参照しやすい
  • デメリット
    • ビルド構成やリポジトリサイズの増大
    • iOS/Androidの独立したリリースサイクルの管理が必要になる

検討の結果、KMP導入初期は試行錯誤が多いと予測でき、即座に確認できる環境が重要だと判断し、モノレポを選択しました。
実際の統合作業としては次のような変更をしています。

  • KMPのリポジトリを新規作成
    • これまで使っていたiOS/Androidのリポジトリ内容をKMPリポジトリに移動
  • ブランチ運用ルールの見直し
    • 共通部分の変更がiOS/Androidに影響することを考慮したルール策定
  • CI/CD条件の変更
    • プラットフォーム別のビルド条件設定

この移行作業が終わった後に共通化部分の開発が始まり、リアーキの完了までこの運用となりました。

結果:何が変わったか

上記の工夫を入れながら開発した結果、元々の狙いであった「実装差異」「開発効率」がどう変化したかを振り返ります。

実装差異について

KMP導入後、Domain/Infrastructure層の中でAPI処理が関わる処理約220箇所のうち、97%をKMPで実装されたものに置き換えました。

結果として、共通化した部分においては両OSで挙動が同一であることをコードレベルで担保できるようになりました。これにより、過去に発生していた各OSで異なっていた細かいパラメータの差異や、ドキュメントの読み違いによるズレなどは一件も発生しなくなりました。

開発効率について

次に開発効率の観点をサイクルタイムの指標で振り返ります。サイクルタイムとは、開発に着手してから完成するまでの時間を指します。今回は最初のコミットを開発着手、マージを完成として、GitHubプルリクエストの最初のコミットからマージまでの時間を基準として計算しました。

上記は導入後からのサイクルタイムの推移をFindy Team+の機能を用いて計測した結果となります。
タスクの内容や難易度によって数値は変動することを前提に、このグラフを時期ごとに分類すると、次のようになります。

この色分けを元に、内容を見ていきます。

(1) 2023年末〜2024年2月:導入準備期間

この期間は、KMP導入のための準備に専念していたため、通常の機能開発は行われておらず、サイクルタイムの計測対象となるタスクはほとんどありませんでした。

リアーキ計画の始動は12月のはじめ、KMPの導入が決まったのは年末12月半ばで、モノレポ化でKMPが導入できたのは翌年の2月後半ごろでした。その間に準備として環境構築・モノレポ化の運用ルール制定・Kotlin/NativeとKotlin for Androidの差異の学習など、新しい技術スタックへの適応期間が必要でした。

つまり、KMP導入には準備期間として約2ヶ月の初期コストが必要だったということになります。

(2) 2024年3〜7月:サイクルタイムの悪化からリアーキ計画終了まで

導入前の2023年11月(最後の機能追加を行った月)と比較すると、2024年初期はむしろ開発効率が悪化している傾向が見られます。
KMPの共通化領域の開発が最も活発だったのは4月ですが、この月のサイクルタイムが一番悪い結果となってしまいました。これはKMP自体の学習コストの高さが要因と考えられます。
特にiOSエンジニアにとっては、KotlinとAndroid Studioを含む新しい開発ツールの学習が必要となっており、初期の生産性低下は避けられなかった形になります。

なお、5月ごろにはKMP部分の実装自体はほぼ完了しています。5月〜7月の期間は並行してリアーキテクチャが行われたUI/Application層に関わる細かいバグの修正が数多く発生しており、その修正にチームで取り組んでいました。
そのため、数値の改善はKMPによる成果ではなく、発生したタスクの性質によって起きたものだと考えられます。

(3) 2024年8月以降:新規開発再開

リアーキ計画が完了し、iOS/Android各メンバーがKMPに適応して、通常のエンハンス開発に戻りました。

サイクルタイムは学習期間中に悪化していた状態から改善し、導入前とほぼ同程度の水準まで回復しました。つまり、学習コストを払い終えて安定期に入った状態と考えられます。しかし、この時点ではKMPによる工数削減の効果はまだ見られていませんでした。

(4) 2025年以降:効率化の活動開始

2025年に入ると数値が改善されていきました。2025年6月時点では、サイクルタイムはKMP導入前の約130時間から約20時間へと大幅に短縮されました。
実は、この少し前から開発生産性の改善についてチームで取り組み始めていました。KMP導入を機に行われた「iOS/Androidチームの統合」により協力体制が整っていたことで、計測・振り返り・改善のサイクルをチーム全体で回せるようになりました。その結果、大幅に時間を改善できたという背景があります。

すなわち、最終的な開発効率の改善はKMPによるコード共通化だけでなく、複数の要因が組み合わさった結果として表れたものだと考えられます。

反省点

振り返ると、計画していた範囲の共通化は達成できましたが、アーキテクチャ設計の議論に十分な時間をかけられずより広い範囲での共通化機会を逃していました。

例えば、現時点ではUI/Application層は分かれた実装になっているため、そこに起因する実装差異はまだ解消できていません。もしも次の図のようにApplication層を含めて共通化する動きを行えていれば、実装差異の解消という意味ではより効果を発揮でき、よりアプリ全体として理想に近づけたのではないかと考えています。

まとめ

KMPを導入し、その活用のための工夫を通して、実装差異の解消や開発効率の向上という部分を計測しました。
改めて振り返ると、KMPをただ導入しただけでなく、その活用のためにチーム体制を大きく変えたことが印象的でした。
まとめると、次のようになります。

  • KMPによって、計画していた範囲の共通化ができ、そこに起因する実装差異の解消ができた
    • 反面、設計を詰めきれておらず、共通化範囲をより増やすべきだったという反省が残った
  • KMP単体では開発効率の改善には繋がっていなかった
    • しかし、その過程でチームが統合されたことで、その後の計測と改善のサイクルがスムーズだった

今回の経験から、KMP導入が効果を発揮するには次の条件がすべて揃っていることが重要だと分かりました。

  1. 明確な技術的ニーズがあり、設計に十分な時間をかけられる
    • iOS/Android間の実装差異を解消したい課題が存在し、共通化できる領域が十分にある
    • 既存アーキテクチャとの整合性を検討しつつ、共通化すべき範囲を見極め、将来の拡張や変更も見据えた設計像をチーム全体で描ける
  2. チーム体制を整えられる・または整っている
    • iOS/Androidエンジニアが協力して開発・レビューできる関係性を構築できる
    • チームメンバー全体がKMPの学習に対して前向きに取り組める
    • 開発生産性の向上に向けての改善サイクルをチーム全体で回すことができる

逆に、上記が満たせていない場合は強みを最大限に発揮することが難しいと考えています。
これらを踏まえ、自分たちの状況に合わせて判断することが重要になるのがKMPだと感じられました。

この記事が参考になりましたら幸いです。

参考資料