バックエンド接続エラーはなぜ起こるのか
Rorkで生成したアプリがFirebaseやSupabaseなどのバックエンドと接続できない場合、その原因は大きく分けて3つです:
- 認証情報の設定ミス — API キーや設定ファイルの不備
- ネットワーク・セキュリティ設定 — CORS、ファイアウォール、プライベートネットワーク
- ランタイムのバグ — 非同期処理の待機不足、state 更新タイミング
このガイドでは、各パターンの症状と解決方法を詳しく解説します。もしビルド段階でエラーが発生している場合は、Rorkアプリのビルドエラー完全解決ガイドも参考にしてください。
エラー1:Firebase Configuration Error
症状
Error: Firebase initialization failed
Error: firebaseConfig is undefined
アプリ起動時に Firebase が初期化できず、ブラウザコンソール(または Xcode)にエラーが表示されます。
原因
google-services.json(Android)またはGoogleService-Info.plist(iOS)をプロジェクトに追加していない- Firebase config が Rork のコード内に正しくインポートされていない
- API key が誤入力または無効
解決方法
ステップ1:Firebase Console から設定ファイルをダウンロード
- Firebase Console にログイン
- プロジェクトを選択
- 「Project Settings」(歯車アイコン)をクリック
- 「Your apps」セクションで、アプリを選択
- iOS / Android それぞれの設定ファイルをダウンロード
iOS の場合:GoogleService-Info.plist
Android の場合:google-services.json
ステップ2:Rork プロジェクトに追加
iOS の場合、Xcode で「File」→「Add Files to Project」で plist を追加。
Android の場合、android/app/google-services.json に配置。
ステップ3:Firebase 初期化コードを確認
Rork が生成したコードで以下のパターンを確認:
// src/config/firebase.js (例)
import { initializeApp } from 'firebase/app';
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT.appspot.com",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID",
};
const app = initializeApp(firebaseConfig);
export default app;YOUR_API_KEY など全て実際の値に置き換わっているか確認します。
エラー2:Supabase 接続エラー
症状
Error: Failed to connect to database
Error: SUPABASE_URL or SUPABASE_KEY is undefined
Supabase へのリクエストが失敗し、ネットワークタブに「CORS error」または「401 Unauthorized」が表示されます。
原因
- Supabase の Project URL または Anon Key が誤設定
- CORS 設定が未構成
- API キーに正しい権限がない
解決方法
ステップ1:Supabase からクレデンシャルを取得
- Supabase Dashboard にログイン
- プロジェクトを選択
- 「Settings」→「API」から以下を確認:
- Project URL:
https://xxxxx.supabase.co - Anon Key(公開可能):
eyJhbGc...で始まる長い文字列 - Service Role Key(秘密):絶対に公開しない
- Project URL:
ステップ2:環境変数に設定
React Native / Expo プロジェクトの場合、.env ファイルに:
EXPO_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=eyJhbGc...
EXPO_PUBLIC_ プレフィックスが重要です(クライアントから見える変数)。
ステップ3:Supabase クライアントを初期化
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = process.env.EXPO_PUBLIC_SUPABASE_URL;
const supabaseAnonKey = process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY;
export const supabase = createClient(supabaseUrl, supabaseAnonKey);エラー3:CORS(Cross-Origin)エラー
症状
Access to XMLHttpRequest has been blocked by CORS policy
Origin 'http://localhost:3000' is not allowed
ブラウザのコンソールに CORS エラーが表示されます。
原因
- バックエンドが、ローカル開発環境(
localhost:3000など)からのリクエストを拒否している - CORS ヘッダーが正しく設定されていない
解決方法
Firebase の場合:CORS 設定不要
Firebase は クライアントサイドライブラリなので CORS エラーは出ません。上記エラーが出た場合は、Firebase 以外のカスタムバックエンド呼び出しで CORS 設定が必要な可能性があります。
Supabase の場合:自動で CORS 対応
Supabase の REST API・Realtime API は CORS が自動で有効です。ただし、カスタム RPC 関数を呼び出す場合は、以下を確認:
カスタムバックエンド(Express 等)の場合:
const cors = require('cors');
app.use(cors({
origin: [
'http://localhost:3000',
'http://localhost:19000', // Expo
'https://yourdomain.com' // 本番
],
credentials: true
}));エラー4:認証トークン無効エラー
症状
Error: Invalid or missing authentication token
Error: 401 Unauthorized
ログイン直後はいいが、時間が経つとトークンが期限切れになります。
原因
- Firebase / Supabase のセッションが自動更新されていない
- トークン更新ロジックが実装されていない
- ローカルストレージ/Secure Store にトークンが保存されていない
解決方法
Firebase の場合:自動リフレッシュ
Firebase SDK は自動的にトークンをリフレッシュします。以下で確認:
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from './firebase.config';
// セッション確認フック
export function useFirebaseAuth() {
const [user, setUser] = useState(null);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
// トークンは自動更新される
});
return unsubscribe;
}, []);
return user;
}Supabase の場合:リフレッシュトークン管理
import AsyncStorage from '@react-native-async-storage/async-storage';
// 起動時にセッション復元
export async function restoreSession() {
const { data, error } = await supabase.auth.refreshSession();
if (error) console.error('Session refresh failed:', error);
return data;
}
// アプリ初期化時に実行
useEffect(() => {
restoreSession();
}, []);エラー5:ネットワークセキュリティエラー
症状
Error: Network request failed
ERR_SSL_PROTOCOL_ERROR
HTTP ベースのバックエンドに接続できません。
原因(iOS)
iOS 9+ では、デフォルトで HTTPS 必須です。HTTP サイトへのアクセスはセキュリティ例外を追加する必要があります。
解決方法(iOS)
Info.plist に以下を追加:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>本番環境では HTTPS サーバーを使用してください。HTTP は開発環境のみです。
原因(Android)
AndroidManifest.xml で android:usesCleartextTraffic の設定が必要な場合があります。
<application
android:usesCleartextTraffic="true"
...>
</application>本番環境では必ず HTTPS にしてください。
エラー6:データ永続化・オフライン同期エラー
症状
- アプリがオフラインになると、データが表示されない
- データベースに保存されたはずのデータが消える
- ネットワーク復帰後に同期されない
原因
- ローカルキャッシュが実装されていない
- SwiftData(iOS)または Realm(React Native)の設定が不完全
- オフライン時の状態管理が不十分
解決方法
Firebase + iOS の場合:Firestore Persistence 有効化
import FirebaseFirestore
let db = Firestore.firestore()
db.settings.isPersistenceEnabled = true
// これでオフラインデータが自動保存されるSupabase + React Native の場合:ローカルキャッシュを実装
import AsyncStorage from '@react-native-async-storage/async-storage';
export async function fetchAndCacheData(table) {
try {
// ネットワークから取得を試みる
const { data, error } = await supabase
.from(table)
.select();
if (!error) {
// 成功時、ローカルに保存
await AsyncStorage.setItem(
`cache_${table}`,
JSON.stringify(data)
);
return data;
}
} catch (e) {
console.error('Network fetch failed, loading from cache');
}
// キャッシュからロード
const cached = await AsyncStorage.getItem(`cache_${table}`);
return cached ? JSON.parse(cached) : null;
}全体を振り返って
データベース接続エラーの 90% は、設定ミス・認証情報の不備・CORS 設定の不完全さで解決します。重要なのは、エラーメッセージを丁寧に読むこと、環境変数を確認することです。
本当に難しいのは、オフライン同期やリアルタイム同期の実装です。Rork で生成したアプリなら、基本構造は既に用意されているので、あとは微調整するだけです。
バックエンド接続が完了したら、RorkアプリのTestFlight配信からApp Store公開までのトラブル対処法に進むことをお勧めします。
より詳しいバックエンド設計について学びたい場合は、以下の書籍を参考にしてください:
Rork で生成したアプリはプロダクションレディですので、これらのエラーもシステマティックに解決できます。頑張りましょう!