86
68

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Firebaseの料金を節約するために、ストレージを使ってリアルタイムDBを回避する

Last updated at Posted at 2016-11-24

GoogleのMbaas「Firebase」は、ユーザー認証からリアルタイムDB・ストレージまで、バックエンドで必要なものを一括で提供してくれて、ものすごく便利です。

Firebaseの始め方 - Qiita

ちょっとしたアプリなら無料プランでもそれなりに使えるし、有料プランもストレージなどは十分にお安いライン。
しかし先の記事でも言及されているように、リアルタイムDBの料金がやや気になるところです。

そこで極力リアルタイムDBを使わずにストレージにデータを入れて節約する方法を試しました。

Firebaseの料金プラン

2016年11月時点でこんな感じです。

Pricing - Firebase
Firebase.png

データの保存(stored)・呼び出し(downloaded)とも、リアルタイムDBがちょっと高いですね。。
特にdownloadが$5/GBは、アクセス増えたときに全部DBでさばいてるとけっこうしんどそうです。

ストレージなら同じ1GBのdownloadで$0.12。単純計算でなんと約40分の1に節約できますね。
というわけでさっそくストレージを使った節約プランを考えてみます。

※実際にはファイル化によるデータ量増加があるのと、リアルタイムDBはローカルキャッシュをうまく使ってくれるみたいなので、もうちょい差は詰まると思います。

jsonデータをファイル化してストレージにぶっこむ

そもそもリアルタイムDBは、JSONオブジェクトにすべてのデータを保存する仕組みになっているそうです。
じゃあそのデータをそのままjsonファイルにしてストレージにつっこめばいいのでは?ということでやってみました。

Firebaseの設定が終わってる状態で、実際の処理はこんな感じ。

var json = { hoge: 1, fuga: 2, piyo: 3 };

//JSONをBlobオブジェクトにする
var blob = new Blob([JSON.stringify(json)], { type: 'application\/json' });

//storageにアップロード
var uploadTask = firebase.storage().ref('json/hogehoge.json').put(blob);

//アップロードタスクのobserve
uploadTask.on('state_changed', function(snapshot){
	// Observe state change events such as progress, pause, and resume
	// See below for more detail
}, function(error) {
	// Handle unsuccessful uploads
}, function() {
	// Handle successful uploads on complete
	// For instance, get the download URL: https://firebasestorage.googleapis.com/...
});

Blobオブジェクトに変換

ファイルとしてアップロードするために、JSONデータをBlobオブジェクトに変換してます。
BlobじゃなくてFileでもよいはず。
(ただしどちらもHTML5の機能なので、ブラウザの対応バージョンはご注意ください)

JavaScriptプログラミング講座【Blob と File クラスについて】

CloudStorageにアップロード

ストレージへのアップロード処理は公式のドキュメントを参照。

ウェブでファイルをアップロードする | Firebase

アップロードのステータスを見たいときはstate_changedをトリガーにごにょごにょしてください。
アップロード自体はその前にput(blob)した段階で実行されています。

CloudStorageのセキュリティ設定

デフォルトの設定のままで上記を実行すると権限ないよって怒られるかもしれません。
これはストレージにデフォルトでセキュリティルールが適用されているせいです。

Storage セキュリティ ルールを使ってみる | Firebase

公式ドキュメントを参考に、適切に設定してやってください。
とりあえず動作確認したい場合は、サンプルルールの「公開」となっているのでやればアップロードできるはず。

ストレージに保存したJSONデータを読み込む

保存したデータを読み込むときはこんな感じ。

var storageRef = firebase.storage().ref('json/hoge.json');

storageRef.getDownloadURL().then(function(url) {
  $.getJSON(url, function(data) {
    console.log(data);
  });
}).catch(function(error) {
  // Handle any errors
});

該当jsonファイルのダウンロードURLが返ってくるので、これをgetJSONで読み込むということをしています。

権限管理をするためにダウンロードURLを都度返してるのだと思うので、
誰でも見れてよいデータなら、最初から公開設定でファイルをアップしておいたほうが楽ちんです。

その場合読み込み時はfirebaseのAPIを使わず、直接jsonファイルの公開URLを指定してgetJSONだけしてやればOK。

CORS問題

上記の処理もそのまま実行するとおそらくこんなエラーになるはず。

No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://xxxx' is therefore not allowed access.

FirebaseのストレージはそのままGoogleCloudStorageなので、そこでCORS設定をしてやる必要があります。

Firebase StorageにCORSの設定をする | Qiita

デメリット・注意点など

  • リアルタイムDBはうまいことローカルにキャッシュしてくれたりするみたいなので、実際にはそれほど通信量は発生しないかも
  • チャットみたいなアプリ作りたいなら、リアルタイムDBじゃないときびしそう
  • ファイルの読み書きが発生する分、ストレージ使うほうが遅くなりそう

同時更新・リアルタイム性などを考えると、やはりリアルタイムDBの恩恵が大きそうです(あたりまえか)。

またリアルタイムDBではデータを正規化せず、一覧表示用などにデータを重複保存することが推奨されてるようです。

データベースの構造化 | Firebase

これもストレージで再現することもできるけど、個人的にはちょっとやりすぎな気も。

検索用などのインデックスっぽい使い方をする部分はリアルタイムDBに残し、メインのデータ部分をストレージに置くような使い方がいいかなーと思っています。あんまり根拠ないけど。

まとめ

Firebase便利。

86
68
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
86
68

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?