こんにちは。クルーズ株式会社CTOの鈴木です。
今回は、SHOPIST.com by CROOZのiOS/Android アプリをFlutterでリニューアルした話について書こうと思います。先日の7月27日に当社主催にて開催したテックカンファレンス「テックヒルズ」でもお話させていただきましたが、約1年間をかけ検証・機能移行を行い、現在公開に至りました。
過去記事と重複する部分などありますが、背景や何がどう変わったかについて改めて書かせていただいたので、リプレイス検討中の方やクロスプラットフォームに興味がある方は是非読んでみてください。
背景
詳細の話は「今後を見据えてFlutterの検証を始めた話 - CROOZ TECH BLOG」にまとめておりますが、大きくは以下の2つです
- iOS/Android設計・実装言語を共通化することによる生産性の向上
- iOS/Android設計・実装言語を共通化することによる技術スタックの統合
二次的なものを加えると、
- フルスクラッチで作り直すことにより、結果的に秘伝のタレ的なコードとの決別
が追加される感じとなります。
アプリリリース当時は、十分なアプリの開発体制が整っておらず、個人に依存していた部分が大きかったため、本来設計として共通化できる部分においてもiOS/Android間でプログラム設計が異なるなど言語以外の部分でも差異があり、設計に関する調査、保守コストを削減したかったというのも背景にはありました。
なぜFlutterだったか?
実装言語を統合する手段としては、クロスプラットフォーム言語ないしフレームワークがありました。XmalinやReact Nativeなど様々ある中でFlutterを選定した理由については、開発コミュニティの発展具合、情報量の多さ、参画するエンジニアのモチベーション、ライセンス上のリスクの大きく4点を各フレームワークで比較して最終的にFlutterを選定しました。
少し掘り下げると
①開発コミュニティの発展具合
これはわかりやすいかと思います。OSSプロジェクトなのでコミュニティが盛り上がってないとバージョンアップやバグの修正などの活動が十分に行われず、アプリは完成したはいいもののリリース後にFlutterSDKのバージョンアップが行われず自分たちだけででFlutterSDKを保守していかなければならないリスクがあります。そのリスクを軽減するための評価項目です。OSSのメリットを享受できないというリスクがあると考えていただければ理解しやすいかもしれません。
またUtility周りはゼロから作るよりもPackage,Pluginを積極的に活用して開発工数を減らしていきたいので、OSS活動が活発的なプロジェクトほど導入することで生産性を向上できるプロジェクトと考えていて、この項目を評価項目としていました。
OSSではなく商用であっても、開発チームやコミュニティについては同じ考え方で評価をしました。
②情報量の多さ
こちらもわかりやすいかと思います。公式のドキュメントがどの程度あるか、公式以外の参考文献がどの程度あるか?GitHubのIssuesで会話が流れているかなどです。
③参画するエンジニアのモチベーション
今まではエンジニア寄りでも少し上流の主にマネジメントレイヤーの人たちの会話みたいになってしまったのですが、それとは別に参画するエンジニアが興味関心があり、チャレンジしていたいと思える技術要素かという視点の評価項目です。
エンジニアである以上、多かれ少なかれ新しい技術にはだれもが関心があるとは思うものの、一方でエンジニアである以上度合いが違えど自分が好む言語や技術というものが必ずあるわけで、そこに合わないものを入れちゃうとマジでモチベーションが駄々下がりするので、やったことないけど興味関心が持てる技術要素かについて社内のネイティブエンジニア数名にヒヤリングをして、選定の参考としました。
④ライセンス上のリスク
「今後を見据えてFlutterの検証を始めた話 - CROOZ TECH BLOG」にも記載のとおりです。ここはリスク最小にしようねという話なので割愛します。
リプレイス中に苦しめられた諸問題
①WebView周り
Cookie制御、HTTP/HTTPSのMixedContents制御、JSで取得できるはずのイベントの取得ができない、一部call back動作がうまく動かないなど、WebView表示部分についてはなぜかうまく動かない系の問題が非常に多く、結局WebViewのPackageをFlutter公式のwebview_flutterからflutter_inappwebviewに切り替えてそこからさらにトライアンドエラーを進めながらなんとか問題が収束するに至りました。
基本的にメイン画面やUI/UXに凝る部分でWebViewを使うことはなく、Flutterの検証についてもメイン画面などのWebViewを使わない部分の検証がメインで、WebView部分についてはサーバコンテンツが表示され、表示崩れがなければ検証としては合格としていたためこの問題に気づくのが遅れ、修正対応に2~3週間ほど余分にかかってしまいました。なので私からのアドバイスとしては、
- WebViewのPackageをFlutter公式のwebview_flutterではなくflutter_inappwebviewにすべきだ。
- ネイティブアプリなんだからWebViewを使う範囲はなるべく最小にしたほうが良い。(特に新規でアプリ作る場合は使わないくらいの気概で進めるべき)
です。
②テキストボックスへのキー入力で謎のクラッシュ発生
テキストボックスからLost Focusしたタイミングでアプリがクラッシュする事象が発生し、調査するも原因がわからずかなり苦労しました。ようやくクラッシュのタイミングで関係のない画面までrebuildされていることまではわかったものの、なぜrebuildが実行されるのかの原因がつかめず、1か月以上試行錯誤を繰り返していました。
結局キーボード表示時にMediaQueryがrebuildを実行させていることが特定でき、回避ははできたもののかなりこの問題には悩まされ、最後のほうはFlutter SDKに手を入れPull Requestするしかないとメンバーと覚悟を決めてFlutterSDKのソースを1週間読むまでしました
1年かけてFlutterリプレイスして得たもの
①約2倍の生産性
端的に言うとiOS/Androidが同一設計同一実装にて実現できるフレームワークと体制、
もう少し正確にいうと実際にはOS個別処理や端末個別処理はあるし、デバッグは両OS個別に行わなければならない項目もあるため本当に2倍にはならないですが、概ね2倍のスピードは手に入れられていると思います。
②秘伝のタレ的なコードとの決別
もう一つ得たものとしては、上記の約2倍の生産性とも関連しますが、だれが作ったんだか何の意図があるのかもよくわからないコードを解釈しながら調査するという極めて無駄な業務から解放されたという事実です。
結構この調査にも今まで時間をとられていて、この決別を合わせると実際には2倍以上の生産性は手に入れられたのではないかと個人的には感じています。
Flutterリプレイスを検討している方へのアドバイス
最後に、Flutter導入を検討している方へのアドバイスです。
両OSを共通実装できるメリットというものは本当に大きいですが、やはり気つけるべきポイントはいくつかあるかと思い、私の視点ですが以下に記載します
①WebView注意
これは既に記載してあるため割愛します。flutter_inappwebviewを使ったほうが良いのではという話です。
②ナレッジに依存する部分が多い
ドキュメントは正直かなり豊富ではある反面、やってみないとわからない。もう少し正確にいうと、文法や実装方法の習得は文献やUdemy 等の活用でできるものの、実現したいことに対し、何のクラス、何のプロパティを組み合わせて実現するのが最適かがトライアンドエラーを繰り返さないとわからないという問題です。
もうこの問題については、趣味がFlutterのメンバーに半年遊んでもらってfeed Backをもらうか、経験者を最低1名参画してもらうくらいしか思いつかないです。
③バージョン更新が早い&ReleaseNoteがわかりづらい
あたりまえですが、Flutterは現在進行形で発展している技術なので、BashやSQLのように枯れている技術じゃないです。そのためFlutter SDKもパッケージのバージョン更新頻度も早いですし、Release Noteの記載も成熟したプロダクトと比較してしまうと結構荒いです。なのでこまめにバージョンアップはチェックし、ローカル環境で定期的に試すようにしたほうがいいです。
ちなみに当社ではfvmという Fluttterのバージョン管理ツールを使ってバージョンの管理をしています。Nodeでいうnpmのようなツールです。
今回は長文となってしまいましたが、ここ1年かけてFlutterでアプリをフルリプレイスした話を記事としてまとめました。
1年というと長いように感じるかもしれませんが、現状の仕様調査込み技術検証込みでの1年だったため今回紹介しきれないくらいの様々な学び、ナレッジがあるので、今後トピックとして共有していきます。
テックヒルズで公開させてもらった記事についてもこちらにリンクを貼っておきますので興味があったら見てみてください。