今回は実務で本当に使う構成を、設計視点まで含めて深掘りします。
扱う範囲:
- Authentication
- Firestore
- Cloud Functions
- Storage
- FCM(Push通知)
全体アーキテクチャ
React Native(フロント)
↓
Firebase Authentication(認証)
↓
Firestore(DB)
↓
Cloud Functions(安全なサーバーロジック)
↓
Storage(画像保存)
↓
FCM(通知)
これで「バックエンド無し構成」が完成します。
1. Authentication(認証)
なぜ最重要か?
Firebaseは認証を軸にすべての権限管理が決まります。
- Firestoreのルール
- Storageのルール
- Functionsの保護
全部 request.auth.uid ベース。
実務でよく使うログイン方式
- メール / パスワード
- Googleログイン
- Appleログイン(iOS必須)
- 匿名ログイン → 後で昇格
インストール
npm install @react-native-firebase/auth
ログイン例
import auth from '@react-native-firebase/auth';
await auth().signInWithEmailAndPassword(email, password);
認証状態監視(超重要)
useEffect(() => {
const unsubscribe = auth().onAuthStateChanged(user => {
if (user) {
console.log("ログイン中:", user.uid);
}
});
return unsubscribe;
}, []);
この監視がアプリの起点になります。
2. Firestore(NoSQLデータベース)
特徴
- リアルタイム同期
- ドキュメント型
- スケーラブル
基本構造
users (collection)
└ userId (document)
└ name
└ createdAt
posts
└ postId
└ title
└ userId
└ imageUrl
書き込み
await firestore().collection('posts').add({
title: 'テスト投稿',
userId: auth().currentUser?.uid,
createdAt: firestore.FieldValue.serverTimestamp(),
});
リアルタイム購読
firestore()
.collection('posts')
.onSnapshot(snapshot => {
const posts = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data(),
}));
});
⚠️ 実務で最重要:読み取り課金
Firestoreは
- ドキュメント読み取り回数課金
onSnapshotを乱用すると地獄になります。
設計ポイント
- 必要なフィールドだけ取得
- pagination必須
- where + index設計
- 不要なリアルタイムを避ける
3. Cloud Functions
役割
React Nativeから直接やらせてはいけない処理を担当。
- 検証
- 課金処理
- FCM送信
- 集計
- 外部API連携
初期化
npm install -g firebase-tools
firebase init functions
Firestoreトリガー
export const onPostCreated = functions.firestore
.document("posts/{postId}")
.onCreate(async (snapshot) => {
const data = snapshot.data();
console.log("New Post:", data.title);
});
無限ループ注意
Firestore更新 → Functions → Firestore更新
これで再トリガーされます。
対策:
- フラグフィールドを持つ
- 別コレクションに書く
HTTPS APIとして使用
export const createPayment = functions.https.onCall(async (data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError('unauthenticated', '認証必要');
}
return { success: true };
});
onCall を使うと認証付きAPIになります。
4. Firebase Storage
画像・動画保存。
実務ベストプラクティス
ファイルパス設計
users/{uid}/posts/{postId}.jpg
ユーザーごとに分離。
アップロード
const reference = storage().ref(`users/${uid}/${Date.now()}.jpg`);
await reference.putFile(uri);
ルール例
match /users/{userId}/{allPaths=**} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
認証必須+自分のフォルダのみ。
実務でやること
- サムネイル生成(Functions)
- 画像圧縮
- 未使用ファイル削除設計
5. FCM(Push通知)
なぜ重要か?
継続率は通知で決まる。
トークン取得
const token = await messaging().getToken();
これをFirestoreのusersに保存。
トークン更新監視
messaging().onTokenRefresh(token => {
// Firestore更新
});
これやらないと通知届かなくなります。
6. Cloud Functions × FCM 連携(実務最頻出)
投稿作成 → 全員に通知。
await admin.messaging().sendMulticast({
tokens,
notification: {
title: "新しい投稿",
body: "投稿が追加されました"
}
});
流れ:
Firestore更新
↓
Functionsトリガー
↓
FCM送信
7. 本番設計の重要ポイント
🔥 課金対策
- Firestore読み取り最適化
- Functions実行時間短縮
- Storage圧縮
🔥 セキュリティ
- ルールは必ず本番前にテスト
- 管理者ロール設計
- Functions内で再検証
🔥 スケーラビリティ
- 大量通知はトピック配信
- バッチ処理
- BigQuery連携
8. よくある実務事故
- Functions無限ループ
- FCMトークン未更新
- Firestore index未設定エラー
- Storage全公開
- リアルタイム監視乱用で課金爆発
9. この構成の強み
- バックエンド不要
- MVP爆速開発
- リアルタイム機能が簡単
- インフラ管理不要
10. でも限界もある
- 複雑なJOINは苦手
- 大規模分析は不向き
- 設計を間違えると高額課金
結論
React Native × Firebaseは
- 小〜中規模アプリに最強
- スタートアップに最適
- MVP開発に最適
ただし
設計を知らずに使うと破綻します。