旅行計画アプリnicodyを支えるFirebaseの活用方法紹介
はじめに
結.JAPANでiOSアプリの開発を行なっています、@yuto_nakano44 です。
この記事では、現在開発・運用している旅行計画アプリnicodyでのFirebase活用方法についてご紹介できればと思います。
少しでもFirebaseを利用した開発に役立ったり、nicodyというサービスに興味を持ってもらえたら嬉しいです!
nicodyとは
まずは nicody というサービスについて紹介させてください。
nicodyは旅行計画ができるサービスで、
旅のしおり
を作って、そこに観光地や飲食店、訪れる時間などの情報を記録できます。
作った旅のしおりは旅行同行者と共有することで一緒にしおりの編集を行い、旅行計画することもできます。
nicodyは昨年11月末に1万ダウンロード突破し、新機能の追加や改善施策も控えており、nicodyのこれからに期待しながら開発してます。
ユーザーとしてもnicodyが好きで、事前にいきたいスポットや時間をしっかり計画しておきたい(それも楽しい)自分にとって旅行に行く時は欠かせないアプリです!個人的にテーマパークでの周り方をメモしておく使い方も良いなと思ってます!
利用している Firebase(GCP) の機能
早速本題ですが、nicody では主に上の図に示した Firebase(GCP)の機能を活用しています。
サービスの根幹となるアプリのデータ管理にNoSQL クラウドデータベースの Cloud Firestore を利用しているだけでなく、Dynamic Links や Cloud Messaging 等のエンゲージメントを高める機能も活用しています。
次から、機能ごとにどのような使い方をしているかを紹介させていただければと思います。
Authentication
まずはサインアップ機能を実現するために利用している Authentication についてです。
nicody では、ユーザーを識別して、ユーザーに紐づいたデータを保存したり、保存したデータにアクセスできるユーザーを制限しており、認証機能の導入は必須でした。
認証機能の提供にFirebaseのAuthenticationを採用している理由は以下の通りです。
- 無料で利用できる(電話番号認証は従量課金だがnicodyでは利用していない)
- セキュリティルールを用いたユーザーのデータを保護するアクセスシステムの構築に必要
- その他のFirebase機能と連携可能(ex. Cloud Functionsでのユーザー作成トリガー)
以下の認証方法を利用して、認証を行なっています。
- Apple
- メール/パスワード認証
サインアップ画面
Cloud Firestore
アプリで使われるデータの保存はNoSQLデータベースのCloud Firestoreを利用し、アプリからSDKを介してデータにアクセスしています。
Firestoreを採用している理由は以下の通りです。
- 一般的に行われているサーバーサイドアプリケーションの開発を行い、ビジネス要件への対応やパフォーマンスの問題への対応などの運用・保守を行うよりも、ある程度インフラを任せられ、クライアントエンジニアのみで開発可能なFirestoreを利用する方が、nicody開発の環境では低コストかつスピーディーに開発を進められると判断した
- リアルタイムリスナー機能、オフラインサポートというnicodyの体験をより引き立たせる機能を持っている
nicodyとリアルタイムリスナー機能
Firestoreはリアルタイムリスナーの機能とオフラインサポートという機能を持っています。
特にリアルタイムリスナーの機能はnicodyで求められる、「共同編集」「離れていても一緒に計画できる」といった体験を実現する上でとてもマッチしていると思います。
更新を確認するためにpollingする必要がなく、Firestoreでリアルタイムリスナーを有効にし、Firestore上のデータの変更が行われると、アプリ側に通知を送ってくれるため、重宝しています。
行程表画面
Firestore を活用した検索機能の実現
nicody には地域、スポットをユーザーによって入力された特定の単語をもとにデータ取得する機能(検索機能)があります。
検索画面
Firestore は以下のように、全文検索をサポートしていないため、Algoliaといった全文検索サービスの利用するか、Firestoreのみで完結する全文検索の仕組みを選ぶ必要がありました。
nicodyでは、コストの観点、検索に必要とされる要件の観点から、Firestoreのみで完結する全文検索の仕組みを導入しています。
Cloud Firestore では、ネイティブ インデックスの作成やドキュメント内のテキスト フィールドの検索をサポートしていません。さらに、コレクション全体をダウンロードして、クライアントサイドでフィールドを検索することは現実的ではありません。
https://firebase.google.com/docs/firestore/solutions/search?hl=ja
実現する仕組みは以下の通りです。
- データ保存時、全文検索の対象としたい文字列をN-gram(bi-gram)で分割してtrueマップとしてフィールドに保存
- ユーザーの入力文字列をN-gram(bi-gram)で分割し、上記で分割した検索対象の文字列に対してクエリを行う
全文検索対象の文字列
bi-gramで分割した文字列
// ユーザーから受け取った文字列をbi-gramにかけて、where句を作成
word.biGram().forEach { token in
query = query.whereField("tokenMap.\(token)", isEqualTo: true)
}
N-gram というアルゴリズムを用いた全文検索機能の詳細については以下の記事が参考になると思います。
Cloud Functions
他のFirebase機能のあらゆる操作をトリガーにコードを実行できるため採用しています。
具体的にはFirestoreへの変更をトリガーにFirestoreへ新たなデータ書き込みを行なったり、アプリに push通知を送ったりしています。
Functionsと関連するFirebase機能
Hosting
nicody ではアプリ内で公開設定をONにした旅のしおりを、Webで閲覧できるようにする機能があります。
公開設定画面
Web で閲覧するために、Hostingを活用してReactのプロジェクトをホストして実現しています。
簡単にデプロイが行うことができ、開発工数を削減できる点や、他Firebase機能との連携で様々な機能を享受できる点でFirebaseのホスティング機能を採用しています。
カスタムドメイン設定
また、デフォルトでは〇〇.firebase.web.app
のドメインが提供されていたのですが、nicody ではブランディングのため、カスタムドメイン(nicody.jp
)を設定して、利用しています。
Firebase Hosting コンソール
Cloud Messaging
旅のしおりに新しいメンバーが追加されたり、行程表の変更が行われたらpush 通知を送るようにしており、その際、無料かつ様々なプラットフォームにpush通知を送信できるCloud Messaging(FCM)を利用しています。
push通知を送るまでの流れ
Dynamic Links
Dynamic Linksは、アプリのインストールの有無に関わらず、複数のプラットフォームで機能するリンクで、以下の2つの用途で利用しています。
- 旅のしおりへの招待
- スポットの共有
Dynamic Linksを利用した招待機能の実現
Dynamic Linksを活用した旅のしおりへの招待の実現方法については以下のようになっています。
招待承諾までの流れ
招待の有効期限設定
nicodyではセキュリティ上の観点から、一度発行した招待リンクは30日まで有効としています。
有効期限の付与はFunctionsを用いて実現していて、FirestoreのInvitations
CollectionにDocumentが作成されたら、Cloud Functionsで有効期限(expiredAt
)のFieldを追加します。
Invitations/{invitationId}/expiredAt
招待リンクを踏んだらアプリ側から、招待に関する情報を取得し、Firestoreのセキュリティールールを用いて、expiredAt
が期限切れであれば取得を拒否するようにしています。
// イメージ
allow read: resource.data.expiredAt > request.time
有効期限切れの招待を踏んだ場合
App Distribution
リリース前のテストで、開発メンバーにアプリ配布を行うために App Distribution を利用しています。
また、自動化ツールの fastlane、CI/CD サービスの Bitrise を利用し、App Distribution のアップロードを行うことで、テストまでの作業の効率化を行なっています。
テストアプリ配布サービスは他にも存在しますが、App Distributionは、無料で使える点や、他のFirebaseの機能使っているためできるだけFirebaseで統一したかったため採用しています。
その他利用しているFirebase機能
Cloud Storage
- ユーザーのアイコンの画像や旅のしおりにアップロードされた画像を管理しています。
Crashlytics
- クラッシュログを記録し、コンソールで確認しています。
- クラッシュはしないものの、アプリ内でエラーが起こった場合を知っておきたいケースがあるため、非致命的なエラーとしてコンソールで確認できるようにしています。
Anaytics
- アプリ、Web のログ取得・分析のために Analytics を利用しています。
Remote Config
- 強制アップデートのフラグ、管理者ユーザーのIDなどを持たせて、アプリ側はその値に応じて振る舞いを変えるように実装を行なっています。
今後の展望
Firestore Version2 設計移行
nicodyアプリは、リリースしてから約半年が経ちました。
リリース前は今のnicodyアプリに比べると機能・要件が少なかったですが、検索機能、旅のしおりの拡充、Web版追加など、それぞれの機能開発で必要になったデータをFirestoreに追加する形で開発を進めてきました。
ある程度のアプリの機能・仕様の全体像が定まってきたこのタイミングで、今後ユーザー数が増えたときにも耐えられる設計への移行、そしてより開発スピードを早めつつ、品質も担保するための仕組みづくりを始めています。
主に取り組んでいることは以下の通りです。
- 設計規約の定義
- 規約設定の主な観点
- スループットを高める
- 最大限セキュアにデータを扱う
- 統一性(CollectionやFieldの命名,リレーションの方法)
- 規約設定の主な観点
- 設計規約に基づいた既存設計からの移行実装
- クライアント側のFirestoreインターフェースのリファクタ
- 設計やCloud Functionsの活用で解決できるクライアント側コードの肥大化の改善
Version2設計移行の背景、進め方、やったことについては改めて記事にできればと思います。
おわりに
nicodyでどのようにFirebaseを活用しているのか紹介させていただきました。
Firebaseの機能を多く活用する環境で開発してみて、機能を組み合わせることで、幅広い体験、要件に対応できる点で、非常に強力なサービスだと思いました。
一方で、Firestoreのセキュリティルールや、この記事で紹介させていただいた機能ごとの仕様や特徴を見落とすと、ユーザー体験を損なったり、負債となってしまう可能性があるため、Firebase関連情報のインプット&アウトプットや拡張性、信頼性を意識したシステムを作りを続けていきたいと思います。
最後までお読みいただきありがとうございました。
Firebaseの活用方法について「自分はこうしてるよ!」等あれば、ぜひお話し聞かせてください!
また、nicodyの開発に興味を持っていただけた方はTwitterにてご連絡お待ちしています!
他nicody開発メンバーも記事を投稿してますので、一緒に読んでいただけると嬉しいです。
▼弊社代表 中山さんの記事
▼弊社取締役 府川さんの記事
▼弊社エンジニア 新納さんの記事
近日公開予定
【nicody開発メンバー募集!】
nicodyを一緒に作り上げていくメンバーを募集中です!
◆ iOSエンジニア(Swift)
◆ WEBエンジニア(React)
を中心にあらゆる職種を募集しています。
弊社代表 中山さんのリンクへお問い合わせお願いいたします!
◯ツイッター
◯facebookメッセンジャー
Discussion