Claude Codeでキャッシュ戦略を設計・実装する方法
Claude Codeを使ってRedis・CDN・アプリケーションレベルのキャッシュ戦略を効率的に設計・実装する方法を解説します。
キャッシュ戦略の設計にClaude Codeを使うメリット
キャッシュは適切に設計しないと、古いデータの表示やメモリの浪費につながります。Claude Codeはアプリケーションのデータアクセスパターンを分析し、最適なキャッシュ戦略を提案・実装できます。
Redisキャッシュの実装
> Redisを使ったキャッシュレイヤーを実装して。
> キャッシュ無効化、TTL管理、キャッシュアサイドパターンで。
// src/lib/cache.ts
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL!);
interface CacheOptions {
ttl?: number; // 秒単位
prefix?: string;
}
export class CacheService {
private defaultTTL = 300; // 5分
async get<T>(key: string, options?: CacheOptions): Promise<T | null> {
const fullKey = this.buildKey(key, options?.prefix);
const data = await redis.get(fullKey);
if (!data) return null;
try {
return JSON.parse(data) as T;
} catch {
return null;
}
}
async set<T>(key: string, value: T, options?: CacheOptions): Promise<void> {
const fullKey = this.buildKey(key, options?.prefix);
const ttl = options?.ttl ?? this.defaultTTL;
await redis.setex(fullKey, ttl, JSON.stringify(value));
}
async getOrSet<T>(
key: string,
fetcher: () => Promise<T>,
options?: CacheOptions
): Promise<T> {
const cached = await this.get<T>(key, options);
if (cached !== null) return cached;
const data = await fetcher();
await this.set(key, data, options);
return data;
}
async invalidate(key: string, prefix?: string): Promise<void> {
const fullKey = this.buildKey(key, prefix);
await redis.del(fullKey);
}
async invalidatePattern(pattern: string): Promise<void> {
const keys = await redis.keys(pattern);
if (keys.length > 0) {
await redis.del(...keys);
}
}
private buildKey(key: string, prefix?: string): string {
return prefix ? `${prefix}:${key}` : key;
}
}
export const cache = new CacheService();
キャッシュアサイドパターンの実装
// src/services/product-service.ts
import { cache } from '@/lib/cache';
import { prisma } from '@/lib/db';
export class ProductService {
async getProduct(id: string) {
return cache.getOrSet(
`product:${id}`,
() => prisma.product.findUnique({
where: { id },
include: { category: true, reviews: { take: 10 } },
}),
{ ttl: 600, prefix: 'products' }
);
}
async getPopularProducts(limit = 20) {
return cache.getOrSet(
`popular:${limit}`,
() => prisma.product.findMany({
orderBy: { salesCount: 'desc' },
take: limit,
include: { category: true },
}),
{ ttl: 300, prefix: 'products' }
);
}
async updateProduct(id: string, data: UpdateProductInput) {
const product = await prisma.product.update({
where: { id },
data,
});
// 関連キャッシュを無効化
await cache.invalidate(`product:${id}`, 'products');
await cache.invalidatePattern('products:popular:*');
return product;
}
}
HTTP キャッシュヘッダーの設定
// src/middleware.ts
import { NextResponse, NextRequest } from 'next/server';
export function middleware(req: NextRequest) {
const res = NextResponse.next();
const path = req.nextUrl.pathname;
// 静的アセット:長期キャッシュ
if (path.match(/\.(js|css|png|jpg|svg|woff2)$/)) {
res.headers.set('Cache-Control', 'public, max-age=31536000, immutable');
}
// API:キャッシュなし
if (path.startsWith('/api/')) {
res.headers.set('Cache-Control', 'no-store');
}
// ページ:短期キャッシュ + ISR
if (!path.startsWith('/api/') && !path.match(/\.[a-z]+$/)) {
res.headers.set('Cache-Control', 'public, s-maxage=60, stale-while-revalidate=300');
}
return res;
}
メモリキャッシュ(アプリケーション内)
小規模なデータにはインメモリキャッシュが有効です。
// src/lib/memory-cache.ts
interface CacheEntry<T> {
value: T;
expiresAt: number;
}
export class MemoryCache {
private store = new Map<string, CacheEntry<unknown>>();
private maxSize: number;
constructor(maxSize = 1000) {
this.maxSize = maxSize;
}
get<T>(key: string): T | null {
const entry = this.store.get(key);
if (!entry) return null;
if (Date.now() > entry.expiresAt) {
this.store.delete(key);
return null;
}
return entry.value as T;
}
set<T>(key: string, value: T, ttlMs: number): void {
// サイズ制限チェック
if (this.store.size >= this.maxSize) {
const firstKey = this.store.keys().next().value;
if (firstKey) this.store.delete(firstKey);
}
this.store.set(key, {
value,
expiresAt: Date.now() + ttlMs,
});
}
clear(): void {
this.store.clear();
}
}
// 設定値などの頻繁にアクセスされるデータに使用
export const configCache = new MemoryCache(100);
キャッシュ戦略の選定ガイド
| データの種類 | 推奨キャッシュ | TTL目安 |
|---|---|---|
| 設定マスタ | メモリ + Redis | 1時間 |
| ユーザープロフィール | Redis | 10分 |
| 商品一覧 | Redis + CDN | 5分 |
| セッション情報 | Redis | 24時間 |
| 静的アセット | CDN | 1年 |
| APIレスポンス | HTTP Cache | 1分 |
キャッシュのモニタリング
// キャッシュヒット率の計測
export class CacheMetrics {
private hits = 0;
private misses = 0;
recordHit() { this.hits++; }
recordMiss() { this.misses++; }
getHitRate(): number {
const total = this.hits + this.misses;
return total === 0 ? 0 : this.hits / total;
}
getStats() {
return {
hits: this.hits,
misses: this.misses,
hitRate: `${(this.getHitRate() * 100).toFixed(1)}%`,
};
}
}
まとめ
Claude Codeを使えば、Redisキャッシュ、HTTPキャッシュ、メモリキャッシュなど多層的なキャッシュ戦略を効率的に設計・実装できます。キャッシュの設計方針をCLAUDE.mdに記述しておくと、プロジェクト全体で一貫した実装が得られます。パフォーマンス改善の全体像は生産性を3倍にするTipsも参考にしてください。
Claude Codeの詳細はAnthropic公式ドキュメントをご覧ください。Redisの詳細はRedis公式ドキュメントを参照してください。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。
この記事を書いた人
Masa
現役DX室長|Claude Code でゼロから多言語AI技術メディア運営中。実務直結の自動化、AI開発相談・研修受付中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Code/Codexの安全なAgent Harness実装ガイド|権限・検証・ロールバックまで
AIエージェントを安全に動かす足場を、権限設定、実行計画、検証、ロールバックの4層で実装。Claude Code/Codexの実務例付き。
Claude Code サブエージェント活用パターン10選
Claude Code のサブエージェント機能を使いこなす実践パターンを10個紹介。並列処理、専門化、コンテキスト分離で開発効率を倍増させる方法を解説します。
Claude Code Agent SDK入門 ― 自律エージェントを最速で構築する方法
Claude Code Agent SDKを使って自律型AIエージェントを構築する方法を解説。セットアップからツール定義、マルチステップ実行まで実践コード付きで紹介します。