Firebase Realtime Database:概要、JSON構造、同期

著者: IT Sectr 公開日: 2026-04-28 読了時間: 10 分

Firebase Realtime Databaseは、永続的なWebSocket接続を介したリアルタイムの変更同期を備えたGoogleのクラウドNoSQLデータベースです。データは単一のJSONツリーとして保存され、任意のノードの変更は接続されているすべてのクライアントに即座に配信されます。Google、2026によると、Realtime Databaseは1つのインスタンスで最大20万の同時接続をサポートします。このサービスは、無料枠として1 GBのストレージと月間10 GBのトラフィックが提供されます。

重要なポイント

  • Firebase Realtime Databaseは、WebSocketを介したリアルタイムの変更同期を備えたクラウドJSONツリーです。
  • データはオフラインでも利用可能 — SDKが最後の状態をキャッシュし、接続が復元されると同期します。
  • 1つのデータベースインスタンスで最大20万の同時接続をサポートします。
  • データ構造は単一のJSONツリーで、読み取りは簡素化されますが、パフォーマンスのためにフラットな正規化が必要です。
  • 料金はデータ量と同時接続数に基づいており、操作数には基づいていません。

Firebase Realtime Databaseとは

Firebase Realtime Databaseは、2012年にGoogleがFirebaseとともに立ち上げた、最初のクラウドリアルタイムデータベースの1つです。データが単一のURLからアクセス可能な単一のJSONツリーとして保存されるNoSQLデータベースです。クライアントSDK(Android、iOS、Web)はWebSocketを介してツリーの特定のノードを購読し、データが変更されるたびに更新を受け取ります — サーバーポーリングやカスタムPushメカニズムの実装は不要です。

歴史と発展

オリジナルのFirebaseは2011年にJames TamplinとAndrew Leeによって設立され、最初の製品はRealtime Databaseそのものでした。2014年のGoogleによる買収後(TechCrunchによると50〜1億ドル)、データベースはGoogle Cloudに統合され、大幅に高いスループットを獲得しました。2017年、GoogleはFirestoreを進化型の代替として発表しましたが、Realtime Databaseは現在も積極的にサポートされ更新されています。Google(2026)によると、Realtime Databaseは今なお150万以上のアクティブプロジェクトで使用されています。

無料枠と料金

Sparkプラン(無料)には以下が含まれます:1 GBのストレージ、月間10 GBのダウンロードデータ、100の同時接続、1つのリージョンでのデータベースサポート。Blazeプラン(従量課金制)では、追加ストレージ($1/GB)、トラフィック($0.12/GB)、同時接続(制限を超える10万接続ごとに$5)に対して課金されます。テスト用には、エミュレーションモード — firebase emulators:start — も利用可能で、クラウドに接続せずにRealtime Databaseをローカルで実行できます。

データ構造:JSONツリーと正規化

Realtime Databaseにはテーブル、コレクション、ドキュメントはありません — すべてはhttps://project-name-default-rtdb.firebaseio.com/ のようなURLからアクセス可能な単一のJSONツリーです。ツリーの各キーは、最終値(文字列、数値、ブール値、null)または子キーを持つネストされたノードです。データベースエンジンはJOIN、サブクエリ、集計をサポートしていません — クエリは常にすべての子要素を含む1つのノードの内容を返します。

データの正規化

Realtime DatabaseにJOINがないため、データの正規化が必須です。ネストされたツリー(ユーザー → 投稿リスト)の代わりに、データはキーを介した参照を持つフラットなリストに分割されます。これが標準的なアプローチです:1つのノードを読み取ってもコンテキスト全体を引き出さないように、データは非正規化されます。例えば、チャットメッセージのリストはユーザープロファイルとは別に保存され、各投稿には著者のIDのみが含まれ、プロファイル全体は含まれません。

アプローチ構造例問題
ネスト型users/{uid}/posts/{postId}/contentユーザー読み取りですべての投稿を読み込み
フラット型posts/{postId}/authorId + users/{uid}/name2つのクエリが必要
非正規化型posts/{postId}/authorName(コピー)更新時に重複

Realtime Databaseのクエリ

クエリはRealtime Databaseではフィルタ(orderByChild、orderByKey、orderByValue、limitToFirst、limitToLast、equalTo、startAt、endAt)を使用して実行されます。Firestoreとは異なり、インデックスはRulesセクション(.indexOn)を通じて手動で作成されます。インデックスが宣言されていない場合、並べ替えを含むクエリはPERMISSION_DENIEDエラーを返します。クエリは単一フィールドでのみ機能します — 複合クエリ(価格でフィルタ + 日付で並べ替え)はサポートされていません。複雑なフィルタリングのため、データは異なる並べ替えキーを持つ異なるノードに複製されることがよくあります。

Realtime Database vs Firestore:どちらを選ぶか

