Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

【Sansan Tech Talk】モバイル開発の技術的挑戦 〜KMP導入で目指す開発生産性の向上〜

こんにちは、Sansan Engineering Unitの部長を務める、笹川 裕人です。今回で5回目となる「Sansan Tech Talk」。この企画はSansanのテックリードたちが直面している技術的な課題や取り組みについて深掘りする連載企画です。 今回はMobile ApplicationグループのAndroidエンジニアである北村 研二にインタビューしました。

▼連載記事はこちら
buildersbox.corp-sansan.com

(写真左から)Mobile Applicationグループ 北村 研二、Sansan Engineering Unit 部長 笹川 裕人

笹川:今回のゲストは、Mobile Applicationグループの北村さんです。北村さん、まずは自己紹介をお願いします。

北村:技術本部のMobile Applicationグループで、プロダクト横断チームのAndroidエンジニアをしている北村 研二です。よろしくお願いします。
Sansan株式会社には2019年の4月に入社しました。前職は小さな受託会社で、Androidエンジニアとして働いていました。Androidが登場し始めた頃、たしかAndroidバージョンが2.0とかの時期から、日本の大手家電メーカーが開発するタブレット端末のアプリ開発、主にOSの開発に携わっていました。家電メーカーがスマホの生産を減少させた後は、車載Androidシステムの開発を担当しました。車載システムには標準のAndroidにはない機能が多く求められ、それを設計・開発する仕事でした。依頼を受けて、設計から実装まで、他のエンジニアと協力して作り上げるという形で働いていました。

笹川:車載用Androidの開発は、ローカルでどこまで進めて、車載で結合するのか興味があります。どんな感じで進めるんですか?

北村:車載の場合、実機を机の上に置き、ビルドマシンでソースコードを書きます。ソースコードはLinuxマシン上でEmacsなどで編集し、ビルドして実機に書き込みます。そのほかのアプリは、ビルド済みのものをOSから呼び出していました。実機があるのでハンドルやウィンカー、エアコンのスイッチなどが一式になっていて、普通のAndroidの開発では味わえない楽しい体験でしたね。

笹川:ありがとうございます。今回の企画では、北村さんが所属するMobile Applicationグループでの技術的なチャレンジや、これまでの取り組み、今後の目標について聞かせてください。

北村:はい、私たちが所属している技術本部では、直近1年で生産性向上に注力しており、その施策の一つとしてKMP(Kotlin Multiplatformの略)を導入し、生産性を上げる取り組みをしています。

笹川:具体的にはどのような取り組みですか?

北村:これまでのモバイル開発は、iOSとAndroidのチームが独立して開発しており、仕様の調整に多くのコミュニケーションコストがかかっていました。例えば、先行してAndroidで開発したものをリリースし、その後iOSで開発する際に、PdMと合意を取った仕様には含まれないような細かな違いを調整するのが大変でした。
また、同じ仕様のプログラムを2回作るコストも課題となっていました。これらをKMPの導入で解決したいと考えていました。

笹川:なるほど。現在の進捗状況はどうですか?

北村:基盤の設計と実装が完了し、現在は実際のプロダクト開発にKMPを導入して開発を進めようとしている段階です。

笹川:まだストアにあるアプリには反映されていないんですね。開発への導入スケジュールはどうですか?

北村:最初のKMP導入プロジェクトは現在設計中で、リリースは8月上旬になる見込みです。

笹川:それは楽しみですね。ちなみに、iOSとAndroidを統一的に開発する仕組みには、他にもReact NativeやFlutterがありますが、KMPを選んだ理由は何ですか?

北村:そうですね。もちろんFlutterも選択肢の一つでしたが、Dartという現在使っていない言語を新しく学ぶ必要がありました。一方、KMPは既存の資産を活用しやすく、既存のロジックを呼び出せて、新しく追加する一部分だけKMPで作れるところにメリットを感じたのでKMPを選定しました。

笹川:なるほど、まだまだ世間的に事例が少ないチャレンジングな取り組みだと思いますが、導入に際してチーム内の議論の経緯でどのように決まったか教えてもらえますか?

北村:技術本部のOKRとして生産性向上を掲げたことが大きかったと考えています。KMPという新しいものを導入することに対して、一定の抵抗感はありましたが、生産性向上という目標に合致する取り組みであったため、納得感を得られました。
また、導入後もプロダクト横断チームがサポートすることを提案したことで、合意形成ができました。

笹川:実際に現在の開発で感じているメリットや、将来的に期待する成果はありますか?

