2025年人気No.1のNext.jsで、最新ツールとウェブを作る！ | エピソード6 データベースの統合

## 目標
- Next.jsにデータベースを統合する方法を学ぶ。
- Supabaseを使って簡単なデータベースをセットアップする。
- CRUD操作（作成、読み取り、更新、削除）を実装する。

---

## 1. データベースの選択
Next.jsと相性の良いデータベースはいくつかあります：
- **Supabase**: オープンソースで、PostgreSQLベース。無料枠あり、リアルタイム機能付き。
- **Firebase**: GoogleのNoSQLソリューション。簡単なセットアップ。
- **MongoDB**: 柔軟なドキュメント型データベース。

このエピソードでは、**Supabase**を使用します。設定が簡単で、Next.jsとの統合がスムーズです。

---

## 2. Supabaseのセットアップ
Supabaseをプロジェクトに導入します。

### 手順：
1. **Supabaseアカウント作成**：
   - [Supabase公式サイト](https://supabase.com)でアカウントを作成し、新しいプロジェクトを開始。
2. **テーブル作成**：
   - Supabaseダッシュボードで「Table Editor」を開き、`posts`テーブルを作成：
     - 列: `id` (自動生成), `title` (text), `content` (text), `created_at` (timestamp, デフォルトで現在時刻)。
3. **APIキーの取得**：
   - ダッシュボードの「Settings > API」から`anon key`と`URL`をコピー。

### ライブラリのインストール：
ターミナルで実行：
```
npm install @supabase/supabase-js
```

---

## 3. Supabaseクライアントの設定
Supabaseと通信するためのクライアントを設定します。

### `lib/supabase.ts`の作成：
```ts
import { createClient } from '@supabase/supabase-js';

const supabaseUrl = 'あなたのSupabase URL';
const supabaseKey = 'あなたのSupabase anon key';
export const supabase = createClient(supabaseUrl, supabaseKey);
```

**注意**：
- 実際のプロジェクトでは、環境変数（`.env.local`）に`supabaseUrl`と`supabaseKey`を保存し、`process.env`で参照してください。

---

## 4. CRUD操作の実装
Supabaseを使って投稿を管理します。

### 投稿の読み取り（Read）：
`app/page.tsx`を編集して投稿リストを取得：
```tsx
import { supabase } from '../lib/supabase';

export default async function Home() {
  const { data: posts, error } = await supabase
    .from('posts')
    .select('*')
    .order('created_at', { ascending: false });

  if (error) {
    console.error('エラー:', error);
  }

  return (
    <div className="min-h-screen flex flex-col items-center bg-gray-100 py-8">
      <h1 className="text-4xl font-bold text-blue-600 mb-8">データベースからの投稿</h1>
      <ul className="space-y-4 max-w-2xl w-full">
        {posts?.map((post) => (
          <li key={post.id} className="bg-white p-4 rounded shadow">
            <a href={`/posts/${post.id}`} className="text-xl font-semibold text-blue-500 hover:underline">
              {post.title}
            </a>
            <p className="text-gray-600">{post.content}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}
```

### 投稿の作成（Create）：
`app/api/posts/route.ts`を作成し、新しい投稿を追加：
```ts
import { NextResponse } from 'next/server';
import { supabase } from '../../../lib/supabase';

export async function POST(request: Request) {
  const { title, content } = await request.json();

  const { data, error } = await supabase
    .from('posts')
    .insert([{ title, content }])
    .select();

  if (error) {
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
  return NextResponse.json(data);
}
```

### 投稿詳細の読み取り（Read）：
`app/posts/[id]/page.tsx`を編集：
```tsx
import { supabase } from '../../../lib/supabase';

export default async function Post({ params }: { params: { id: string } }) {
  const { data: post, error } = await supabase
    .from('posts')
    .select('*')
    .eq('id', params.id)
    .single();

  if (error || !post) {
    return <div>投稿が見つかりません</div>;
  }

  return (
    <div className="max-w-2xl mx-auto p-6">
      <h1 className="text-3xl font-bold text-blue-600 mb-4">{post.title}</h1>
      <p className="text-gray-600">{post.content}</p>
    </div>
  );
}
```

---

## 実践：動的ブログへの移行
- **Home**: Supabaseから投稿リストを取得。
- **投稿詳細**: 動的ルートで個別の投稿を表示。
- **API**: 新しい投稿を追加するエンドポイントを作成。

**テスト**：
1. Supabaseダッシュボードで直接投稿を追加。
2. `curl`やPostmanで`/api/posts`にPOSTリクエストを送信：
   ```
   curl -X POST http://localhost:3000/api/posts -H "Content-Type: application/json" -d '{"title":"新しい投稿","content":"Supabase最高！"}'
   ```

---

## エピソード6の終了
- SupabaseをNext.jsに統合し、データベースを使ったブログを構築しました。
- CRUD操作の基本を実装しました。

**次回のエピソード**：フォームと認証を追加し、ユーザーインタラクションを強化します。

---

この記事が役に立ったと思ったら、ぜひ「いいね」を押して、ストックしていただければ嬉しいです！次回のエピソードもお楽しみに！