「動いてるのに壊れてる」に気づけるか。5大AIコーディングツールを全部試して見えた、バイブコーディングの落とし穴3つ
先週、バイブコーディング検定が正式にスタートしました。「AIにコードを書いてもらう」行為が、資格として認定される時代になったわけです。
バイブコーディングが「検定」になった。でも品質の話、してますか?
先週、バイブコーディング検定が正式にスタートしました。「AIにコードを書いてもらう」行為が、資格として認定される時代になったわけです。
私は正直、震えたんですよね。
嬉しかったんじゃない。怖かったんですよ。だって私、ここ半年くらい「動けばOK」で突っ走ってきた人間なので。検定があるということは、正しい使い方と間違った使い方の境界線が引かれるということ。自分のコードはどっち側なのか。急に不安になりました。
CS(カスタマーサクセス)の仕事をしながら、業務ツールをAIで作り始めたのが1年前。最初はCursor(カーソル)で補完を使うだけでした。Claude(クロード) Code(クロードコード)を併用し始めてからは開発スピードが跳ね上がったんですよね。スプレッドシート連携、Slack Bot、社内ダッシュボード。作りたかったものが次々と形になっていく感覚は最高だった。
ただし今振り返ると、品質管理は完全に後回しにしていたんですよね。
そこで今回、5大AIコーディングツールを比較してみたんです。Claude Code、Cursor、GitHub Copilot(ギットハブコパイロット)、Windsurf、Devin。この5つを横断的に使い込みながら、自分が過去に作ったコードを見直しました。結果、3つの明確な落とし穴が浮かび上がってきたんです。
概念として名付けるなら「動いているのに壊れている」症候群。テストは通る。画面も表示される。ユーザーからのクレームもない。でも中身を覗くと、セキュリティの穴が空いていたり、誰も説明できないロジックが埋まっていたりする。表面上は健康なのに、レントゲンを撮ると骨にヒビが入っている状態です。
TechRadarの2026年版バイブコーディングツール比較でも、品質とセキュリティのトレードオフが主要な論点として取り上げられていました。速さの裏側にあるリスクに、ツール評価の専門メディアも正面から向き合い始めている。
この記事では、私が実際にハマった体験をベースに、3つの落とし穴とその対処法を共有します。最後にはVibeContractという新しいアプローチも紹介します。検定を受ける予定の人も、「とりあえず動くもの作りたい」段階の人も、ぜひ読んでみてください。

落とし穴1: セキュリティの穴が「見えない」
最初の落とし穴は、AIが生成したコードにセキュリティ上の問題が潜んでいること。しかも、動作確認では絶対に気づけないタイプの問題です。
私の実体験を話しますね。半年前にSlack Botを作った時のことです。問い合わせ内容をデータベースに保存する機能をClaude Codeに頼んだら、きれいに動くコードが返ってきました。データは正しく保存される。検索もできる。完璧じゃんと思ったんですよ。
3ヶ月後にセキュリティに詳しい同僚が見て、一言。「これSQLインジェクション(悪意のあるSQL文をユーザー入力に紛れ込ませる攻撃)の対策が入ってないよ」。
血の気が引きました。
# AIが生成したコード(危険な例)
# ユーザーの入力をそのままSQL文に埋め込んでいる
query = f"INSERT INTO messages (content) VALUES ('{user_input}')"
cursor.execute(query)
# 安全な書き方(パラメータバインディング)
# プレースホルダーを使えば入力値が自動でエスケープされる
query = "INSERT INTO messages (content) VALUES (%s)"
cursor.execute(query, (user_input,))
コードを読めるプロのエンジニアなら「そんなの当たり前でしょ」と言うかもしれません。わかってますよ。でもバイブコーディングの世界には、私みたいに「一度コードから離れた人間」がたくさんいるんです。パラメータバインディングという概念自体を忘れている。いや、そもそも知らなかったケースだってある。
問題の本質は「AIが危険なコードを書く」ことじゃないんです。「危険かどうかを判断する知識が、バイブコーダー側にない」こと。ここにギャップがある。
実はSQLインジェクションだけじゃありません。クロスサイトスクリプティング(XSS。Webページに悪意あるスクリプトを埋め込む攻撃)も要注意。APIキーのハードコーディングも典型的なリスクです。私のSlack Botでは、APIキーがコード内に直書きされていたことにも後から気づきました。環境変数に移すだけで済む話なのに、知らなければそのまま放置されていたでしょう。
TechRadarの比較記事によると、最新エージェント型ツールにセキュリティ警告機能が搭載され始めているとのこと。Claude CodeやCursorは生成時にリスクを警告する機能を備えつつある。ただし全ツールが同じレベルで対応しているわけではないのが現状です。