北村:KMPでビジネスロジックの共通化が達成され、さらに各OSのネイティブ機能を使うことでビューの部分の生産性も向上しています。また、将来的にはKMPプロジェクトでUI部分も共通化できる技術がセットであるので、導入すればAndroidとiOSが同じコードでかける環境を実現できます。これはだいぶ先の大きなチャレンジですが、目指していきたいです。

笹川:ビューまで行くとかなり攻める感じですね。そこまで進むと分けて考える必要がない状態を作れるんですね。ハードウェア対応はKMPにとって厄介だと思いますが、対応は進んでいますか?

北村:そうですね。KMPはOSの違いを吸収できる仕組みを提供する技術であり、OSの違いを全て吸収してくれる技術ではありません。そのため、自分で実装しないといけない場面が多々あります。例えば、日付のフォーマット処理です。KMPでは提供されていないため、OSそれぞれの仕組みを使って共通化しなくてはいけません。本当はKMPのライブラリで対応してくれたら嬉しいですが、KMPは共通化する仕組みを提供するだけなので、大変な部分もありますね。

笹川:プラットフォーム側でその厚みが調整されている感じなんですね。ライブラリー提供側の設計判断は勉強になります。今後の進展が楽しみですね。
他に生産性向上のトピックで、KMP以外で取り組んでいるものや、今後やっていきたいことはありますか?

北村:そうですね。以前はビューのコードをiOS、Androidそれぞれで書く必要がありましたが、今はFigmaというデザインツールを使ってUIを作成し、それをエンジニアがiOSの場合はSwiftUI、Androidの場合はJetpack Composeで作ります。しかし、デザインを見てコードに書き起こす際に、デザインのドット数が4なのに実装では8になっているといった細かい違いが生じることがあります。プルリクエストのレビューでも、数字や色味、アイコンの大きさの違いをチェックする必要があります。

笹川:設計の本質というよりは、何か間違いを探しているような感じですね。

北村:そうなんです。そのため、単純作業のコストを削減するために、Figmaのデザインからコードを自動生成する仕組みを考えて進めています。AndroidだとRelay for Figmaというプラグインがあり、これを使うとJetpack Composeのコードを自動生成できます。これをSansanとEightのAndroid開発に適用できないか調査しています。

笹川:UIからのコード生成についてですが、生成されるコードがあまり良くないという話も聞きます。単純に導入するだけではうまくいかない印象はありますか?

北村:それはコード生成ツールの作り込みと、そのコード生成ツールが変換しやすいデザインになっているかに影響を受けます。SansanとEight両方に適用を検討しましたが、デザイナーのデザインの作り方によって結果が変わります。Sansan側は適用しやすく、変換したら概ね問題ないコードになりますが、Eight側は絶対座標で置いているため画面の幅に対応できず、そのままの適用が難しい状況です。

笹川:なるほど。我々のプロダクト組織は、デザイナーやその他のプロダクト開発に関わる役割の人が近くにいるので、この課題を解決するのにいい環境かもしれませんね。

北村:そうですね。実際にSansan側で効果が出たら、Eight側でもデザイナーと交渉しようと考えています。

笹川:それは良さそうですね。両者にメリットがあると思うので、受け入れてもらえそうです。UI周りの作業は私もやったことありますが苦手意識があるので、これが実現するのは楽しみです。他に自動生成ではアプリ以外にAPIの検討はしていますか?

北村:デザイナーが作ったデザインからコードを生成する際と同様の問題がAPIにもあります。APIのドキュメントを見ながらモデルをスマホ上で実現するためのクラスを書くときに、nullableか非nullかを間違えてしまい、予期しない値が入るとクラッシュすることがあります。そのため、解決策としてツールを使ってコードを生成をすることで、写経をせずに済んだり、プルリクエストのレビュー負担を削減できると考えています。

笹川:なるほど。ドキュメントの品質によってできるかどうかが変わってくるんですね。

北村:その通りです。EightのWeb版では既にコード生成がされており、API通信部分が実装されています。これを基にEightのAndroidアプリにも適用できそうだと判断し、進めています。一方、Sansan側はAPI Blueprint形式で書かれていて、複雑なモデルになると日本語で「これは次のどれかになるよ」と書かれている部分が変換できず、問題が生じます。そのため、APIドキュメントからのコード生成はEight側では進んでいますが、Sansan側では現状難しい状況です。

笹川:SansanのMobileチームとWebチームの連携は、うまく対応できそうですね。圧倒的な改善が期待できるのであれば、解消できるような気がします。

