このすみノート

Webエンジニアが技術や趣味を書くブログです。

Firebase Realtime DBの実戦投入を振り返る - 採用方針やセキュリティで気をつけたことなど

Crieit Advent Calendar 2018」の記事です。2018年は、業務で「Firebase Realtime Database」を使った1年でした。

firebase.google.com

Realtime Databaseは、数ミリ秒で各クライアントへデータを同期します。はじめて使ったときは、とても感動しました。開発したシステムでは、リアルタイムのデータ表示が必要な、特定機能に限定してRealtime Databaseを投入しています。

色々と工夫した点がありますので、今回はその辺りの知見を共有します。

RDB(Relational Database)との併用

「Firebase Realtime Database」は、データベースとして単体で使うわけではなく、PostgreSQLと併用して運用しています。

それには、いくつかの理由があります。

  1. はじめて使うので、ミニマムにプロジェクトで採用し、様子を見ることにした
  2. データ容量や転送量に連動する従量課金のため、最低限のリアルタイム表示に必要なデータだけ置くことにした
  3. Realtime Databaseは、柔軟なクエリ発行が苦手です。管理画面をはじめとする、細かな検索条件が発生するシーンには不向きでした

棲み分けとしては、リアルタイム表示が必要なデータをRealtime Databaseに投入し、それ以外はRDB(PostgreSQL)に保存しています。

また、Firebase Console上の誤操作で、データを上書きしたり消失できてしまう可能性があります。そこで、復旧スクリプトも用意しました。

具体的には、PostgreSQLにあるマスターデータを元にして、API経由でデータを再セットするスクリプトです。ただ、一度も出番はなかったです。

セキュアなデータはRDB(PostgreSQL)に置く

また、PostgreSQLを併用しているもうひとつの理由に、セキュアなデータを置きたくなかった点があります。

後述するセキュリティルールを工夫すれば対策も可能ですが、保険をかけて、セキュアなデータはサーバーサイドのRDBに暗号化して保存してします。

セキュリティルールの調整で、書き込みを拒否する

セキュリティルールは、基本的に以下の設定で運用しています。私の場合、書き込みは許可せず運用することにしました。

また、リアルタイムのデータ表示に必要な特定のテーブルに絞って、読み込みを開放しています。

{
  "rules": {
    ".read": false,
    ".write": false,

    "sampletable": {
      ".read": "auth != null",
      ".write": false
    }
  }
}

書き込みを拒否した理由は、主に以下の3点です。

  1. PostgreSQLのマスターデータにも反映したかったので、書き込みはサーバーサイドで処理したかった
  2. フロントエンドJSから直接データを書き込ませないことで、安全性を高めたかった
  3. 認証は自前でやっており、Firebase Authenticationで認証していない。そのため、細かな書き込み権限の制御が難しかった

なお、書き込みを許可しなかったとしても、Admin用のライブラリを使えば書き込みは可能です。PHPには公式のAdmin SDKがなかったので、OSSを利用しました。

github.com

読み込み側の権限は「auth != null」にしています。念のため、Firebase Authenticationの匿名認証を挟んで運用している形です。

f:id:konosumi:20181216200759p:plain

GCP(Google Cloud Platform)と連動している点に注意

Firebaseのプロジェクトを開設すると、GCP(Google Cloud Platform)のConsoleでもアクセスできるようになります。この点はかなり重要です。

私が技術書典4で頒布した「Realtime Database x React本」でも、注意事項を書いてます。抜粋して掲載します。

「APIとサービス」の認証情報を確認すると、Firebaseが自動で作成したキーがあることが分かります。そして、APIキーにおける警告マークは、APIキーが無制限であることを示しています。実運用で使用される場合は、設定は必須であると言えます。開発段階でも、可能な限り制限を設定することが望ましいでしょう。

WEBサービスであればリファラで、モバイルアプリであればバンドルIDなどでAPIキーを制限するのが基本形です。これを設定しておかないと、Firebase用のアクセスAPIキーが無制限状態で運用されてしまいます。

少し内容が古くなってしまいましたが、技術書典4で頒布した本にもFirebaseの概要を書いてます。無料でダウンロードできます。

konosumi.booth.pm

Realtime Databaseの実装は、メルカリを参考にするのがオススメ!

私がプロジェクトで採用した構成は、「PHPカンファレンス2017のメルカリチャンネル」をベースにしています。

tech.mercari.com

会場でメルカリの@sota1235さんに質問して、「半年ほど運用しているが、一度もダウンしたことはない」という返答をもらったのが、採用の決め手になりました。

メルカリチャンネルにおけるRealtime Databaseの知見は、他の記事でも共有されています。ぜひ参考にしましょう!

tech.mercari.com

Cloud Firestoreとの関係性

Realtime Databaseの対抗馬として、Cloud Firestoreがあります。

firebase.google.com

個人的には、以下のような印象を持っています。

  1. Cloud Firestoreは、まだベータ版である
  2. クエリの柔軟性は、Cloud Firestoreのほうが高い

Cloud Firestoreの特徴である「クエリ処理の機能性、効率性、柔軟性」は、とても魅力的です。

さいごに

リアルタイムのデータ表示が必要な、特定機能に限定してRealtime Databaseを投入しました。感触はとても良いです。

また、オフライン対応があるのも魅力的です。もしデータ同期に失敗しても、クライアントがオンラインになったら、自動的に同期を再開します。これを自前のWebSocketで実装するとしたら、相応の苦労が必要なことは間違いありません。

巨人の肩の上にのることのメリットを、改めて実感した1年でした。