はじめに
この記事では、Next.js + Supabase を組み合わせて、モダンなWeb開発に必要な7つの主要機能を実際に動かしながら学べるハンズオンを提供します。
🚀 本記事のコンセプト:最短で「動く」を体験する
Supabaseの強力な機能を最短ルートで理解するため、本記事ではあえてセキュリティ設定(RLS)を簡略化しています。
「認証機能を完成させないとDBが触れない」といった依存関係をなくし、各機能を独立して試せるように構成しています。
完成リポジトリ:
https://github.com/ka2-ya/supabase-tutorial
セットアップ
git clone https://github.com/ka2-ya/supabase-tutorial.git
cd supabase-tutorial
npm install
cp .env.local.example .env.local
# .env.localにSupabaseのURL/Keyを設定
npm run dev
1. Database (CRUD)
まずはPostgreSQLの基本操作です。
SQL実行 (SQL Editor)
学習をスムーズに進めるため、ログイン不要で誰でも読み書きできるポリシーを設定します。
CREATE TABLE todos (
id BIGSERIAL PRIMARY KEY,
title TEXT NOT NULL,
completed BOOLEAN DEFAULT false,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- RLSを有効化
ALTER TABLE todos ENABLE ROW LEVEL SECURITY;
-- 【学習用設定】誰でも全ての操作が可能
CREATE POLICY "Enable all access for learning" ON todos FOR ALL TO public USING (true) WITH CHECK (true);
実装例
// 取得・作成・更新・削除
await supabase.from('todos').select('*')
await supabase.from('todos').insert({ title })
await supabase.from('todos').update({ completed: true }).eq('id', id)
await supabase.from('todos').delete().eq('id', id)
2. Authentication
メール認証やGoogleログインを簡単に統合できます。
// サインアップ・ログイン
await supabase.auth.signUp({ email, password })
await supabase.auth.signInWithPassword({ email, password })
// OAuth (Googleなど)
await supabase.auth.signInWithOAuth({ provider: 'google' })
// ユーザーの状態を監視
supabase.auth.onAuthStateChange((event, session) => {
setUser(session?.user ?? null)
})
3. Storage
画像などのファイル管理もSQLライクに操作可能です。
バケット作成後のポリシー (SQL)
-- 【学習用設定】誰でもファイルのアップロードと読み取りが可能
CREATE POLICY "Public Access" ON storage.objects FOR ALL TO public USING (bucket_id = 'public-files');
実装例
// アップロード・公開URL取得
await supabase.storage.from('public-files').upload(path, file)
const { data } = supabase.storage.from('public-files').getPublicUrl(path)
4. Realtime
データベースの変更を即座にUIに反映させます。
const channel = supabase
.channel('messages')
.on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'messages' },
(payload) => setMessages(prev => [...prev, payload.new])
)
.subscribe()
[!IMPORTANT]
RealtimeはRLSの影響を受けます。学習用ポリシー(USING (true))が設定されていることを確認してください。
5. Edge Functions
Denoベースのサーバーレス関数で、バックエンド処理を記述します。
// supabase/functions/hello-world/index.ts
Deno.serve(async (req) => {
const { name } = await req.json()
return new Response(JSON.stringify({ message: `Hello ${name}!` }))
})
// クライアントからの呼び出し
const { data } = await supabase.functions.invoke('hello-world', { body: { name: 'World' } })
6. Semantic Search (AI / ベクトル検索)
pgvector を使い、キーワード一致ではなく「意味」で検索します。
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
content TEXT NOT NULL,
embedding vector(1536) -- OpenAIのエムベディング次元数
);
-- 類似度検索関数
CREATE FUNCTION match_documents(query_embedding vector(1536))
RETURNS TABLE (id bigint, content text, similarity float)
LANGUAGE plpgsql AS $$
BEGIN
RETURN QUERY
SELECT d.id, d.content, 1 - (d.embedding <=> query_embedding)
FROM documents d
ORDER BY d.embedding <=> query_embedding LIMIT 10;
END; $$;
7. Cron (定期実行)
pg_cron を使って、DB側で定期的なタスクを実行します。
CREATE EXTENSION IF NOT EXISTS pg_cron;
-- 毎日午前3時に古いメッセージを自動削除
SELECT cron.schedule('cleanup-job', '0 3 * * *',
'DELETE FROM messages WHERE created_at < NOW() - INTERVAL ''7 days''');
まとめ
Supabaseを使えば、これまで個別に構築が必要だったインフラがPostgreSQLを中心に集約されます。
かなり便利なのでぜひ試しに動かしてみてください!
今後も試してみた機能は随時追加していきます。