北村:あとは変換ツールを使わずにAIを活用すると、曖昧な部分も対応できることがあるので、Sansan側ではAIの活用が望ましいと考えています。

笹川:確かに。Mobileチーム側の作業だけで完結できますし、AIを活用するのは良い取り組みですね。この課題を解決できれば、工数削減やトラブル減少につながり、ユーザー価値も上がりそうです。期待しています。ありがとうございます。
それでは、生産性向上以外の観点で技術的なチャレンジや今後の展望はありますか?

北村:昨年リリースしたEightのV10で公開したタッチ名刺交換が技術的なチャレンジでした。昨年4月のEight Networking EXPOにて先行で体験を提供するため、3月に本格的に開発を始め、2カ月弱の厳しいスケジュールで取り組みました。タッチ名刺交換における技術的な挑戦は、BLE(Bluetooth Low Energyの略)を使って位置情報を近くの端末に知らせ、電波強度を計測して名刺交換を行うというものでした。

笹川:2カ月弱でハードウェアのコア技術を使って機能実現するのは大変だったと思いますが、その中で工夫したことはありますか?

北村:そうですね。プロダクト横断チームとはいえ、Eightのドメイン知識を持っていない私たちが、Eight開発に直接関わるのは開発効率が悪いと判断し、役割分担をして新機能の開発を担当しました。私たちがBluetooth機能を使ってタッチ機能を実装し、並行してEightのプロダクト開発チームがそのライブラリを組み込み、UIを作り込んで、サーバーとの通信を担当するという流れで進めました。

笹川:並行して開発することで、何とか間に合う状況を作ったんですね。

北村:はい。機能の中身が決まっていない段階からライブラリのインターフェースだけ決めて、アプリ担当チームにはこのインターフェースでデータがくるから先にそれを作っておいてと連携しました。私たちはライブラリだけを作り、サンプルのテストアプリでタッチのテストを行い、安定性や精度を高めました。

笹川:インターフェースを切ってそれぞれ独立する、という一般的なソフトウェアプラクティスを効果的に用いた事例ですね。素晴らしいです。
この機能は使ってみると分かりますが、とても体験がいい機能なので、それが1カ月ちょっとで作られたのは驚きです。ソフトウェアプラクティスでよく言われることですが、合流したときにうまくいかなかったことや苦労はありませんでしたか?

北村:もちろんありました。つなぎ込んでうまくいかなかったり、動かしてみてより良いユーザー体験のためには機能が足りないことに気付いたりしました。そのため仕様を急遽変更することもありましたが、デバッグ用に多くの情報を取れるインターフェースを用意していたので、開発チームがそのインターフェースを使って乗り切りました。

笹川:流石ですね。追加機能に必要な情報を先回りして用意していたんですね。そのおかげで、EightのV10のタッチ名刺交換は余裕を持って開発完了できたんですか?それともイベントの数日前まで頑張っていたんですか?

北村:そこはかなり大変でしたね。昨年4月のNetworking EXPOでの最初のバージョンは、イベント会場でデモを行う程度だったので、精度はそれほど求められていませんでした。しかし、V10リリースに向けて一般ユーザーにも使ってもらおうとしたとき、パフォーマンスが問題になりました。最高の名刺交換体験を実現するためには、この速度では不十分だとPdMから指示があり、9月末のリリースに向けて多くの苦労を経験し、リリース直前まで調整が続きました。

笹川:そのパフォーマンス向上のために、どんな工夫や課題の解決があったんですか?

北村:4月のEight Networking EXPO版では、Bluetooth機能を使ってタッチアイテムを検出し、相手と接続してからアプリ側にコネクションを渡し、通信を行ってメッシュ交換をしていました。この方法では、タッチしてから1.7秒ほどかかっていました。ユーザーからすると1.7秒間反応がないため、本当に動くのか心配になってしまいます。そこで求められたのはSuicaのような即座の反応速度でした。そこで私たちが考えたのは、事前に接続する方法でした。一定距離に近づいている間にコネクションを張っておき、タッチが検出されたら前もって接続しているコネクションをすぐにアプリに渡せるようにしました。これにより、タッチの速度を2.7倍高速にできました。また、アプリにコネクションが渡された段階でUIを変化させ、ユーザーにタッチ機能が反応したことを伝えられるようにもしました。

笹川:2秒弱が3倍速くなると、ほとんど瞬時にということですよね。技術的な工夫に加え、見せ方でも体験を向上させているのが素敵だと思いました。これからも頑張ってください。ありがとうございました!

北村:こちらこそ、ありがとうございました。お疲れさまでした!


20240312182329

© Sansan, Inc.