Firestore導入前に知ってほしい。３層に分解して、メリット・デメリット比較と使いどころを考える


# はじめに

Firebase Cloud Firestoreは個人的に非常に期待しているサービスです。Firestoreは従来のモバイルアプリ開発の3層の概念を統合したサービスだと感じています。

<img width="661" alt="CloudFirestore.png" src="https://qiita-image-store.s3.amazonaws.com/0/24308/23c72e50-8517-b029-6ec5-609e4ec02a6e.png">

例えばデータ同期するモバイルアプリを作る場合、以下が相当します。

- クラウドDB （ex. MySQL)
- API/WEBアプリケーション (ex. Ruby On Rails)
- モバイルDB (ex. realm)

この３層を一手に引き受けてくれるのがFirestoreの存在です。これらの開発をしないで済むなら「神」のような存在ですよね。

本当にFirestoreは神サービスなのか？
私の答えは**「NO」**です。

それでもとても強力で素晴らしいサービスであることは間違いないです。どんなメリット・デメリットがあるのか３層の観点からそれぞれ考えてみました。導入する前に本当にFirestoreを使ってよいのか？考える参考にして頂ければと思います。

# TL;DR

- いいことばかりではなく、トレードオフを理解しよう
- クライアント側の開発に負担を強いることになる（逆説的にアプリエンジニアにはサーバー不要で魅力的に見えてしまう）
- それでもスピード重視なら使う（ただし覚悟必要）


# 1. モバイルDBとしての評価

**総合評価： ☓　微妙なところ**
どこまでいってもNoSQL。それを理解して使う必要あり。

### オフライン対応

**結論：オフライン対応は出来ているが、通信不安定では待たされる**

完全なオフライン時には、キャッシュからデータを引き出してくれます。ただし、100%lossの時（通信不安定）は、読み込み待ちが発生しキャッシュからもデータを引き出す事ができず待たされます。ローカルデータベースと同期部分が切り離されて柔軟になってほしいですね。例えば自分でタイムアウトを設定出来るようにするか、キャッシュに直接アクセス可能になるなど。

