AI Coding(Vibe Coding)の体験と課題〜Cloudflare・Hono・Stripe開発から見えたもの
こんにちは、岡本です。AWSやCloudflareを活用したサーバーレスアプリケーション開発、Stripeの決済統合、ReactやHonoといった最新技術に携わる開発者として、日々新しいツールや手法を試しています。今回は、AIツール「Cursor」を活用した「Vibe Coding」の体験と課題について、Cloudflare WorkersやHono、Stripeを使ったデモアプリ開発を通して紹介します。
1. Vibe Codingとは何か
「Vibe Coding」という言葉は、AIツールを使って自然言語で指示を出し、コード生成やデバッグを自動化する開発手法を指します。実はすでにWikipedia記事も英語では作られており、Google翻訳にかけると次のように定義されています。
この概念は、 LLMに依存するコーディング手法を指し
、プログラマーは自然言語による記述を提供することで、手動で記述するのではなく、実用的なコードを生成できる。
このアプローチは、開発者が細かいコードを書く負担を軽減し、アイデアや設計に集中できる点で注目されています。
2. Cursorを使ったVibe Codingの体験から感じたこと
「AIコーディングは、AIに運転席を譲る覚悟が必要だ」という意見がありますが、やはり長年開発者をしていると、ハンドルを手放すのにはまだまだ勇気が必要です。とはいえこのまま置いていかれるのもキャリア的によくないなと思い、個人的に作ってみようと思っていたアプリ開発のハンドルを譲ってみることにしました。
アプリとしては、LINEと連携させた読書メモサービスで、LINEのチャットにメモを送信すると、それをウェブから表示・検索できるというものです。

開発期間は1日半くらいで、サブスクリプションの決済やマイページ実装まで完了しています。
長所: とにかく早く試せる・失敗できる
実際にやってみて感じた最大のメリットはこの試行回数です。「AIエージェントの肝要は試行回数を大幅に増やせること」という話を以前教えてもらったことがあるのですが、「これがそうか・・・」となりました。
というのも実はこのAIコーディング、3つくらいのアプリを同時に開始させていました。その中でビルドエラーが治らなかったり、いつまで経っても要件を満たすアプリにならないものも出てきていて、読書メモアプリが唯一課金機能実装まで走り抜けたという背景があります。この辺りは要件が複雑だったり、自分もあまりよくわかっていない技術選定を敢えて行わせてみたりしたこともあり、「AIコーディングがダメだ」というよりは「事前の要件・仕様次第でリリースすらできないことがある」という捉え方をすべきだと思います。
事前準備の内容次第で結果が変わると言うことは、1つのサービス・要件に対する開発でも敢えて3つも4つものコーディングパターンを試すことができます。MVPを志向するものから、できるだけB2Bの大口契約を目指すような要件、あるいはデザインから決めるかDBやAPIから決めるかもありそうです。このような進め方のシミュレーションにもAIは使えそうだなと感じました。
課題: みんなが知らないことは、AIも知らない
一方で「まぁそうだよね」という気持ちと、「結局この分野ではまだまだ人間優位か」と思った点はがこれです。「公式のドキュメントやGitHubのソースコードをよく読むと見つかるベストプラクティス」やほぼ間違いなく実装してくれません。人間でも難しい領域ではありますが、技術カンファレンスなどで情報収集すると、「こういうやり方をするのがよい」とアウトプットされていたり、「ここでハマるから気をつけな」のような情報を得られることがあります。ただ、それらのアウトプットを重み付けすることが難しいためか、どちらかというと初心者かよく言って中級者がやるだろうなという実装をAIは仕上げてきます。実際にみたコードなどは、後半の有料部分で紹介します。
この点については、開発者が手動でレビューし、修正を加える必要があります。そのため、運転席を譲ったとしても、やはりまだ助手席で教習車のように補助ブレーキを踏む準備はしておく必要がありそうです。
対策案: AIの協働を仕掛ける
知らないことはできないというのはもはや仕方ないことです。ただ、人間社会におけるフェイルセーフ・フールプルーフのような仕組みはできるはずです。今回試していて良かったなと思ったのは、Pull Request駆動開発によるGeminiでの検知です。GitHubのリポジトリには、Gemini Code Assistを利用した自動レビューを設定しています。そのため、AIにコードを書かせた際は、pull requestをGitHub上で開いてからマージするようにしました。その結果、脆弱性のあるコードが含まれていた場合や、「後でやる」とコメントだけ残されている実装などをGeminiがレビューで指摘してくれました。