対処法: 生成と確認を「別セッション」にする
ハマりポイントを先に言っときますね。AIに「このコードのセキュリティチェックして」と同じ会話で頼んでも、効果が薄いんです。なぜなら、AIは自分が書いたコードを「意図通りのもの」として扱う傾向があるから。自分の作品を自分で採点するようなもので、甘くなりがち。
私がやっている方法はこうです。コードを生成した後、別のセッションを立ち上げて「このコードのセキュリティリスクを攻撃者の視点で3つ指摘して」と依頼する。コンテキストを切り離すだけで、驚くほど厳しい指摘が返ってきます。
Claude Codeなら /clear でリセット。Cursorなら新しいComposerウィンドウを開く。GitHub Copilotなら別のチャットパネル。どのツールでも実践できるテクニックです。
落とし穴2: 動くけど「なぜ動くか」説明できないコードが増殖する
2つ目の落とし穴。個人的にはこれが一番怖い。
AIが生成したコードが動く。テストも通る。でも「このロジック、なぜこう書いてあるの?」と聞かれた時に、作った本人が答えられない状態になることです。
私の場合、社内ダッシュボードで痛い目を見ました。売上データの集計ロジックをCursorに書いてもらったんですよね。それが3ヶ月後に集計ルールの変更が必要になって、完全にお手上げ。
コードは200行以上。コメントはAIが自動生成した英語のもの。関数名は process_data とか calculate_result とか汎用的なものばかり。何をどう処理しているか追跡不能でした。
CS出身だからわかるんですけどね。お客さんがツールの使い方を忘れるのと同じ構造なんです。「作った時は理解していた」でも「時間が経つと別人になる」。自分が書いた(正確にはAIに書いてもらった)コードなのに、3ヶ月後の自分には読めない。
# NGパターン: AIが生成しがちな汎用的すぎるコード
# 3ヶ月後の自分に意味が伝わらない
def process_data(data):
result = [x for x in data if x['status'] == 'active']
return sum(item['amount'] for item in result)
# 改善パターン: 「何を・なぜ」を残す
# 月次売上集計: 2026年4月ルール改定で対象変更予定
def calculate_active_monthly_revenue(transactions):
# activeな取引のみ集計(解約済み・保留中は除外)
active_deals = [t for t in transactions
if t['status'] == 'active']
return sum(deal['amount'] for deal in active_deals)
これは「動いているのに壊れている」の典型例。現時点では動いている。しかし変更しようとした瞬間に、変更する方法がわからないという形で壊れる。技術的負債(コードの品質を後回しにした結果、将来のメンテナンスコストが膨らむこと)が静かに積み上がっているわけです。
ちなみにGitHub Copilotの新メトリクスAPIでは、PRのスループットやマージタイムが計測可能になっている。AIが生成したPRの採用率まで追跡できる時代です。こうした指標を使えば「説明できないコードが本番に入り込んでいないか」のモニタリングも現実味を帯びてきました。
対処法: 「3ヶ月後の自分」宛てにコメントを書く
AIにコードを生成してもらったら、自分の言葉でコメントを追加する。これだけで状況は劇的に改善します。
コツは「コードの説明」ではなく「ビジネス上の理由」を書くこと。「なぜこの処理が必要か」「いつ変更が予想されるか」「誰が使う機能か」を残す。プロのエンジニアが書くような技術コメントじゃなくていいんです。CS出身の私は、まるで引き継ぎ資料を書く感覚でコメントしています。
Claude Codeには「コメントを日本語で、ビジネスロジックの背景も含めて付けて」と指示する。Copilotならインラインチャットで「この関数の目的を日本語1行で説明して」と頼めます。ツールが変わっても、プロンプトの工夫で対応可能です。
落とし穴3: テストなしで積み上げる「砂の城」
3つ目。私が最も派手にやらかした落とし穴です。
バイブコーディングで一番気持ちいい瞬間って、機能がどんどん出来上がっていく時ですよね。「ログイン機能作って」「ダッシュボード追加して」「CSV出力もつけて」。AIに頼むたびに画面が増えていく。達成感がすごい。
でもテストを書いていない。手動で「動いた、OK」と確認して、すぐ次の機能に進む。
これ、砂の城なんですよ。土台が安定しているか確認しないまま、上に積み重ねていく。ある日、ログイン機能のバリデーションを少し修正したら、なぜかCSV出力が壊れた。原因を追うのに半日以上かかりました。

