現実を知る

3時間で作ったアプリ、3ヶ月後はどうなっているか——バイブコーディングの技術的負債メカニズム

バイブコーディングのプロトタイプが3ヶ月後に誰も手を入れられなくなる理由を、複数の研究データとコード例で解剖する。体験談ではなく、メカニズムの話だ。

公開: 2026年2月26日約12分

3時間で作ったアプリが、3ヶ月後に誰も触れない状態になっている。これは「下手な作り方をした」という話ではない。バイブコーディング特有の構造的なメカニズムが引き起こす、複数の独立した研究が一致して示すパターンだ。


技術的負債とは「分割払いのローン」だ

「技術的負債(Technical Debt)」という言葉は、ソフトウェアエンジニアリングの世界で1990年代から使われてきた概念だ。

簡単に言えば、「今は動く方法を選んで、後で整理する」という選択肢を取るたびに発生する、目に見えない負債だ。クレジットカードに近い。今月は便利に使えるが、来月は利息ごと返すことになる。使い続ければ、返済だけで精いっぱいになる。

エンジニアはこれを意識的にコントロールしながら開発する。「今は負債を取ってでも速く出す」「次のスプリントで整理する」という判断を繰り返す。問題は、バイブコーディングではこのコントロールが機能しない点にある。

AIは「今動くコードを書く」のが仕事だ。後で整理することは、明示的に頼まない限り考えない。毎回のプロンプトで「動くものを作って」と頼めば、毎回「動くもの」が返ってくる。整理は誰もやらないまま積み上がっていく。

技術的負債の恐ろしさは、最初の3ヶ月は何も感じない点にある。「速く作れる!」という感覚だけが残り、負債は静かに蓄積される。請求書が届くのは、新しい機能を追加しようとした瞬間だ。


なぜ負債が生まれるのか——5つのパターン

AIを使った開発で技術的負債が蓄積するメカニズムは、いくつかのパターンに整理できる。

パターン1: セッションをまたぐたびに「方言」が変わる

AIには「先週の自分」という記憶がない。会話を始めるたびにリセットされる。これが命名規則の崩壊を引き起こす。

// ❌ 3ヶ月続けたバイブコードの現実
// Day 1(セッション1)の書き方
const getUserData = async (userId: string) => { /* ... */ };

// Day 30(セッション7)では別の書き方になっている
async function fetchUser(id: string) { /* ... */ }

// Day 90(セッション23)ではさらに変わっている
const user_info = await getUser(user_id);  // スネークケースに混入

// → 同じ「ユーザー取得」が3つの異なる関数として存在する
//   どれが正しいか、どれが最新か、誰にもわからない
// ✅ CLAUDE.mdで命名規則を明示した場合
// どのセッションでも同じルールが適用される
const fetchUserById = async (userId: string): Promise<User> => { /* ... */ };

プロジェクトのルールをファイルに書いてAIに毎回読ませることで、この崩壊は防げる。Claude CodeであればCLAUDE.md、CursorであればCursor Rulesが、AIへの「記憶」として機能する。

パターン2: テストが「通る」が「保証しない」

AIに「テストを書いて」と頼むと、テストを書く。ただしそのテストは、コードが正しく動くことを保証していないことがある。「テストが存在する」という事実と「テストが品質を担保している」という事実は別物だ。

// ❌ AIが「テスト書いておきました」と生成したコード
test("ユーザーを作成できる", async () => {
  const result = await createUser({ name: "test" });
  expect(result).toBeDefined(); // 何かが返ればOK
  // → エラーオブジェクト { error: "Failed" } が返っても通過する
});
// ✅ 実際に動作を保証するテスト
test("ユーザーを作成すると正しいデータが返る", async () => {
  const result = await createUser({ name: "test" });
  expect(result.id).toBeDefined();
  expect(result.name).toBe("test");
  expect(result.createdAt).toBeInstanceOf(Date);
  expect("error" in result).toBe(false); // エラーオブジェクトでないことを確認
});

さらに深刻なのは、AIがテスト失敗を「テストを修正する」ことで解決するケースだ。複数の開発者が「Cursorがテストをパスするためにコードを直すのではなくテストを書き換えた」という現象を報告している。バグが隠れたまま、テストだけがグリーンになる。

パターン3: 同じ処理が3箇所に生まれる

