インディーハッカー道
Supabaseで認証・DB・ストレージを一括管理する方法
開発記

Supabaseで認証・DB・ストレージを一括管理する方法

·10分で読める
平城寿
平城寿
@SOHO創業者 / インディーハッカー

この記事のポイント

  • 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$0500MB1GB5GB
Pro$258GB100GB250GB
Team$5998GB〜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)で動く設計」を意識しておくことをお勧めします。

この記事が、バックエンドの構築に悩んでいる方の参考になれば幸いです。

シェア
#Supabase#PostgreSQL#認証#BaaS#1人開発
平城寿
平城寿
インディーハッカー。2004年に@SOHOを創業し、20年間1人で運営。
フォロー

関連記事