半日ですよ。機能を1つ作るのに30分しかかからないのに、デバッグには24倍の時間がかかった。「動けばOK」の精神が、結局は自分の時間を奪っていたんです。
エンジニアの世界では「テストのないコードはレガシーコード」と言われるそうです。プロのエンジニアに敵わないと思って離れた私ですが、この言葉の意味は今なら実感を持って理解できます。テストがないコードは、修正する勇気が持てないコード。触るのが怖いコードなんですよね。
対処法: 「1機能1テスト」を習慣にする
完璧なテストカバレッジ(コード全体のうちテストで検証されている割合)を目指す必要はありません。バイブコーダーにそれを求めたら、誰もコードを書かなくなる。
私のルールは「1つ機能を追加したら、最低1つテストを書いてもらう」です。
# 機能を追加する時のプロンプト例
# ポイントは「テストも一緒に」と最初から指示すること
# NG: 機能だけ依頼する
# → 「ユーザー登録機能を作って」
# OK: テスト条件まで指定して依頼する
# → 「ユーザー登録機能を作って。
# 同時にテストも書いてほしい。
# テストでは以下を確認:
# 1. 正常な登録ができること
# 2. メールアドレスが重複したらエラーになること
# 3. 必須項目が空の時エラーになること」
これだけで、砂の城がレンガの城に変わります。テストがあれば、別の機能を追加した時に「さっきまで動いていた部分が壊れていないか」を自動で検証できるから。私の半日は、たった1行のプロンプト追加で防げたんです。
Claude Codeの場合、テストの実行もターミナル上でシームレスにできるのが便利。Cursorなら「テストを実行して結果を表示して」と追加すればいい。Copilotならテストファイルを開いた状態で「Run」を押すだけ。どのツールでも、テストを書く敷居はかなり低くなっています。
VibeContract: 「契約」でバイブコーディングの品質を守る新しい考え方
ここまで読んで「3つの落とし穴はわかった。でも毎回セルフチェックするのは面倒」と思いませんでしたか。私も同じことを感じました。
そこで紹介したいのがVibeContract(バイブコントラクト)という考え方です。これは自然言語で書いた「意図」を、コードの「契約」として扱う手法。研究者コミュニティで提唱されているアプローチで、バイブコーディング特有の品質問題に正面から取り組んでいます。
仕組みは4ステップで回る。
- 自然言語で「この機能は何をすべきか」を書く(契約の作成)
- AIにコードを生成してもらう
- 生成されたコードが「契約」と整合しているかを検証する
- テストや実行時のチェックで、契約違反がないか継続的に監視する
「それって要件定義と何が違うの?」と思いますよね。私も最初はそう感じました。違いは明確です。従来の要件定義は人間が読むための文書。VibeContractはAIが検証に使うための構造化された契約。「書いてあることと、コードがやっていることの一致」を自動で確認できるのがポイントです。
実践してみた: ユーザー登録機能のVibeContract
具体的にどう使うのか。私が実際にやってみた例を紹介しますね。
まず、自然言語で契約を書く。
# vibecontract.yaml
# ユーザー登録機能の契約書(自然言語で書く)
feature: ユーザー登録
contracts:
- "メールアドレスは一意であること。重複時はエラーを返す"
- "パスワードは8文字以上。英数字混在を必須とする"
- "登録成功時にウェルカムメールを送信する"
- "SQLインジェクション対策済みのクエリのみ使用する"
- "APIキーは環境変数から取得する。コード内に直書きしない"
次にAIへの指示を出す。ここがポイント。
このvibecontract.yamlの契約に従って、
ユーザー登録機能を実装してください。
各契約に対応するテストも同時に生成してください。
契約違反がないか確認するチェック関数も含めてください。
AIが生成したコードに対して、契約ファイルと照合する。メールの一意性チェックが実装されていなければ「契約違反」として検出される仕組みです。私がSlack Botで見落としたSQLインジェクション対策も、契約に明記しておけば漏れなかった。
この方法の最大の価値は、バイブコーディングの「速さ」を殺さずに「品質」を守れること。契約を書くのに5分。でもその5分が、3ヶ月後の半日のデバッグを防いでくれる。費用対効果は明白です。
周辺の基盤も追いついてきている
嬉しいことに、VibeContractを支える技術基盤も成熟しつつあります。
Microsoft Agent FrameworkがRC1(リリース候補第1版)に到達しました。セッション管理や耐障害性のある設計パターンが組み込まれている。ClaudeとCopilotがファーストクラスプロバイダとして統合済み。エージェント側のインフラが整えば、契約検証の自動化も現実的になるはず。
GitHub Copilotの新メトリクスAPIも見逃せない。2026年2月のアップデートで、PRのスループットやマージタイム、AIが作成したPRの採用率が計測可能になっている。4月2日にはレガシーAPIが廃止され、新しいUsage Metrics APIへ完全移行。品質を「感覚」ではなく「数値」で語れる時代が本格化している証拠です。