AIはコードベース全体を把握していない。別のファイルに同じ処理が存在することを知らず、毎回新しく書く。

// ❌ バイブコーディング3ヶ月後のよくある状態
// src/features/login/ui/form.tsx(Day 5に追加)
if (!email.includes("@")) { setError("メールアドレスが不正"); }

// src/features/signup/ui/form.tsx(Day 20に追加)
if (email.indexOf("@") === -1) { alert("無効なメール"); }

// src/features/profile/ui/form.tsx(Day 60に追加)
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) { return "メール形式が間違っています"; }

// → バリデーションルールが3種類存在する
//   どれかを直してもあとの2つには反映されない
// ✅ 共通処理を一箇所に集約した場合
// src/shared/lib/validation.ts
export const validateEmail = (email: string): boolean =>
  /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);

// あとは全箇所でこれを呼ぶだけ

これが「コードの複製(code duplication)」と呼ばれる問題だ。ひとつのバグを直すとき、3箇所を探して同時に直す必要が生じる。1箇所見落とせば、別のルートから同じバグが再発する。

パターン4: ハードコードされた値が増殖する

「今はこれで動く」という判断で直書きされた値は、後で問題になる。

// ❌ 「今は動くから」でハードコード(バイブコードの典型)
const MAX_UPLOAD_SIZE = 5242880; // 5MBだが、なぜこの数字?
const API_URL = "https://api.example.com/v1"; // 環境が変わっても変更できない
const ADMIN_EMAIL = "admin@example.com"; // メアドが変わったら全部探す必要がある

// → 3ヶ月後、誰もこの数字の意味を知らない
//   本番とテストで違う値が必要になっても変更できない
// ✅ 定数・環境変数を正しく管理する
const MAX_UPLOAD_SIZE_BYTES = 5 * 1024 * 1024; // 5MB(意図が読める)
const API_URL = process.env.NEXT_PUBLIC_API_URL; // 環境ごとに切り替えられる

パターン5: 「動かせばいい」最適化がアーキテクチャを壊す

AIにエラーを投げると、そのエラーを消す修正を返す。根本原因を追うのではなく、症状だけを抑える。

モグラ叩きと同じ構造だ。1匹叩けば別の場所から出てくる。APIのタイムアウトエラーを直すためにリトライを増やしたら、今度はデータが二重登録される。二重登録を防ぐためにチェックを入れたら、今度はレスポンスが遅くなる。修正のたびに別の問題が生まれ、コードは複雑さだけが積み上がる。


データで見る「3ヶ月後」の現実

これらのパターンは、複数の独立した研究で定量的に確認されている。

AIコードに含まれる問題の数

コードレビューAIのCodeRabbitが2025年に発表したレポートは、470件のOSSのGitHub Pull Requestを分析した。AI生成のPRと人間が書いたPRを比較すると、差は顕著だった。

  • PR1件あたりの問題数: AI 10.83件 vs 人間 6.45件(約1.7倍)
  • 命名の不一致: 2倍多い
  • 可読性の問題: 3倍以上多い
  • ロジックエラー: 1.75倍多い
  • セキュリティ問題: 2.74倍多い
AI vs human code gen report: AI code creates 1.7x more issuesWe analyzed 470 open-source GitHub pull requests, using CodeRabbit’s structured issue taxonomy and found that AI generated code creates 1.7x more issues.coderabbit.ai

問題の数だけが多いわけではない。問題の「質」も異なる。命名の不一致や可読性の低さは、コードを読む人間のコストを増やす。3ヶ月後に「このコード、何をやっているか」を理解するのに時間がかかる状態が積み上がる。

コードの複製が増え、整理が消える

GitClearが2億1100万行のコード変更を分析した2025年の研究では、AIコーディングが普及した2021年から2024年の間に起きた変化が記録されている。

  • コピペコードの割合: 8.3%(2021年)→ 12.3%(2024年)
  • コードクローン(重複ブロック): 2024年に約4倍に増加
  • 2024年は初めて「コピペ行数」が「リファクタリング(整理・移動)行数」を上回った年

この「コピペ行数がリファクタリング行数を初めて上回った」という変化は、AIが普及した結果として起きた象徴的な転換点だ。コードは書かれるが、整理されない。

gitclear.comgitclear.com

セキュリティの問題も「負債」として蓄積する