参考
[Firestoreで作るオフライン動作対応の iOSアプリ](https://medium.com/swift-column/firestore-offline-edee47ee72cc)

### スキーマレス

**結論: 柔軟だが、それゆえに難しさも**

FirestoreはNoSQLのためスキーマレスです。マイグレーションとも無縁です。ただスキーマが決まっていないということは、常にそのデータが存在するかどうか分からないということです。参照の場合、便利がゆえにクラッシュリスクが潜みそうな部分です。

### リレーショナル

**結論: 複雑になるのは必至**

これもNoSQLを扱う上で避けて通れないところだと思います。リレーショナルに参照したい場合にはやっぱりあると思います。その場合、いくつものクエリを発行する必要が出てくると思うので、データ設計と同期のレイテンシを気にするには難易度が高そうです。

参考
[Cloud FirestoreのSubCollectionとQueryっていつ使うの問題
](https://qiita.com/1amageek/items/d2ef7a49bccf5b4ea78e) [RDB技術者のためのNoSQLガイド　NoSQLの必要性と位置づけ](https://www.slideshare.net/recruitcojp/rdbnosqlnosql)


# 2. API（WEBアプリケーション）としての評価

**総合評価： △　強力だが柔軟性が課題**
高スケーラビリティのあるAPIと考えると強力ですよね。ユーザー認証不要なデータであれば、より使いやすい。

#### 認証

**結論： ~~やるには覚悟が必要~~ 既存の認証サーバーとも統合可能**

ユーザーのアクセス制御はFirebase Authenticationによって実現できます。これはメリデメありますね、既存サービスとして認証を持っている場合、これと統合させる必要があるので、~~かなり辛そうです~~。新規サービスでガッチリ使う場合、Firebaseと心中できるかの決断を迫られるポイントです。Firebase Authenticationの良さもあるので上手くハマれば開発を高速化できます。
~~逆にここが自社サービスや他社サービスと柔軟に出来るようになれば使いやすいと思いますが、そういう思想のサービスではないので難しいでしょうね。~~

追記：カスタム トークンで既存の認証サーバーと統合できるとのことで、コメント頂きました。@1amageekさん、ありがとうございます。
https://firebase.google.com/docs/auth/admin/create-custom-tokens

#### インフラ

**結論： 最高！**

いうまでも無いですが、インフラを気にしなくてよいのは、とても幸せです。アラートに怯える日々からおさらばできます。スケーラビリティ対応は、なんだかんだで開発コストが馬鹿になりません。

#### APIレス

**結論： 柔軟性に欠けるのはトレードオフ。**

もちろん開発コストゼロですから、最高ですね。ただスキーマと直結のためでデータ加工したいという要望には答えられません。大抵のAPIはスキーマのデータを垂れ流すというより、良い感じに加工しますよね。それが出来ない辛さは必ず生じます。
ただ便利な機能も用意されています。FirestoreのイベントをトリガーにCloud Functionsを使うことができるのと、REST APIをそのまま利用することができます。

参考
[(公式)Cloud Functions を備えた Cloud Firestore の拡張
](https://firebase.google.com/docs/firestore/extend-with-functions?hl=ja)[(公式)Cloud Firestore REST API を使用する](https://firebase.google.com/docs/firestore/use-rest-api?hl=ja)

## 3. クラウドDBとしての評価

**総合評価： ◎　スケーラビリティ最高！**
DBのスケーラビリティを考えなくてよいのは長期運用することを考えると本当に最高です！

### データ解析

**結論： BigQuery連携待ち**

なんらかデータをモバイルアプリから吸い上げてきたら、解析なり加工なりしたくなるでしょう。FirestoreはNode.js、Phython、Goなどのサポートもありますので、もちろんスクリプト組んで色々やることは出来るでしょう。ただCloud Datastore（GCPのNoSQL）もBigQueryと連携されていることを考えると、遅かれ早かれBigQueryと連携されるはずです。そうなれば、とても強力ですね。

### インフラ

**結論： 最高！スケーラビリティは無限！**

データベースも同様にスケーラビリティの課題はつきまとう問題です。それを一切気にしなくて良いので、最高ですね。巨人の肩に乗りましょう！

### トランザクション

**結論: サポートされている**

大量のデータを一度に更新したい場合にも安心です。

### コンソール画面

**結論: 本番運用には耐えなそう**

Firebaseの管理画面にはコンソール画面が用意されています。サンプル程度で見ている分には良いですが、本番運用時にはほぼ使えないだろうと、もっぱらの噂です。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Firestore(多分Realtime Database)、FirebaseのWebコンソールがデータ件数増えたらほぼ使いにもにならない感(　´･‿･｀)開発環境でデータ件数少ない時と割り切り必要なのかな？(　´･‿･｀)あるいは、どこかボタンとか見逃してる？🤔</p>&mdash; 🐶 mono(　´･?･｀)  (@_mono) <a href="https://twitter.com/_mono/status/936523940830199808?ref_src=twsrc%5Etfw">2017年12月1日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# メリット・デメリットまとめ

３層で考えてみた時の、Firestoreを導入する際のメリット・デメリットをまとめてみます。

### メリット

- スケーラビリティ最強。インフラから解放され、アプリケーションに集中できる。
- サーバーサイドのAPI開発コストがゼロ。同期処理の開発は結構手間なので嬉しい。
- トータルコストはサーバーを持たない分、安くなる（たぶん）
- （いずれBigQueryと連携されれば、解析も強力にできるようになる）

### デメリット

- どこまでいってもNoSQL。リレーショナルな参照や更新／削除には弱い。
- ユーザー固有データを扱うには、Firebase Authenticationにロックインする事になる。もちろんメリットも大きいが、相当の覚悟は必要。
- クライアント側の開発コストや難易度は高まる（サーバーが無双になる分、クライアント側に負担を強いるフシがある）

手放しにいいことばかりではなく、トレードオフであることが分かるかと思います。


# 最後に、Firestoreの使いどころはどんなとき？

- NoSQLとして書き込みのみのログ的なものには使いやすい。ユーザー行動履歴とか。
- 最初から小規模なアプリのつもりならぜひ使っていきたい。
- 短期的にモバイルアプリの構築をスピーディーにしたいとき。リーン的に開発の初期段階で使うのはアリ。ただしツラミは絶対出てくるので、もしあなたがベンチャー企業のCTOなら、予め**CEOに「スピード優先するけど、スケールしてきたら改修必要だからね」**と言っておこう。
- 意外とシンプルな参照オンリーの配信にはいいかも。ちょっとしたニュースアプリとか簡単に作れそう。

FirestoreのようなmBaasなサービスはどこまで言っても、柔軟性とのトレードオフですね。そしてインフラが強くなるので大規模なサービスで使いたいところですが、大規模になればなるほど複雑さは増してくるため逆に使いづらくなるあたりが矛盾している部分でもあります。

とはいえ、少ないリソースで開発スピードを高められるのは間違いないです。状況に合わせて選択することも良いと思います。

以上、本記事がFirestore導入検討の助けになれば幸いです。