1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Posted at

目標

  • 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の作成:

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の作成:

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の編集:

'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を使ってキャッシュを実装しました。
  • ブログのスケーラビリティと速度を強化しました。
  • シリーズ完結!お疲れ様でした!

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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?