
Supabaseで認証・DB・ストレージを一括管理する方法
この記事のポイント
- ✓Supabaseを使って認証
- ✓ストレージを一つのプラットフォームで管理する方法を解説
- ✓Firebaseとの比較や
Supabaseで認証・DB・ストレージを一括管理する方法
「認証はAuth0、データベースはPlanetScale、ストレージはAWS S3」
数年前まで、Webアプリケーションのバックエンドを構築するには、こうした複数のサービスを組み合わせるのが一般的でした。
ところが、これは1人開発者にとって大きな負担です。
各サービスのアカウント管理、APIキーの管理、ドキュメントの確認、料金体系の把握。
サービスが増えるほど、管理コストが指数関数的に増大します。
私がSupabaseを導入したのは、この管理コストを劇的に削減するためでした。
認証、データベース、ストレージ、リアルタイム通信。
すべてを1つのダッシュボードで管理できるという圧倒的な利便性が決め手でした。
この記事では、Supabaseの各機能を実際にどう使っているかを、コード例付きで解説します。
なぜFirebaseではなくSupabaseなのか
BaaS(Backend as a Service)といえば、多くの方が最初に思い浮かべるのはFirebaseでしょう。
Googleが提供する実績あるサービスです。
私も以前はFirebaseを使っていました。
ところが、Firebaseにはいくつかの構造的な問題がありました。
1. データベースがNoSQL(Firestore)
Firestoreはドキュメント指向のNoSQLデータベースです。
シンプルなデータ構造には向いていますが、リレーショナルなデータを扱うには苦労します。
@SOHOのようなプラットフォームでは、ユーザー、案件、応募、メッセージなど、テーブル間の関連が複雑です。
JOINが使えないNoSQLでは、データの取得に何回もクエリを発行する必要があり、パフォーマンスとコードの複雑さの両方が悪化しました。
2. ベンダーロックイン
FirestoreのクエリはFirebase独自の構文です。
将来、別のサービスに移行したくなった時、すべてのクエリを書き直す必要があります。
SupabaseのデータベースはPostgreSQLです。
標準的なSQLが使えるため、ベンダーロックインのリスクが低い。
3. 料金の予測困難さ
Firestoreは読み取り・書き込み回数で課金されます。
ユーザー数が増えると、予想外に高額になることがあります。
ある月に突然請求額が3倍になった経験があり、それ以来Firestoreを使うのが怖くなりました。
Supabaseの料金体系はシンプルで、Proプランは月額$25。
データベースのストレージ8GB、認証ユーザー無制限、ストレージ100GBが含まれています。
読み取り回数で課金されないため、料金の予測がしやすいのです。
Supabase認証(Auth)
セットアップ
Supabaseの認証機能は、箱を開けてすぐ使えるレベルの完成度です。
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);たった3行で、認証機能付きのクライアントが完成します。
メール認証
// サインアップ
const { data, error } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'securepassword123',
});
// ログイン
const { data, error } = await supabase.auth.signInWithPassword({
email: 'user@example.com',
password: 'securepassword123',
});
// ログアウト
await supabase.auth.signOut();メール認証のフローは以下の通りです。
1. ユーザーがメールアドレスとパスワードでサインアップ 2. Supabaseが確認メールを自動送信 3. ユーザーがメール内のリンクをクリックして認証完了
確認メールのテンプレートは、Supabaseのダッシュボードからカスタマイズできます。
OAuth(ソーシャルログイン)
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: `${window.location.origin}/auth/callback`,
},
});Google、GitHub、Twitter/X、Discord、Appleなど、20種類以上のOAuthプロバイダーに対応しています。
OAuthの設定は、各プロバイダーでClient IDとClient Secretを取得し、Supabaseのダッシュボードに設定するだけです。
以前はOAuth認証の実装だけで1週間かかっていましたが、Supabaseなら数時間で完了します。
Supabaseデータベース
Row Level Security(RLS)
Supabaseの最大の特徴の一つが、Row Level Securityです。
RLSは、PostgreSQLの機能を活用して、データベースレベルでアクセス制御を行う仕組みです。
-- ユーザーは自分のデータのみ閲覧可能
CREATE POLICY "ユーザーは自分のプロフィールのみ閲覧可能"
ON profiles FOR SELECT
USING (auth.uid() = user_id);
-- ユーザーは自分のデータのみ更新可能
CREATE POLICY "ユーザーは自分のプロフィールのみ更新可能"
ON profiles FOR UPDATE
USING (auth.uid() = user_id);これがどれほど強力かというと、APIの認可ロジックをバックエンドコードに書く必要がなくなるのです。
従来のアプローチでは、すべてのAPIエンドポイントに「このユーザーにこのデータへのアクセス権があるか?」というチェックロジックを書く必要がありました。
1箇所でもチェックを忘れると、セキュリティホールになります。
RLSを使えば、チェックロジックはデータベースに集約されます。
フロントエンドから直接Supabaseのクライアントライブラリでクエリを発行しても、RLSポリシーによって自動的にフィルタリングされます。
1人開発で「セキュリティの見落とし」を防ぐには、最も効果的な手段だと実感しています。
リアルタイムサブスクリプション
Supabaseのリアルタイム機能は、データベースの変更をリアルタイムでフロントエンドに通知できます。
const channel = supabase
.channel('messages')
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'messages',
filter: `room_id=eq.${roomId}`,
},
(payload) => {
// 新しいメッセージが挿入された時のコールバック
setMessages((prev) => [...prev, payload.new]);
}
)
.subscribe();WebSocketの管理、再接続ロジック、バックプレッシャーの制御。
これらを自前で実装すると数週間はかかりますが、Supabaseならコールバックを設定するだけです。
@SOHOのメッセージ機能でこのリアルタイムサブスクリプションを使っていますが、遅延は体感で100ms以下。
十分にリアルタイムと呼べるパフォーマンスです。
Supabaseストレージ
ファイルのアップロード
const { data, error } = await supabase.storage
.from('avatars')
.upload(`${userId}/profile.jpg`, file, {
cacheControl: '3600',
upsert: true,
});ストレージもRLSと同様に、バケットごとにアクセスポリシーを設定できます。
-- ユーザーは自分のフォルダにのみアップロード可能
CREATE POLICY "ユーザーは自分のフォルダにアップロード可能"
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'avatars' AND
auth.uid()::text = (storage.foldername(name))[1]
);S3互換のAPIなので、将来的にAWS S3に移行する場合も、コードの変更は最小限で済みます。
画像の変換
Supabaseのストレージには、画像のリサイズ機能が組み込まれています。
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('profile.jpg', {
transform: {
width: 200,
height: 200,
resize: 'cover',
},
});サムネイル生成のためにLambdaやCloud Functionsを用意する必要がありません。
以前はSharpやImageMagickを使って自前でリサイズ処理を書いていましたが、Supabaseではパラメータを指定するだけです。
この「自分で書かなくていい」という安心感は、1人開発者にとって非常に大きいのです。
運用で学んだ注意点
Supabaseを1年以上運用してきた中で、いくつかの注意点が見えてきました。
1. RLSの設定ミスに注意
RLSを有効にしたテーブルにポリシーを設定し忘れると、そのテーブルへのアクセスが完全にブロックされます。
私はこれで3時間デバッグに費やしました。
「データが取得できない」→「APIの問題か?」→「フロントエンドの問題か?」と追いかけた結果、RLSのポリシーが未設定だったという。。
対策として、テーブルを作成したら必ずその場でRLSポリシーも設定することをルーティン化しています。
2. マイグレーションの管理
Supabaseのダッシュボードから直接テーブルを変更できますが、本番環境ではマイグレーションファイルで管理すべきです。
supabase migration new add_users_tableダッシュボードでの直接変更は、変更履歴が残らず、環境の再現性が失われます。
開発環境でマイグレーションファイルを作成し、テストしてから本番に適用する。
この手順を守ることで、データベースの変更を安全に管理できます。
3. Edge Functionsの活用
SupabaseのEdge Functions(Deno Deploy ベース)は、サーバーレス関数の実行環境です。
フロントエンドから直接呼び出せない外部APIとの連携や、機密性の高い処理に使っています。
// supabase/functions/send-email/index.ts
Deno.serve(async (req) => {
const { to, subject, body } = await req.json();
// メール送信ロジック
// ...
return new Response(JSON.stringify({ success: true }), {
headers: { 'Content-Type': 'application/json' },
});
});ただし、Edge Functionsはコールドスタートがあるため、初回のリクエストは数百ミリ秒の遅延が発生します。
リアルタイム性が求められる処理には、Express等の常駐サーバーのほうが適しています。
Supabaseの料金体系
2026年3月時点のSupabase料金体系を整理します。
| プラン | 月額 | DB容量 | ストレージ | 帯域幅 |
|---|---|---|---|---|
| Free | $0 | 500MB | 1GB | 5GB |
| Pro | $25 | 8GB | 100GB | 250GB |
| Team | $599 | 8GB〜 | 100GB〜 | 250GB〜 |
個人開発ならProプラン(月額$25)で十分です。
年間$300(約4.5万円)。
Auth0 + PlanetScale + AWS S3を個別に契約するよりも、大幅に安い。
しかも、すべてが1つのダッシュボードで管理できます。
読者の皆さんへ
もしあなたが「認証の実装が面倒」「データベースの管理が大変」「ストレージの設定がわからない」と感じているなら、Supabaseは間違いなく試す価値があります。
特に1人開発者や小規模チームにとって、バックエンドの複雑さを劇的に減らせるツールです。
ただし、一つだけ注意してほしいのは、Supabaseに依存しすぎないことです。
SupabaseはPostgreSQLベースなので、標準的なSQLを使う限りベンダーロックインのリスクは低いです。
ところが、RLSポリシーやEdge Functionsなど、Supabase固有の機能に深く依存すると、移行時のコストが増大します。
「Supabaseがなくなっても、PostgreSQLとExpress(またはNext.js API Routes)で動く設計」を意識しておくことをお勧めします。
この記事が、バックエンドの構築に悩んでいる方の参考になれば幸いです。

