🎣 Supabase Webhooks:自動化で駆動するデータベース

従来のバックエンド開発では、「データが変更された」時に他のアクションをトリガーするのは、非常に面倒でした。

例えば:「ユーザー登録が成功した時、ウェルカムメールを送信する。」 従来の方法:

  1. フロントエンドが /api/register を呼び出す。
  2. バックエンドでAPI内に db.users.insert(...) を記述。
  3. Insertが成功したら、バックエンドが sendWelcomeEmail(...) を呼び出す。
  4. メール送信が失敗した場合、リトライロジックも処理する必要がある。

この方法の問題点:もし別のAPI /api/admin/create-user を追加したり、上司が直接データベース管理画面でユーザーを手動追加した場合、これらのユーザーはウェルカムメールを受け取れません。ロジックが特定のAPI内に固定されているからです。

「誰がこのテーブルを操作しても、新しいデータがあれば、データベース自身がメール送信をトリガーする」方法はないでしょうか? あります!それが Database Webhooks(データベーストリガー) です!


1. Database Webhooksとは?

PostgreSQLの基盤には、Trigger(トリガー)という非常に強力な機能があります。これは特定のテーブルで発生する INSERTUPDATEDELETE イベントを監視できます。

Supabaseチームはこの基盤機能をラップし、非常に使いやすい Database Webhooks を作成しました。 その動作ロジックは: [このテーブル]で[追加/更新/削除]が発生した時、自動的に[HTTP POSTリクエスト]を[指定したURL]に送信する。

これにより、データベース内部に閉じていたイベントが、一気にインターネット全体に解放されます!


2. 実践シナリオ:注文ステータス更新通知

orders テーブルがあり、status カラム(pendingpaidshipped など)があるとします。 「注文ステータス�� paid に更新されたら、APIを叩いて上司に出荷通知する(またはLine Notifyと連携する)」とします。

ステップ1:Webhookを受信するAPIの作成(Next.js)

まず、Next.jsプロジェクトでWebhookを受信するAPIを準備します:

// src/app/api/webhooks/order-paid/route.ts
import { NextResponse } from 'next/server';

export async function POST(request: Request) {
  try {
    // 1. Supabaseから送信されるWebhook Payloadを取得
    const body = await request.json();
    
    // Supabase Webhookのデータ形式は以下のようになります:
    // {
    //   "type": "UPDATE",
    //   "table": "orders",
    //   "record": { "id": "123", "status": "paid", "amount": 500 },     // 新しいデータ
    //   "old_record": { "id": "123", "status": "pending", "amount": 500 } // 古いデータ
    // }

    const newRecord = body.record;
    const oldRecord = body.old_record;

    // 2. ロジック判定:本当に「他のステータスからpaidに変わった」か確認
    if (newRecord.status === 'paid' && oldRecord.status !== 'paid') {
      console.log(`🎉 支払い通知を受信!注文ID:${newRecord.id},金額:${newRecord.amount}`);
      
      // TODO: ここでメールサービス(Resend)やLine Notifyを呼び出せます!
      // sendLineNotify(`注文 ${newRecord.id} が支払われました。すぐに出荷してください!`);
    }

    return NextResponse.json({ success: true });
  } catch (error) {
    return NextResponse.json({ error: 'Webhook処理に失敗しました' }, { status: 500 });
  }
}

ステップ2:Supabase管理画面でWebhookを設定

次に、SupabaseにこのAPIにイベントを送信するよう指示します。

  1. Supabase管理画面にログイン。
  2. 左メニューで Database -> Webhooks を選択。
  3. 右上の Create a new Hook をクリック。
  4. 条件を設定:
    • Name: Order Paid Webhook
    • Table: orders テーブルを選択
    • Events: Update をチェック(ステータス更新を監視するため)
  5. HTTPリクエストを設定:
    • Method: POST
    • URL: APIのURLを入力(ローカル開発中の場合はNgrokでlocalhostを公開する必要があります。例:https://your-ngrok.app/api/webhooks/order-paid
  6. HTTP Headersを設定:
    • Content-type: application/json
    • (強く推奨)Secret Tokenを追加:Authorization: Bearer my-super-secret-token
  7. Save hook をクリック。

3. セキュリティ対策:Webhookの真偽を検証する方法

これは非常に恐ろしいことです:/api/webhooks/order-paidインターネット上に公開されています! もしハッカーがこのURLを推測し、Postmanで POST リクエストを送信し、偽の {"status": "paid"} 注文データを送り込んだ場合、システムは支払いがあったと誤認し、出荷を繰り返してしまいます!

防御方法:Secret Tokenの検証

SupabaseでWebhookを設定する際(ステップ6)、カスタムHTTPヘッダーを追加しました: Authorization: Bearer my-super-secret-token

Next.jsのコードにセキュリティチェックを追加します:

// src/app/api/webhooks/order-paid/route.ts

export async function POST(request: Request) {
  // 🛡️ セキュリティの第一防御線:キーを確認
  const authHeader = request.headers.get('Authorization');
  if (authHeader !== `Bearer ${process.env.SUPABASE_WEBHOOK_SECRET}`) {
    console.error("ハッキング攻撃!Webhook検証失敗!");
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  // キーが正しい場合、出荷ロジックを続行...
  const body = await request.json();
  // ...
}

これで、SUPABASE_WEBHOOK_SECRET を知っているSupabaseサーバーのみが、あなたのAPIにアクセスできます!


4. Edge Functions vs Webhooks

「SupabaseにはServerless関数(Edge Functions)もあるが、Webhookと何が違うのか?」と疑問に思うかもしれません。

  • Edge Functions:Supabase上でホストされるコード(Deno環境)。非常に軽量な計算ロジックに適しています。
  • Database Webhooks:イベントを外部にプッシュします。通常はNext.jsプロジェクト(Node.js環境)にイベントを送信することを推奨します。

実践的なアドバイス: Next.js App Routerを使用するフルスタック開発者の場合、WebhookでNext.js APIにイベントを送信することを強く推奨します。 Next.jsには既にORM(Prisma/Drizzle)、メール送信モジュール、決済モジュールが整備されています。Supabase Edge Functionsでロジックを再実装するよりも、すべてのビジネスロジックをNext.jsで一元管理した方が、開発体験が何倍もスムーズです!

Database Webhooksをマスターすれば、アーキテクチャは「受動的なクエリ」から「イベント駆動型(Event-Driven)」に進化します。これが大規模で拡張性のあるシステムを構築する究極の秘訣です!

完全なチュートリアルをロック解除

このチャプターは有料コンテンツです。プロジェクトに参加して、10以上の神レベルのPromptや実際のソースコード例を含む、5000字以上の深い分析をロック解除してください!