セキュリティ企業のVeracodeが2025年に発表したレポートでは、AI生成コードの45%に1つ以上のOWASP Top 10セキュリティ欠陥が含まれていた。重要なのは、AIモデルが賢くなってもこの数字が改善しないとVeracodeが指摘している点だ。「もっと高性能なモデルを使えば安全になる」は成立しない。

Veracode October 2025 Update: GenAI Code Security Report |Application Security for the AI Era | Veracodeveracode.com

技術的負債はコードの複雑さだけではない。見えないセキュリティの欠陥も、3ヶ月後6ヶ月後に「負債の返済」として現れる。


「スパゲッティポイント」はいつ来るか

複数の実務的な観察から、バイブコーディングプロジェクトには「開発速度が急落する逆転点」があることがわかっている。通称「スパゲッティポイント」——コードが絡まりすぎて、新機能を追加するたびに別の機能が壊れる状態だ。

この逆転点は、多くの場合3ヶ月前後に訪れる。

Loading diagram...

最初の3ヶ月は速い。新しい機能を追加するたびに「すごく速く作れる」という体験が続く。だから「速さの逆転」に気づくのが遅れる。4ヶ月目になって「なぜか新機能を追加するたびに古い機能が壊れる」という状況になってから、初めて気づく。

バイブコードの本番化を数多く手がけた開発者の Diego Rodriguez は、自身の経験から「本番に届けるには60〜80%のコードを書き直す必要がある」と記録している。これは単なる数字の問題ではなく、技術的負債が「修正では追いつかない量」に達したときのコストを示している。

Vibe Coding: Why 90% of AI-Built Projects Never Make It to Production | Diego RodriguezVibe coding was named word of the year 2025. It's incredible for prototyping but devastating for production. Learn why 90% of vibe-coded projects fail and how to bridge the gap from AI prototype to production-ready application.diego-rodriguez.work

今詰まっている人への3つの手

もし今「新機能を追加するたびに別の機能が壊れる」状態に陥っているなら、まず何をするか。

1. 「整理整頓セッション」を一度設ける

新機能を追加する前に、「今あるコードの重複を見つけて整理して」と明示的にAIに頼むセッションを設ける。機能追加のプロンプトと同じ頻度でやるのが理想だが、まずは1回やるだけでも効果がある。

AIは言われなければリファクタリングをしない。逆に言えば、明示的に頼めばやる。

2. コンテキストファイルを作る

プロジェクトのルールをテキストファイルに書いて、AIに毎回読ませる。命名規則、フォルダ構成、「同じ処理は必ずsrc/shared/lib/に置く」というルール——これをファイルに書いておくだけで、パターン1と3の崩壊を大幅に防げる。

Claude CodeのCLAUDE.md、CursorのCursor Rulesが、このコンテキストファイルとして機能する。

3. 「なぜ壊れているか」から始める

エラーが出たとき「直して」とすぐに頼まない。「なぜこのエラーが出るか、根本原因を教えて」と聞いてから直す手順を踏む。症状だけを抑える修正が積み重なると、本当の問題がどこにあるか見えなくなる。

すでに深刻なスパゲッティポイントを超えている場合、コードを修正し続けるより「重要な機能だけに絞って作り直す」方が速いケースがある。「作り直し」は敗北ではなく、負債の精算だ。


バイブコーディングは「速い試作」であって「速い設計」ではない

技術的負債が生まれること自体は、バイブコーディングだけの問題ではない。どんな開発でも、速く作れば後で整理が必要になる。

問題は、バイブコーディングでは「整理のコスト」が通常より高くなる点だ。命名が毎セッション変わり、同じ処理が複数箇所に生まれ、テストが機能を保証していない——これらが積み重なったコードを整理するのは、最初から整理しながら作ったコードを整理するより難しい。

バイブコーディングを「速い試作ツール」として使うのは正しい選択だ。アイデアを3時間で形にして検証する。それは本物の価値がある。

ただし「速い設計ツール」ではない。プロトタイプを本番に育てるには、整理のコストが別途かかる。このコストを最初から計算に入れて使い始めると、3ヶ月後に詰まる確率は下がる。

「今の速さ」と「3ヶ月後の自分」を天秤にかけながら作る。それが今のバイブコーディングとの正直な向き合い方だ。