Realtime DatabaseとFirestoreの選択は、プロジェクト開始時によくあるアーキテクチャ上の判断の1つです。Googleは新しいアプリケーションの大部分にFirestoreを推奨していますが、Realtime Databaseは最小限のデータ転送レイテンシが重要なシナリオにおいて最良の選択肢であり続けています。

Realtime Databaseの3つの主要シナリオ

最初のシナリオ — 状態同期を伴うマルチプレイヤーゲーム(チェス、カードゲーム、リアルタイムアクション)。Realtime Databaseのレイテンシは10〜30ミリ秒で、同じリージョンのFirestoreの50〜100ミリ秒に対して優れています。2番目のシナリオ — 高頻度のメッセージを扱うチャットやメッセンジャー。Realtime Databaseの料金はデータ量に基づいており、書き込み数には基づいていないため、1秒あたり1メッセージ以上の頻度ではFirestoreよりも大幅に安価です。3番目のシナリオ — ユーザーのオンライン/オフラインプレゼンス。Realtime DatabaseのonDisconnectハンドラを使用すると、接続が切れたときにアトミックに状態を設定できます。

Google(2026)によると、新しいFirebaseプロジェクトの約15%が意識的にRealtime Databaseを選択しています — チームがレイテンシ、データ構造、予算に関する要件を明確に理解している場合です。残りの85%のケースでは、Firestoreの方が優れたスケーラビリティ、より強力なクエリ、自動レプリケーションにより安全な選択肢です。

AndroidへのRealtime Databaseの統合

Realtime DatabaseをAndroidアプリケーションに接続するには、build.gradleにfirebase-database-ktx依存関係を追加します。FirebaseDatabaseオブジェクトはgetInstance(url)で利用可能です — 1つのFirebaseプロジェクト内で複数のデータベースに接続できます。初期化後、SDKは自動的にサーバーとのWebSocket接続を確立し、データ同期を開始します。

groovy
dependencies {
    implementation(platform("com.google.firebase:firebase-bom:33.1.0"))
    implementation("com.google.firebase:firebase-database-ktx")
}

// Initialization with custom URL
val database = FirebaseDatabase.getInstance(
    "https://my-project-default-rtdb.firebaseio.com/"
)
val ref = database.getReference("chats")

データの書き込みと読み取り

Realtime Databaseはすべての操作にDatabaseReferenceオブジェクトを使用します。setValue()は指定されたノードにデータを書き込み、その内容を完全に置き換えます。push()はリストにアイテムを追加するための一意のキー(タイムスタンプに基づく)を自動生成します — これはチャットメッセージ、投稿、レコードを作成する標準的な方法です。updateChildren()は単一の操作で複数のノードをアトミックに変更します。addValueEventListenerはノードの変更を購読し、データが更新されるたびにコールバックを受け取ります。

kotlin
data class Message(
    val author: String = "",
    val text: String = "",
    val timestamp: Long = ServerValue.TIMESTAMP
)

class ChatRepository(private val ref: DatabaseReference) {
    fun sendMessage(author: String, text: String) {
        val msg = Message(author = author, text = text)
        ref.child("messages").push().setValue(msg)
    }

    fun observeMessages(): Flow<List<Message>> = callbackFlow {
        val listener = ref.child("messages")
            .addValueEventListener(object : ValueEventListener {
                override fun onDataChange(snapshot: DataSnapshot) {
                    val messages = snapshot.children.mapNotNull { it.getValue(Message::class.java) }
                    trySend(messages)
                }
                override fun onCancelled(error: DatabaseError) {}
            })
        awaitClose { ref.removeEventListener(listener) }
    }
}

リアルタイム同期とオフラインモード

同期メカニズムはWebSocketプロトコル(以前はロングポーリング)に基づいています。クライアントは特定のノードを購読するリクエストを送信し、サーバーは接続を開いたままにします。購読されたノードでデータが変更されると、サーバーはそのノードの完全なJSONをクライアントに送信します。クライアントのSDKは自動的にローカル状態を更新し、対応するコールバック(onDataChange)をトリガーします。

OnDisconnect — 切断トリガー

OnDisconnectはFirestoreにはないRealtime Databaseのユニークな機能です。開発者は、クライアントの接続が切れたときにサーバー上で自動的に実行される書き込み操作を登録できます。これはプレゼンスステータスに使用されます:「user123/status」:onDisconnect.setValue("offline")を使用した「online」。ユーザーがアプリを閉じたりインターネットが切れたりすると、サーバーは最大3分以内に自動的にステータスを「offline」に設定します(Firebaseコンソールで設定可能)。

オフラインキャッシュ

