LayerX エンジニアブログ

LayerX の エンジニアブログです。

なぜバクラク申請・経費精算はFlutterでアプリの作り直しをしているのか


バクラク申請・経費精算チームでモバイルエンジニアをしている id:kikuchy です。

埼玉県民として翔んで埼玉の2作目を履修してきました。埼玉県民が東京の池袋に集まって会議しているところや、県民の日にみんなが夢の国に行ってしまうあたりがリアリティあって良かったです。今作も笑わせてもらいました。

この記事はLayerXテックアドカレ2023の30日目の記事です。
前回はチームメイトの @_chocoyama さんによる 【特別対談】 Flutterエンジニアの今オレ x iOSエンジニアの過去オレ でした。chocoさんの時空を超える能力が最大限活かされた、Flutter開発の現場に対する不安が払拭される素敵な記事でしたね!
次回はカードチームエンジニアの Omoriさんの記事になります。楽しみ!


本日は、現在Flutterを使用して再開発しているバクラク申請・経費精算のモバイルアプリについて書かせていただきます。

バクラク申請・経費精算のモバイルアプリの現状

すでにバクラク申請・経費精算のモバイルアプリは各種ストアからダウンロードしてご利用いただけます。

バクラク申請・経費精算

バクラク申請・経費精算

  • LayerX, Inc
  • ビジネス
  • 無料
apps.apple.com
play.google.com

起動していただけるとおわかりになる通り、WebViewでモバイルブラウザ用の画面を表示している、いわゆるWebViewアプリとなっています。
WebViewアプリとして開発しリリースに至った経緯については、過去にこのブログで書いておりますのでそちらを御覧ください。
tech.layerx.co.jp

どうして作り直すことに?

体験が良くなかったから、です。

2022年当時、WebViewアプリにすることを決めた一番大きな理由はエンジニアリソースが少ないことでした。
リソースを節約しつつ、アプリという形でお客様に機能を提供できたので、当初の技術選定としては間違いではなかったと思っています。
アプリをリリースした大きな理由の一つである交通系ICカードの読み取り機能もWebViewのJavaScriptブリッジで実現できましたし、エンジニアが少ないまま機能拡充するという当初の目的は果たせたのです。

しかし、やはりリリースしてから見えてくるものもあります!

アプリを使っていただいたお客様から、現在のWebViewアプリ(Webアプリケーションのスマホ用表示を含む)の使い勝手についてたくさんのご意見をいただきました。
こうしたご意見には「これはWebのままでは解決が難しいのではないか」というものも多く、体験改善の難しさが目立ってきたのです。

プレスが出ている通り弊社は調達も行い、今ならモバイルのエンジニアも増やせるぞ、というタイミングになったことも相まって、2023年のはじめ頃からモバイルエンジニアの採用を強化と、アプリの脱ガワアプリ化を目指す動きが始まりました。

layerx.connpass.com


検討した技術スタック

採用でエンジニアを増やせそう、と言っても際限なしに増やせるわけではありません。
10人増やそうったって、予算上限もありますし、コミュニケーションコストも上がるし、第一にオンボーディングの時点でキャパオーバーが目に見えています。

当面は1,2人程度を採用することを目指して、それでも爆速でリリースを迎えてメンテナンスもできる、そんな技術スタックを探すことになりました。

要望と要件

莫大な機能を持っているバクラク申請・経費精算のアプリ用再実装を、2-3人チームで、発足から3-6ヶ月で完遂できる。

そんな要望で技術スタックを探します。
3-6ヶ月でリリース?!んな無茶な。しかしそれをなんとかする方法を探すのがバクラクの爆速開発。

公開できるものに限っていますが、主にネックとなるであろう技術要件は以下でした。

  1. UIや申請フォームの複雑なバリデーションロジックをiOS/Androidで共用できる
  2. PDFをインライン表示できる
  3. 将来の拡張性のため、iOSのApp ExtensionやAndroidのWidgetを実装できる

それぞれをちょっとだけ解説します。

