Next.jsを企業向けに最適化！2025年のアプリ構築術 | エピソード5: Redisでスケーラビリティを強化

## 目標
- Next.jsアプリのスケーラビリティを向上させる方法を学ぶ。
- Redisを使ってキャッシュを実装する。
- ブログの読み込み速度を最適化し、大規模運用に備える。

---

## 1. 企業向けアプリにおけるスケーラビリティの重要性
企業向けアプリでは、ユーザー数の増加やトラフィックの急増に対応する必要があります。Redisを使ったキャッシュは、データベースへの負荷を軽減し、高速なレスポンスを実現します。このエピソードでは、ブログの投稿リストをキャッシュします。

---

## 2. Redisのインストールと設定
Redisをプロジェクトに導入します。

### 手順：
1. **ローカルRedisのインストール**（オプション）：
   - Dockerを使用する場合：
     ```
     docker run -d -p 6379:6379 redis
     ```
2. **ライブラリのインストール**：
   ターミナルで以下を実行：
   ```
   npm install redis
   ```

---

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

### `lib/redis.ts`の作成：
```ts
import { createClient } from 'redis';

const redis = createClient({
  url: 'redis://localhost:6379', // 本番では環境変数を使用
});

redis.on('error', (err) => console.error('Redisエラー:', err));

export async function connectRedis() {
  if (!redis.isOpen) {
    await redis.connect();
  }
  return redis;
}
```

**注意**：
- 本番ではUpstashなどのマネージドRedisサービスを使用し、環境変数でURLを管理。

---

## 4. キャッシュの実装
投稿リストをRedisでキャッシュし、高速化します。

### `app/api/posts/route.ts`の作成：
```ts
import { NextResponse } from 'next/server';
import { supabase } from '../../../lib/supabase';
import { connectRedis } from '../../../lib/redis';

export async function GET() {
  const redis = await connectRedis();
  const cacheKey = 'posts_cache';

  // キャッシュから取得を試みる
  const cachedPosts = await redis.get(cacheKey);
  if (cachedPosts) {
    return NextResponse.json(JSON.parse(cachedPosts));
  }

  // キャッシュがない場合、Supabaseから取得
  const { data: posts } = await supabase
    .from('posts')
    .select('*')
    .order('created_at', { ascending: false });

  // キャッシュに保存（有効期限60秒）
  await redis.setEx(cacheKey, 60, JSON.stringify(posts));

  return NextResponse.json(posts);
}
```

### `app/page.tsx`の編集：
```tsx
'use client';

import { useEffect, useState } from 'react';

export default function Home() {
  const [posts, setPosts] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchPosts = async () => {
      const res = await fetch('/api/posts');
      const data = await res.json();
      setPosts(data);
      setLoading(false);
    };
    fetchPosts();
  }, []);

  if (loading) return <p className="text-center">読み込み中...</p>;

  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>
  );
}
```

---

## 実践：キャッシュ付きブログ
- **キャッシュ**：投稿リストをRedisに保存し、60秒間再利用。
- **高速化**：データベースへの直接アクセスを減らし、レスポンスを向上。

**確認**：
- `npm run dev`で起動し、`http://localhost:3000`で読み込み速度が向上するか確認。
- Redis CLI（`redis-cli`）で`GET posts_cache`をチェック。

---

## エピソード5の終了
- Redisを使ってキャッシュを実装しました。
- ブログのスケーラビリティと速度を強化しました。
- シリーズ完結！お疲れ様でした！

---

この記事が役に立ったと思ったら、ぜひ「いいね」を押して、ストックしていただければ嬉しいです！シリーズを通して学んだことをぜひ活用してください！