このほかにも、Claudeを利用して事前にある程度技術的な要件を整理しておくことも効率的でした。これによって初回のAIコーディングで50%くらいまでのプロダクトが一気に出来上がります。また、作業がひと段落するたびにやり残しを整理させることで、セッションを新しくしたときにコンテキストを引き継げるようにも実装できました。

まだまだ手探りな部分のあるAIコーディングではありますが、ここまでのボリュームを2日足らずでできるとなると、「まだ早い」と様子見してる場合でもないのかもしれません。このプロダクト自体は、自分で使ってみて更新するステージですが、ある程度整えばリリースしようと思います。
[おまけ] 今回のコーディングで見かけた、気になるStripe系の実装2つ
元StripeのDevRelの視点から、「多分この実装は他のPJでも高確率でやるんじゃないかなぁ・・・」と感じたものを2つピックアップしてみました。
Stripeの商品・料金取得処理が富豪的な実装になる
指定したプランを数件返すAPIや料金表を実装する時、Stripe上にあるデータを参照するのが効率的です。ただしAIに任せたところ、次のようなコードが出てきました。
await stripe.products.list({ limit: 100 }).then(({data}) => data.filter(product => {
return product.metadata.id === targetPlanId
})
理論上確かにデータは取得できるのですが、Stripe上に商品データが101件以上あったらどうするのかが漏れていたり、パフォーマンスの悪い実装であることが一目でわかるコードです。そのため関数やコメントを手で以下のように修正し、これに該当する形へ修正させる指示が必要でした。
// 製品を検索
const {data: prices} = await stripe.prices.list({
lookup_keys: [lookupKey],
expand: ['data.product']
});
let product = prices[0].product;
if (!product) {
throw new Error('製品が見つかりません');
}
if (typeof product === 'string') {
product = await stripe.products.retrieve(product);
}
if (product.deleted) {
throw new Error('製品が見つかりません');
}
ここでのポイントは、「lookup_keysを使った検索」がさほど知られていないということです。確かにStripeのドキュメントにはあるのですが、数行のみの言及です。これを見つけられるのは、よほどStripeに精通している人か、その人に教わったことがある人しかいないでしょう。
Cloudflare Workersの特性に合わせた実装
もう1点Stripe周りで「知らないと無理じゃないか・・・?」と思ったのはWebhook系統です。Webhook APIを保護するための署名検証メソッドが、このように実装されていました。
/**
* Webhook署名を検証
*/
constructEvent(payload: string, signature: string): Promise<Stripe.Event> {
return this.client.webhooks.constructEvent(
payload,
signature,
this.config.webhookSecret
);
}
一見問題のない実装に見えるのですが、実はこれCloudflare Workersでは動かないのです。デプロイして実行させると、次のようなエラーが発生します。
{"message":"SubtleCryptoProvider cannot be used in a synchronous context."}
エラーメッセージの通りなのですが、Cloudflare Workersなどのエッジ環境で実行するには、非同期処理版のメソッドを使う必要があります。そのため本来は以下のコードにしないといけません。
/**
* Webhook署名を検証
*/
constructEvent(payload: string, signature: string): Promise<Stripe.Event> {
return this.client.webhooks.constructEventAsync(
payload,
signature,
this.config.webhookSecret
);
}
これもCloudflareのブログにさらっと紹介されているだけのTipsです。そのため、数多くのドキュメントの中に埋もれてしまったのか、AIはこの実装を提出することができませんでした。
譲るからこそ、ちゃんと見る
「運転席を譲る」ことは、「運転やそれに伴う責任も完全に任せること」ではありません。実際の車においても、所有する車で事故が起きた場合は運転者が自身でなくとも責任が多少なりと発生します。それゆえに、AIコーディングをするためには、逆説的かもしれませんが、自身が生成されたコードについて判断できるようになる必要があるでしょう。もしくはそれをリスクとして許容できる体制を作るかですね。