バクラク申請・経費精算はお客様の企業様の業務に合わせて、申請フォームを企業様内で定義できます。
例えば「初めて使用するクラウドサービスは申請しないと使えない。扱う情報がクラスAの場合はサービスのURLのみで良いが、クラスBの場合はプライバシーポリシーのページURLも記載すること」という規定があったとします。
この場合、フォームは以下のように構成します。

  • 扱う情報の区分
    • ラジオボタンで選択
      • 選択肢は「クラスA」「クラスB」
    • 常に入力必須
  • サービスのURL
    • テキスト入力欄
    • 常に入力必須
  • プライバシーポリシーページのURL
    • テキスト入力欄
    • 扱う情報の区分が「クラスB」のときのみ入力必須
「クラスA」「クラスB」を切り替えると、他の入力項目が入力必須になったりそうじゃなくなったりする例

他の入力項目の値によってバリデーション条件が変化するのがわかります。
条件に合わせて必須か否かが自動的に切り替わるため、従業員の方が「この場合はどれが必須なんだっけ」と迷わずに済み、申請のハードルが低いフォームが出来上がるのです。
そして、実際にはもっと複雑な組み合わせを作ることが可能です。

もちろん、アプリでもこれを実現しなければなりません。
これを2OS分実装してメンテナンスもする、というのは品質確認にかかるコストが莫大になります。開発中の簡単な動作検証も一苦労です。
この手間は可能な限り避けたいものとして、チームに認識されていました。

また、バクラク申請・経費精算はAI-OCRによる領収書などの自動読み取り機能があります。
カメラで撮影したレシートをアップロードすると、数秒で金額欄や取引先名を埋めてくれる優れものです!
どの部分を読み取ってフォームを埋めたのかは画像上にマーカーを表示することで示しているので、もし読み取り間違いがあったときも「どう間違ったのか」を説明でき、納得感の高い体験になっています。
このマーカー付き画像をPDFとして作成しているため、快い体験のためにはPDFの表示ができることが必須なのでした。

ランチで行ったお店のレシートもこの通り!レシートのどこを読んだのかがわかります


そして、せっかくネイティブアプリにするのです。
アプリが起動していないときも含めた体験も追求したい!
そうすると、ホーム画面や共有画面など、アプリ外の画面についても開発したいケースが出てくるでしょう。
そうしたときに「Swift/Kotlinじゃないから諦めないと…」と言いたくない!
ちゃんとそうした機能を開発できる余地を残しておきたいのです。

https://developer.apple.com/jp/app-extensions/


これらの要件を満たしながら高速に開発する必要があるため、複数OSの機能をワンソースで実現できるようなクロスプラットフォームフレームワークをメインに、複数のスタックを検討しました。

ネイティブ開発(iOSはSwift + SwiftUI、AndroidはKotlin + Jetpack Compose)

現在のWebViewアプリはiOSとAndroidを別々に作ってあります。
そこにそれぞれのOSで主流なUIフレームワークを乗せるという、正当進化の方策です。

OSのSDKを直接使用できるため、各OSが提供する機能をフルに活用できるという、ある意味で当たり前な、しかし最強のメリットがあります。
PDFの描画もiOS/Android共、SDKでサポートされていますし、使いやすくラップしたライブラリも公開されています。

コードベースについては、認証や計測など一部の既存のものは活かすことができますが、バリデーションロジックの共用はできません。
バクラク申請・経費精算の申請フォームは、利用者様の設定によって様々なバリデーションを組むことができます。
柔軟性が求められ、かつ複雑なこのバリデーションを二重実装、いや、現在のWebの実装も含めると三重実装をすることは、実装や品質保証の面で、今後のメンテナンスコストを劇的に増大させる可能性がありました。

Kotlin Multiplatform

www.jetbrains.com

日本国内でも複数のIT企業が採用しているフレームワークです。
ロジックはKotlinで記述します。Androidで大人気の言語なので、Kotlin向けの資産がすでにたくさんあるのも魅力。