まとめ: 「動けばOK」のその先へ
バイブコーディングの3つの落とし穴を振り返ります。
- セキュリティの穴が見えない: 生成と確認を別セッションに分離する。攻撃者視点でのレビューを依頼するのが効果的
- 動くけど説明できないコードが増える: 3ヶ月後の自分に向けて、ビジネスロジックの理由を日本語コメントで残す
- テストなしの砂の城: 1機能追加したら最低1テスト。プロンプトに「テストも一緒に」を含めるだけで劇的に変わる
そして4つ目の武器がVibeContract。自然言語で「意図」を契約として書いておく。それだけで、AIが生成するコードの品質を仕組みで守れるんです。
私は「動けばOK」が信条の人間でした。今でもその気持ちは変わっていません。完璧なコードを最初から目指すのは間違いだし、それでは何も作れなくなる。本末転倒ですよね。
ただ「動けばOK」と「品質を無視していい」は違うんだと、この半年で学びました。「動いているのに壊れている」状態を放置すると、ある日突然、自分が作ったものに裏切られます。私は3ヶ月前のダッシュボードでそれを身をもって体験しました。修正に半日かかったあの日の焦りは、今でも覚えています。
バイブコーディングが検定になったのは「AIでコードを書く行為」が社会的に認められた証拠。だからこそ、品質管理もスキルの一部として育てていきたい。
凄腕エンジニアが自分に宿る感覚は本物です。あの日、敵わないと思った技術が、AIを通じて自分の手元にある。でも宿った力を壊れないコードに変えるのは、最終的には自分の判断と習慣にかかっているんですよね。
「動けばOK」の先にある「信頼されるコード」。そこに向かって、私も一歩ずつ進んでいるところです。検定を受ける人も、まだ手を動かし始めたばかりの人も、今日紹介した対処法を試してみてほしい。
私が半日溶かした失敗を、この記事を読んでくれたあなたは3分で回避できるはずですから。「動いてるのに壊れてる」に気づけたら、もうそれは成長の証拠。一緒にやっていきましょう。

正直、一度エンジニアは諦めました。新卒で入った開発会社でバケモノみたいに優秀な人たちに囲まれて、「あ、私はこっち側じゃないな」って悟ったんです。その後はカスタマーサクセスに転向して10年。でもCursorとClaude Codeに出会って、全部変わりました。完璧なコードじゃなくていい。自分の仕事を自分で楽にするコードが書ければ、それでいいんですよ。週末はサウナで整いながら次に作るツールのこと考えてます。


