Xtoneでのスマホアプリ開発時の技術選定

エクストーンの大久保です。以前の記事では主にWeb開発の技術スタックについて、豊田の方から話をさせていただきましたが、今回はスマートフォン向けのネイティブアプリ開発時の技術スタックや、選定理由について私の方から紹介いたします。

早速ですが、エクストーンにおけるスマホアプリ開発時の技術スタックは以下になります。

アプリ開発で主に利用している技術スタック

  • iOS
    • 言語: Swift
    • ライブラリ: Alamofire, Realm, Lottie, R.swift, LicensePlist
    • パッケージ管理: Swift Package Manager, CocoaPods, Carthage
  • Android
    • 言語: Kotlin
    • ライブラリ: Android Jetpack(LiveData, ViewModel, Navigation, etc.), Retrofit, OkHttp, Realm, Lottie, Koin
    • パッケージ管理(ビルドツール): Gradle
  • 共通
    • クロスプラットフォーム開発: Flutter, Unity
    • mBaaS: Firebase
    • CI/CD: Bitrise
    • デザイン: Figma, Zeplin

Swift / Kotlin

まずはアプリ開発のベースとなる言語やフレームワークですが、弊社では基本的にSwiftとKotlinを使用してネイティブアプリとして作ることが大半です。例外としては、ゲーム的なUIや演出が必要な場合はUnityを、クロスプラットフォーム開発がマッチするようなプロジェクトでは、Flutterを選択することがあります。
弊社では比較的に早くにObjective-CからSWift、JavaからKotlinに乗り換えてきました。特にSwiftの方は、バージョン1が出た直後から利用開始した結果、 Swift3でシンタックスが大きく変更されてしまい、移行に苦労したりもしました。しかし、早めにキャッチアップすることで、言語のコンセプトや変更された理由などにも理解が深まり、結果的にはメリットの方が多かったと考えています。
目に見える効果としては、Null Safetyの機能により、クラッシュが減ったことが挙げられます。

Flutter

前述したように、最近はFlutterの利用も検討段階ではよく挙がるようになってきています。
アプリの開発を行う際には基本的にiOS/Androidの両OS向けに作成するので、であれば1つのソースコードで複数のOS向けの開発が行えることは単純にメリットです。その他の利点としては、OS間の実装やそれに伴う挙動が一致することがあるかと思います。OSごとの流儀やその基になったコンセプトは尊重すべきだとは思いますが、OSによって挙動が違うと、プロジェクト内ではたびたびそれが混乱のもとになります。あえてやっている場合はよいのですが、大抵はiOS、Androidの実装担当者の認識のズレやコミュニケーション不足から、結果的に実装差分が生まれてしまっていることが大半な印象です。
Flutterを利用する場合は、チーム構成にもよりますが、弊社のエンジニアチームの規模だと両OSの担当者が力を合わせて1つのアプリを作成して行くことになるため、このギャップを埋めることができると感じています。
一方で、当然Flutterも万能ではなく、苦手な分野も多々あります。特にOSの機能をフル活用するようなアプリや細やかなチューニングが必要となるアプリでは向いていません。もちろん、必要な部分だけネイティブで書き、共通化できる部分はFlutterで実装するという組み合わせもありですが、その比重がネイティブ側に偏っていけばいくほど、Flutterを利用するメリットが失われていきます。
このように採用の判断は慎重に行う必要がありますが、アプリがOSの機能と密に連携しない場合は、十分選択肢になりえると状況になってきていると思いますので、今後も積極的に採用していきたいと考えています。

自動テスト

自動テストの導入具合については、正直なところプロジェクトを開始した時期やメンバーによってバラバラな印象です。特定の日時で発火するような機能など、実際に試験環境を用意しにくいケースについては、さすがにテストが書かれていることが多いですが、必要十分とは言い難い状況です。
必要なところにだけテストを書いている、という言い方もできるかもしれません。
最近のプロジェクトではMVPやMVVMなどテストを比較的行いやすいアーキテクチャを採用することが多いこともあって、古いプロジェクトに比べると比較的テストが充実しています。この辺は、そもそもテスト行うためにそういったアーキテクチャを採用していることもあって、卵と鶏な感じですが、やはり新しいプロジェクトのほうがテストが書かれている割合は多そうです。
またそれらの多くはユニットテストで、UIテストについては占める割合がさらに低くなります。
UIテストが相対的に少ないこと自体は、テストピラミッドの考え方には基づいているので、問題はないのですが、機会があればアプリでUIテストをがっつりやることも挑戦していきたいとは考えています(だって夢がありますよね?)。

CI/CD

CI/CDはBitriseを利用しています。テストは先に書いたとおり十分だとは思っていませんが、テストが存在するプロジェクトであればCI上でプルリクエスト作成時やマージされるタイミングで実行して、品質の担保に寄与されています。
その他では主に開発中のアプリの配布の利用されています。Androidの場合はFirebase App Distributionを、iOSの場合はTestFlightを用いて配布を行うことが多いです。
一方で、アプリストアへのリリースの自動化は、ほとんど行われていません。これは受託開発ではクライアント側でリリース作業を行っていただくことが多く、弊社側でリリースまで行うことが稀だからです。

パッケージ管理

最後に基本的にiOSのみの話になりますが、パッケージ管理の話です。CI/CDの項でも書きましたが、弊社は受託開発を基本としているので、自身がストアへのリリースを行うことは少なく、最終的なビルドもクライアント側で行うことが多いです。クライアント側にiOS開発に詳しい方がいるとは限らないので、ビルドを行い、アプリをストアへアップするまでの作業を減らすことが重要となります。現状でも、CocoaPodsで行うライブラリのインストールを事前に済ませるなどの工夫を行っています。
iOSでは近年Xcodeと統合されたSwift Package Managerが登場しました。これを利用するとXcode外でのビルド前の準備が必要なく、プロジェクトを開いた際に依存する外部ライブラリが自動取得されるので、クライアントへプロジェクトを渡す際の手間が省けたり作業ミスが減ることが期待されます。
現在のところ、フルでSwift Package Managerに移行したプロジェクトはまだないので、その効果の程を実感できていないですが、今後積極的に移行していきたいと考えています。

おわりに

いかがだったでしょうか。
本当はWeb側の技術スタックの記事が公開されてから、すぐにこの記事も公開できればよかったのですが、かなり間が空いてしまいました。各項目を掘り下げた話はできていませんが、読んでいただいている方の何かの参考になれば幸いです。
今はまだWeb開発の記事が多いですが、今後はアプリ開発の記事も増やしていきたいと考えています。