最近はCompose for iOSのalpha版もでてきてUIのコード共通化の機運も高まってきましたが、まだアルファリリースとのことで、UIについてはiOSとAndroidで別々に記述する必要あり、と判断していました。

UIについては別々に記述するとなると、iOSやAndroidのライブラリを自由に使うことができます。もちろん、メンテナンスコストは両OS分発生しますが…

AndroidのWidgetはもちろん実現可能。iOSのApp Extensionも動作することをchocoさんに確かめて頂いたので、拡張性についても問題なさそうでした。

Flutter

flutter.dev


私が前職で使用していた技術でもあり、日本でも勢いがあるクロスプラットフォーム技術です。
ロジックをOSをまたいで使用できるというクロスプラットフォームフレームワークに一般的なメリットに加え、フレームワークが独自に画面を描画するという特徴があります。
これにより、バリデーションロジックだけでなくUIもワンソースで実現できるという大きなメリットがあります。


PDFの表示に関しても、プラグインがいくつか公開されている他、それらが要件を満たさなくても最悪PlatformViewを使用することでiOS/AndroidのPDF表示ライブラリを使用することで解決できます。

App ExtensionやWidgetはメモリや動作時間の制限があるため、ランタイム上で動かすDartで書くことは難しいとされています。
しかし、 @_chocoyama さんに実験していただいたところ、UIをSwiftUIなどOSネイティブな要素で構成しつつ、Dart Engine上で動いているDartのAPIを呼び出すのであれば実機でもメモリの制限内で動作させられることがわかりました。

また、 id:kikuchy がFlutterKaigiの運営でもあるため、採用市場に顔が利く、という点も若干プラスに働いた気がします。気のせいかも知れない。

Flutter採用の決め手は

ここまでで星取表は以下のとおりです。

ネイティブ実装 KMM Flutter
コードの共用 🔺
PDF表示 🔺
アプリ外機能実装

FlutterかKMMかで悩んでいたのですが、最終的にはUIを含めたコードの共用ができることを重く受け止め、Flutterを採用することにしました。

UIのコードを別々にしてしまうと、たとえロジックが共通だったとしても、UIレイヤーで生じるバグもありえますし、つなぎ込みでミスが発生する可能性があります。
結局、品質を確認する段階でのコストが増大するため、これを避ける決定をした、という形です。

Flutterを採用してどうだった?

UIの共通化が、当初の目論見通りの効力を発揮しています。
バクラク申請・経費精算は状態数がとても多いのですが、基本的にiOSシミュレーターで表示を確認しながら開発を進められています。OS固有の機能が絡む箇所は多くはないため、Androidでの表示と動作確認は適宜行うだけで済んでいます。

どのUIが開発されたのか・どんな見た目なのかをWidgetbookで共有したり、Atomic Designに沿って分類していたWidgetを別の方法で分類したりと、紆余曲折はあるものの、現在のチームが開発しやすく、メンテンナンスし易い方法を探しながら進んでいます。

新生バクラク申請・経費精算は絶賛開発中です!
俺たちの戦いはこれからだ!!

これから

リリースを迎えたら、ちゃんとしたアプリだからこそできることも追求したいと思っています。
日本の企業内の事務作業をどれだけ意識せずにできるようにするか、そこでアプリだからこそできることを実現してお客様に喜んでもらいたいですね!

もしFlutterで日本の事務作業をバクラクにすることに興味があれば、こちらのOpendoorからお声掛けください。お話しましょう!
jobs.layerx.co.jp



また、LayerXではCasual Nightという取り組みを始めました!
LayerXのメンバーと、プロダクトやチーム、エンジニアリングについてゆる〜くお話しながら色々な飲み物や食べ物を楽しむイベントです。

第3回のCola Nightは私も参加します!
何を隠そう、LayerXのコーラ部部員なのです。いろんなクラフトコーラを揃えておりますのでぜひ飲みにいらしてください!

jobs.layerx.co.jp