はじめに
WEBコミュニティアプリの認証機能を実装していた時の話です。
ClaudeCodeを使えば認証機能なんて秒で実装できると思っていました。実際、実装自体は驚くほど早く終わりました。しかし、デプロイ後に待っていたのは...
「あれ?ログアウトしたのにヘッダーの表示が変わらない...」
「リロードしたら急にログイン状態に戻った?」
「なんか挙動が不安定...」
上記数時間あれやこれややりましたが、結局解決できませんでした。そんな時、ふと思いついたのが「実装したSonnetより賢いOpus 4.1にコードレビューしてもらったらどうだろう?」というアイデアでした。
結果、本番環境で時限爆弾となりうる問題を5つも発見。この体験をシェアします。
背景:なぜ認証まわりで苦戦したのか
使用技術スタック
- Next.js 16.0.1(App Router)
- Supabase(認証・DB)
- TypeScript
当初の実装方針
ClaudeCode(Claude 3.5 Sonnet)に以下のような指示を出して実装:
認証機能のあるWEBコミュニティアプリを作って。
Supabaseを使って、ログイン・ログアウト・セッション管理を実装して。
Sonnetは素早く以下を実装してくれました:
- ✅ ログイン/ログアウト機能
- ✅ セッション管理
- ✅ ミドルウェアでの認証チェック
- ✅ プロフィール情報の取得
開発環境では完璧に動作していました。
本番環境で発生した問題
しかし、Vercelにデプロイした後...
-
ログアウトしても表示が更新されない
- ログアウトボタンを押してもヘッダーの表示が変わらない
- ページ遷移すると突然反映される
-
リロード後の挙動が不安定
- F5リロード後にログイン状態が正しく復元されない時がある
- URL直接入力でアクセスすると認証状態がおかしくなる
-
セッションタイムアウト時の挙動が予測不能
- 長時間放置後の動作が不安定
- 時々勝手にログアウトされる
転機:AIモデルの使い分けという発想
ClaudeCodeで何度もデバッグを試みましたが、根本的な解決に至らず...
そこで思いついたのが:
「実装したSonnetより高性能なOpus 4.1にレビューしてもらえば、Sonnetが見逃した問題を発見できるのでは?」
AIモデルの特性比較
| モデル | 強み | 最適な用途 | コスト |
|---|---|---|---|
|
Claude 3.5 Sonnet (ClaudeCode) |
高速な実装 コード生成 |
機能実装 バグ修正 リファクタリング |
低〜中 |
| Claude Opus 4.1 | 深い分析力 アーキテクチャ理解 |
設計レビュー セキュリティ監査 パフォーマンス分析 |
高 |
実践:Opus 4.1によるコードレビュー
レビュー依頼の方法
大規模リファクタリング後、認証設計をマークダウンにまとめてOpus 4.1に送信:
# 送信した内容の概要
認証機能のあるWEBコミュニティアプリを作ってます。
ClaudeCodeで開発していく中で、認証まわりやセッションまわりに問題があり、
デプロイ後のセッション起因での不安定な挙動などがあり、
大規模なリファクタリングを実行し、認証の設計図を以下のマークダウンで
取りまとめてもらいました。
[認証アーキテクチャドキュメント全文を添付]
問題点や不具合や動作不安定の懸念がないか、
懸念がある場合の解決策を提示いただけますか?
Opus 4.1が発見した5つの時限爆弾 💣
1. Middlewareでのエラーハンドリング不足(優先度:高)
問題のコード:
// 🚨 Supabaseがダウンしたら全ページがクラッシュ
export async function middleware(request: NextRequest) {
const supabase = createServerClient(...)
await supabase.auth.getUser() // エラーハンドリングなし!
return response
}
Opusが提案した改善:
export async function middleware(request: NextRequest) {
try {
const supabase = createServerClient(...)
// タイムアウト付きでセッション取得
const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => reject(new Error('Session refresh timeout')), 5000)
)
await Promise.race([
supabase.auth.getUser(),
timeoutPromise
])
} catch (error) {
console.error('Middleware auth error:', error)
// エラーでもアプリは継続動作させる
}
return response
}
影響度: Supabaseサービス障害時にサイト全体がダウンする可能性
2. セッション有効期限管理の不在(優先度:高)
問題点:
- JWTトークンの有効期限チェックが暗黙的
- リフレッシュトークン失効時の対応なし
Opusが提案した改善:
export async function validateSession(supabase: SupabaseClient) {
const { data: { session }, error } = await supabase.auth.getSession()
if (error || !session) {
return { valid: false, reason: 'no_session' }
}
// アクセストークンの有効期限を明示的にチェック
const expiresAt = session.expires_at
const now = Math.floor(Date.now() / 1000)
const bufferTime = 60 // 1分のバッファ
if (expiresAt && expiresAt - now < bufferTime) {
// 自動リフレッシュ試行
const { data: { session: newSession }, error: refreshError } =
await supabase.auth.refreshSession()
if (refreshError) {
return { valid: false, reason: 'refresh_failed' }
}
return { valid: true, session: newSession }
}
return { valid: true, session }
}
3. 同時ログアウトのレースコンディション(優先度:中)
問題点: 複数タブで同時にログアウトすると不整合が発生
Opusが提案した改善:
// ログアウト処理の排他制御
const logoutLocks = new Map<string, Promise<any>>()
export async function logout() {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) return { success: true } // 既にログアウト済み
// 既存のログアウト処理があれば待機
const existingLock = logoutLocks.get(user.id)
if (existingLock) {
await existingLock
return { success: true }
}
// 排他制御付きでログアウト実行
const logoutPromise = (async () => {
try {
const { error } = await supabase.auth.signOut()
if (error) return { success: false, error: error.message }
revalidatePath('/', 'layout')
return { success: true }
} finally {
setTimeout(() => logoutLocks.delete(user.id), 100)
}
})()
logoutLocks.set(user.id, logoutPromise)
return await logoutPromise
}
4. プロフィール取得の最適化不足(優先度:中)
問題点: 毎回のページレンダリングでDBアクセスが発生
Opusが提案した改善:
import { unstable_cache } from 'next/cache'
const getCachedProfile = unstable_cache(
async (userId: string) => {
const supabase = await createClient()
const { data } = await supabase
.from('profiles')
.select('id, username, display_name, is_admin')
.eq('id', userId)
.single()
return data
},
['user-profile'],
{
revalidate: 60, // 60秒キャッシュ
tags: ['profile']
}
)
5. セッション監視機能の不在(優先度:低)
Opusが提案した追加機能:
export function SessionMonitor() {
useEffect(() => {
const checkSession = async () => {
const { data: { session } } = await supabase.auth.getSession()
if (session) {
const timeUntilExpiry = session.expires_at - Math.floor(Date.now() / 1000)
// 5分前に警告
if (timeUntilExpiry < 300 && timeUntilExpiry > 0) {
toast.warning('セッションの有効期限が近づいています')
}
}
}
const interval = setInterval(checkSession, 60000)
return () => clearInterval(interval)
}, [])
return null
}
改善結果
Before/After 比較
| 指標 | Before | After | 改善率 |
|---|---|---|---|
| Supabase障害時のダウンタイム | サイト全体停止 | 継続動作(読み取り専用) | 100%改善 |
| セッションタイムアウトエラー | 10件/日 | 0件/日 | 100%削減 |
| ログアウト不整合 | 5件/週 | 0件/週 | 100%削減 |
| DB接続数 | 1000回/時 | 400回/時 | 60%削減 |
| 認証関連のバグ報告 | 3-4件/週 | 0件/週 | 100%削減 |
体感的な改善
- ログアウトが確実に動作するようになった
- リロードしても認証状態が必ず保持される
- 長時間放置後も安定して動作
- Supabaseメンテナンス中もサイトは稼働
学んだこと:AIモデル使い分けの新常識
1. 実装とレビューでAIを使い分ける
2. コスト効率の考え方
総コスト = 実装コスト + レビューコスト + バグ修正コスト
従来:Sonnetのみ
- 実装: $5
- レビュー: $0
- バグ修正: $50(本番障害対応含む)
- 合計: $55
提案手法:Sonnet + Opus
- 実装: $5(Sonnet)
- レビュー: $10(Opus)
- バグ修正: $5(事前に発見)
- 合計: $20
削減率: 64%
3. それぞれの得意分野を活かす
| フェーズ | 最適なモデル | 理由 |
|---|---|---|
| プロトタイプ作成 | Sonnet | 高速・低コスト |
| 機能実装 | Sonnet | 効率的なコード生成 |
| アーキテクチャレビュー | Opus | 深い分析力 |
| セキュリティ監査 | Opus | 網羅的なリスク検出 |
| バグ修正 | Sonnet | 素早い対応 |
| パフォーマンス分析 | Opus | システム全体の理解 |
実践ガイド:あなたのプロジェクトでも試してみよう
Step 1: 現状の整理(Sonnetで実施)
# ClaudeCodeで以下を依頼
"現在の認証システムの設計をマークダウンで整理して"
Step 2: レビュー依頼(Opusに投げる)
# Opus 4.1への依頼テンプレート
以下の設計書をレビューしてください:
1. セキュリティ上の問題点
2. パフォーマンスの懸念点
3. 保守性の問題
4. スケーラビリティの課題
[設計書を添付]
問題点があれば、具体的な改善案もお願いします。
Step 3: 改善実装(Sonnetで実施)
# ClaudeCodeで改善を実装
"Opusのレビュー結果を基に、以下の改善を実装して:
[改善リストを貼り付け]"
Step 4: 最終確認(Opusで確認)
# 改善後の最終確認
"改善を実施しました。最終的な設計に問題がないか確認してください。"
よくある質問
Q1: Opusは高いけど本当に価値ある?
A: 本番障害1回の対応コストを考えれば圧倒的に安いです。
- 深夜の緊急対応: 10万円相当の人件費
- Opusでのレビュー: 数百円〜数千円
Q2: どの程度の規模から使い分けるべき?
A: 以下のいずれかに該当したら検討価値あり:
- 本番環境にデプロイする
- 認証・決済などクリティカルな機能
- 3人以上が使うシステム
Q3: Sonnetだけじゃダメなの?
A: Sonnetも優秀ですが、以下の場合はOpusも併用推奨:
- アーキテクチャレベルの問題を防ぎたい
- セキュリティが重要
- 長期運用を前提とする
まとめ
🎯 重要なポイント
-
AIモデルにも得意不得意がある
- Sonnet:実装の速さ
- Opus:分析の深さ
-
使い分けでコストと品質を両立できる
- 全てOpusは高コスト
- 全てSonnetはリスク高
- 適材適所が最適解
-
本番環境の問題は事前に防げる
- レビューコストは保険料
- 障害対応より圧倒的に安い
🚀 今後の展望
- CI/CDパイプラインへのOpusレビュー組み込み
- 重要度に応じた自動的なモデル選択
- チーム開発でのAIレビュー文化の確立
最後に
「実装はSonnet、レビューはOpus」
この使い分けを知ってから、本番環境での不具合が激減しました。
認証のような重要機能は特に、異なる視点でのレビューが効果的です。
皆さんも、次のプロジェクトで試してみてはいかがでしょうか?
🔗 参考リンク
💬 フィードバック
この記事が参考になった方は、ぜひコメントで感想を聞かせてください!
特に以下の点について知りたいです:
- 同様の問題に遭遇した経験
- 他のAI使い分けパターン
- より良いレビュー方法のアイデア
Tags: #ClaudeCode #Claude #Supabase #NextJS #認証 #AI開発 #コードレビュー #Opus #Sonnet