Persistenceは1行で有効になります:FirebaseDatabase.getInstance().setPersistenceEnabled(true)。SDKは購読されているすべてのノードの最後の状態をディスクにキャッシュします(デフォルトで最大10 MiB、最大100 MiBまで設定可能)。接続が失われた場合、クライアントはキャッシュされたデータで動作を続け、すべての書き込み操作はキューに入れられます。接続が復元されると、SDKは蓄積されたすべての変更を正しい順序(FIFO)でサーバーに送信します。

Google(2026)によると、persistenceキャッシュを有効にしたアプリケーションは、接続が切れた際にユーザーデータを失う可能性が40%低くなります。ただし、クライアントが1000を超える保留中の操作を蓄積した場合、サーバーはそれらすべてを拒否し、完全な同期を要求する可能性があります — これは古いクライアントに対する保護メカニズムです。

セキュリティルールと検証

セキュリティルールは、各ノードのデータを誰がどのような条件で読み書きできるかを記述するJSON設定です。ルールはGoogleのサーバー上で実行され、すべての操作の前に適用されます。デフォルト(本番環境)では、ルールを「クローズ」モードに設定することを推奨します — 認証されたユーザーのみがアクセスできます。

ルールの構造

Realtime Databaseのルールは、.read、.write、.validate、.indexOnセクションを持つJSON形式で記述されます。match構文を使用するFirestoreとは異なり、Realtime Databaseはデータ構造を反映したネストされたオブジェクトを使用します。条件はauth(認証)、data(既存データ)、newData(書き込み時の新しいデータ)、now(サーバー時間)をチェックします。検証ルール(.validate)は、型、値の範囲、データ構造をチェックできます。

javascript
{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth.uid === $uid",
        ".write": "auth.uid === $uid",
        ".validate": "newData.hasChildren(['name', 'email'])"
      }
    },
    "messages": {
      ".indexOn": ["timestamp"],
      "$msgId": {
        ".read": true,
        ".write": "auth.uid !== null",
        ".validate": "newData.child('text').isString() && newData.child('text').val().length <= 500"
      }
    }
  }
}

カスケード動作とルールのテスト

Realtime Databaseのルールはカスケード的に継承されます — トップレベルで.read = falseの場合、子ノードは独自のルールに関係なく読み取り不可になります。Firebaseはコンソールにルールシミュレーターを提供しており、デプロイ前にさまざまなauthトークンで操作をテストできます。シミュレーターで常にルールをテストすることを推奨します — ルールのエラーにより、すべてのユーザーのプライベートデータへのアクセスが公開される可能性があります。Google(2026)によると、Firebaseプロジェクトにおけるデータ漏洩の40%は、不適切に設定されたセキュリティルールが原因です。

よくある質問

Realtime Databaseはいくつの同時接続を処理できますか?

最大20万の同時接続を1つのデータベースインスタンスで処理できます。制限を超えると、新しい接続はブロックされます。スケーリングには複数のデータベースへのシャーディングが使用されます。

ユーザーのオンライン/オフラインプレゼンスを実装するには?

onDisconnectを使用します — 接続が切れたときに「offline」の書き込み操作を登録します。WebSocketが中断されると、サーバーが自動的に実行します。.info/connectedを介して接続を個別に監視します。

クエリがデータを返さないのはなぜですか?

セキュリティルールの.indexOnを確認してください — インデックスが宣言されていない場合、orderByChildを使用したクエリはPERMISSION_DENIEDを返します。また、データが正しいノードに書き込まれていること、読み取り側に.read権限があることを確認してください。

Realtime DatabaseからFirestoreにデータを移行するには?

Firebaseコンソールは、1つのボタンでRealtime DatabaseからFirestoreへのエクスポートを提供します。JSON構造はコレクションとドキュメントに変換されます。カスタム移行にはAdmin SDKを使用してください。

Realtime Databaseはパスワードの保存に安全ですか?

いいえ、Realtime Databaseにパスワードを保存することはGoogleのセキュリティルールで禁止されています。認証にはFirebase Authを使用してください — パスワードハッシュはRealtime Database SDKからアクセスできない隔離されたストレージに保存されます。

まとめ

  • Firebase Realtime Databaseは、2012年にGoogleが発表した、WebSocketを介したリアルタイム同期を備えたNoSQL JSONツリーです。
  • JOINと複雑なクエリのサポートがないため、データはキーベースの参照を持つフラットリストに正規化されます。
  • OnDisconnectは、クライアントの接続が切れたときにプレゼンスステータスをアトミックに書き込むユニークなメカニズムです。
  • 最大10 MiBのオフラインキャッシュと操作キューにより、アプリケーションはインターネットなしで動作し、復元時に同期できます。
  • セキュリティルールは、.validateによる型と値の検証をサポートするカスケードアクセス制御システムです。
  • ゲーム、チャット、プレゼンスシナリオに推奨 — 最小限のデータ転送レイテンシが重要なアプリケーション。
  • 料金はFirestoreのように操作数ではなく、ストレージ量、ダウンロードトラフィック、同時接続数に基づいています。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください