← Blog
Claude CodeAI DevelopmentReactRefactoring

Claude Codeで200コンポーネントを一括修正した実録 — バグ分類・修正・検証の全工程

9 分で読める

このトピックを深掘りする

Claude Code活用

Claude Codeを使った大規模リファクタリング・CLAUDE.md設計・セッション管理の実践知

全4本中 1 本目。

このトピックの記事一覧

シリーズ全体の流れを見ながら、次に読む記事へ進めます。 初めての方はホームへ →

はじめに

このポートフォリオサイトには211個のインタラクティブコンポーネントがある。流体シミュレーション、ピアノ、迷路生成、ピンボール——ブラウザ上で動く小さなデモを次々と追加してきた結果だ。

問題は、これだけの数になるとバグも比例して増えることだ。setTimeout のリーク、AudioContext の未ハンドル例外、NaN が Canvas に流れ込む数値安全性の欠如。1つ1つは小さいが、211ファイルを手動で点検して直すのは現実的ではない。

そこでClaude Codeを使い、6コミットで延べ100+コンポーネントを一括修正した。この記事はその実録だ。何が効いて、何が失敗したかを、コミットハッシュとファイル数の実データとともに共有する。

一括修正の実績データ

まず結果から示す。以下は実際のコミットログから抽出したデータだ。

  • 08925bcb — 31ファイル: リソースリーク、コード品質、安全性の包括修正
  • 04163d8e — 18ファイル: AudioContext エラーハンドリング、mountedRef ガード、clipboard 安全性
  • f51f0c83 — 15ファイル: モジュールレベル可変状態の排除、レンダーパフォーマンス最適化
  • 1fc14711 — 8ファイル: 数値安全性ガード、Canvas サイズバリデーション、システム設定追跡
  • 7723cfaf — 16コンポーネント: passive event listener 追加、touch-action 設定、Pointer Events 統一
  • e129df45 — 7コンポーネント: キーボードアクセシビリティ対応

合計で95ファイル以上を修正した。各コミットは1つのバグカテゴリに絞っている。これが精度を保つための最も重要な判断だった。

ワークフロー: 「分類 → 一括適用 → 検証」

一括修正は4ステップで進めた。

1. バグの分類

最初にやるのは「パターンの発見」だ。211コンポーネントを眺めて、繰り返し現れるバグを分類する。

実際に見つかったパターンの例:

  • setTimeout/setInterval リーク: useEffect の cleanup で clearTimeout していない
  • AudioContext 未ハンドル: ユーザーインタラクション前の new AudioContext() が例外を投げる
  • NaN 伝播: canvas.width が 0 のとき 1 / widthInfinity になり描画が壊れる
  • モジュールレベル状態: ファイルスコープで let count = 0 のように状態を持つとHMRで壊れる
  • mouse → pointer 未統一: onMouseDownonTouchStart を別々に書いている(Pointer Eventsに統一すべき)

この分類フェーズは人間がやる。Claude Code はパターンの「発見」よりも「大量適用」が得意だからだ。

2. 修正テンプレートの定義

分類ができたら、各パターンに対して「こう直す」というテンプレートを定義する。

例えば AudioContext の修正テンプレート:

// Before: 例外が投げられる可能性
const ctx = new AudioContext()

// After: try-catch + resume() ガード
let ctx: AudioContext | null = null
try {
  ctx = new AudioContext()
  if (ctx.state === 'suspended') {
    await ctx.resume()
  }
} catch (e) {
  console.warn('AudioContext initialization failed:', e)
}

数値安全性のテンプレート:

// Before: NaN/Infinity が伝播する
const scale = 1 / canvas.width

// After: ガード付き
const scale = canvas.width > 0 ? 1 / canvas.width : 1

このテンプレートを CLAUDE.md に記述しておくと、Claude Code が全ファイルに一貫して適用してくれる。

3. 一括適用

Claude Code にパターンとテンプレートを渡し、「このパターンに該当する全ファイルを修正して」と指示する。

ここで重要なのは 1回のセッションで1カテゴリだけ を扱うことだ。「AudioContext の修正」と「passive listener の追加」を同時に頼むと、見落としが発生する。コンテキストウィンドウは最も希少なリソースだ。

実際のセッションの流れ:

  1. 対象パターンを説明(テンプレート付き)
  2. Claude Code が該当ファイルを走査
  3. 修正を適用
  4. ビルドが通ることを確認
  5. 1コミット

4. 検証

bun run buildTypeScript の型チェックとビルドを通す。これが最低限のバリデーションだ。加えて、修正カテゴリによっては手動確認も行う。

  • Canvas 系の修正 → ブラウザで実際に描画を確認
  • AudioContext 系 → Safari と Chrome で音声再生を確認
  • アクセシビリティ系 → キーボードのみで操作を確認

全自動にはできないが、「バグカテゴリごとに確認観点が決まっている」ので効率は良い。

効いたプラクティス

6回のバルクフィックスを通じて学んだ、効果の高いプラクティスを4つ挙げる。

バリデーション先行

テストやビルドチェックを先に整備してから Claude Code に渡すと、品質が体感で2-3倍になる。AI は「何が正解か」を判定する手段があると、自己修正のループが回る。

逆に、バリデーション手段がないと「見た目は正しそうだが実は壊れている」コードが増える。vitest を導入して97テストを一括追加したのも、この考え方に基づいている。

1セッション1タスク

先述の通り、1回のセッションでは1つのバグカテゴリだけを扱う。コミット f51f0c83(モジュールレベル状態の排除、15ファイル)と 04163d8e(AudioContext 修正、18ファイル)は別セッションで実行した。

混ぜると精度が下がるだけでなく、レビューも困難になる。「このコミットで何が変わったか」が一目でわかる粒度を保つことが重要だ。

パターンの名指し

「このファイルと同じパターンで修正して」が最も精度が高い指示方法だ。例えば:

Match3.tsx の AudioContext 修正パターンを参照して、残りの17ファイルに同じ修正を適用して。

抽象的な説明よりも、具体的なコード例を1つ渡す方が圧倒的に再現性が高い。

レビュー視点の分離

コードレベル(微視的)のレビューと仕様レベル(巨視的)のレビューは別々に行う。

  • 微視的: 「clearTimeout が正しく呼ばれているか」「null チェックが漏れていないか」
  • 巨視的: 「この修正でユーザー体験が変わっていないか」「パフォーマンスに影響はないか」

1つのレビューで両方を見ようとすると、どちらも中途半端になる。

失敗したこと

成功談だけでは不誠実なので、失敗も共有する。

「全部直して」は機能しない

最初の試みでは、「全コンポーネントのバグを全部直して」と丸投げした。結果は散々だった。スコープが広すぎて、修正の粒度がバラバラになり、一部は過剰な書き換え、一部は見落としという状態に。

ここから「1カテゴリ1コミット」のルールが生まれた。

バグカテゴリの混合

初期のコミット 08925bcb(31ファイル)は実は「リソースリーク、コード品質、安全性」と3カテゴリが混在している。このコミットのレビューは他の5つと比べて明らかに時間がかかった。後の5コミットでは1カテゴリに絞った結果、レビュー時間が大幅に短縮された。

CLAUDE.md の肥大化

プロジェクトの CLAUDE.md にルールを追加し続けると、ある時点から効かなくなる。ルールが多すぎてコンテキスト内で競合するのだ。

対策として定期的な棚卸しを行い、「もう該当するコードがないルール」や「一般的すぎて意味がないルール」を削除している。hooksは決定論的に動くが、CLAUDE.md は助言的にしか機能しない。効かないルールは削除が最善だ。

定量的な結果

プロジェクト全体の数字を共有する。

  • 総コミット数: 323
  • Claude co-authored コミット: 82(約25%)
  • バッチフィーチャーコミット: 21回(各5コンポーネントずつ新規追加)
  • バルクフィックスコミット: 6回(合計100+コンポーネント修正)
  • テスト一括追加: 97テスト(vitest 導入時)

注目すべきは、コミットの25%が Claude との共著である一方、アーキテクチャ設計やワークフロー定義は100%人間が行っている点だ。AI が書いたコードの品質を担保しているのは、人間が設計した「仕組み」だ。

AIとの分業モデル

6回のバルクフィックスを経て、AI との分業モデルが明確になった。

人間が担当すること:

  • アーキテクチャ設計(Canvas vs DOM の判断、物理エンジンの設計)
  • バグパターンの発見と分類
  • ワークフローの定義(「1カテゴリ1コミット」などのルール)
  • デザイン目標の設定(「滞在時間の最大化」という方針)
  • 最終的な品質判断

AI が担当すること:

  • パターンに基づく実装の大量適用
  • リファクタリング(同じ変換を多数のファイルに適用)
  • バグ修正(テンプレートが定義済みの場合)
  • テストの一括生成
  • コンテンツ生成

核心は「仕組みの中で AI を動かす」ことだ。テンプレート、ルール、パターンを人間が事前に定義し、AI は選択と配置に集中する。AI に「何を作るか」を考えさせるのではなく、「定義済みのパターンをどこに適用するか」を判断させる。

これは工場のラインに似ている。設計図は人間が書く。AI は設計図に従って組み立てる。設計図の品質がそのまま成果物の品質になる。

まとめ:Claude Code一括修正

211コンポーネントのバルクフィックスで学んだことを3つに絞る。

1. AI は「パターンの大量適用」が最も得意

18ファイルに同じ AudioContext 修正を適用する、16コンポーネントの mouse events を pointer events に書き換える——こうした反復作業での AI の精度と速度は、人間を圧倒する。

2. 人間は「パターンの発見と定義」に集中すべき

「setTimeout リークがある」と気づくのは人間の仕事だ。「useEffect の cleanup に clearTimeout を追加する」というテンプレートを書くのも人間の仕事だ。AI にパターンを発見させようとすると、精度が大幅に下がる。

3. バルクフィックスの秘訣は「分類の粒度」

1コミットに1カテゴリ。これが全てだ。スコープを狭く保てば、AI の精度は上がり、レビューは楽になり、問題が起きたときのロールバックも容易になる。

200コンポーネントを1つずつ直す必要はない。正しく分類すれば、6回の操作で済む。