いまさらですがGithub Copilotを使い始めたので、試しに知識のある分野でバイブコーディングしてみます。
GithubおよびVS Code上で、Spring Boot、Thymeleaf、CSSフレームワークを利用したアプリケーションを作ってみます。
本記事は、バイブコーディングした感想をつらつら書くものです。
やったこと
- VS Code上でGithub Copilotチャットを利用しながらアプリを実装
- VS Code上でGithub Copilotコード補完を利用しながらアプリを実装
- GPT4oベースのチャット
やってないこと
- Github上でのGithub Copilotエージェントを利用した自動PR
- Github上でのGithub Copilotエージェントを利用した自動レビュー
- GPT4o以外をベースとしたチャット
やってないことは、エージェントがGithub Copilot Pro以上(課金)でないと利用できなかった機能です。しばらくGithubを触ってなかったので、課金前提の機能を使うのには抵抗がありました。
ちなみに無料のGithub Copilot Freeで始めましたが、月間チャット50回しかできないため、すぐにProを使いたくなります。Proは30日間無料でトライアルできます。
記事の構成
今回の開発では、Github Copilotに与えるプロンプトで1Issueを作成し、Github Copilotの提示をレビューしつつ目的とする形にしていき1PRを作成します。1プロンプトでIssueが完了することはなく、何度もやりとりしています。
本記事では、1Issueごとに#段落で書いていきます。
プロジェクトのセットアップ
プロンプト
Spring Boot でアプリケーションの基本構造を作る。
以下の条件に合致する。
* Spring Boot 3.5.9を利用する。
* 言語にJavaを利用する。
* ビルドツールにMavenを利用する。
* Spring Bootの設定ファイルにYAMLを利用する。
* Web、Thymeleaf、MyBatis、H2への依存関係を追加する。
Spring Initializrの使い方を説明してくれました。親切です。
しかし、基本的なディレクトリ構造は以下のようになりますと説明され、思想強めな感じもしました。
- com.exapmple
- controller
- service
- repository
mvn clean spring-boot:runで起動すると当然のごとくエラーとなるので、トップページを作るよう指示して本Issueは完了です。
コード:https://github.com/yoshikawaa/ai-sample/pull/2
顧客情報の表示機能を作る
プロンプト
H2DBの顧客情報テーブルにアクセスして、情報を表示する業務を作る。
顧客情報テーブルにはMyBatisのリポジトリでアクセスし、取得した情報を画面に表示する。
顧客情報を格納するJavaエンティティのGetter、Setterを簡略化するため、Lombokを使う。
顧客情報テーブルは以下の項目を持つ。
* メールアドレス
* パスワード
* 顧客名
* 登録日
* その他必要と思われる項目
アプリケーション起動時に、H2DBの顧客情報テーブルを作成し3件のレコードを登録する。
これだけの情報でも、そこそこのものを作ってくれるのでありがたいです。
- 上記のプロンプトで私は顧客1件の情報を取得することを想定したが、全件取得・表示画面を作ってくれた。許容
- トップ画面に顧客情報を表示しようとしたので、ちゃんと独立した業務を作るよう指示した
- 上記の「その他必要と思われる項目」は提示してくれなかった
顧客情報の表示は内容的に簡単なのか、大きなトラブルもなく許容できるものが作れました。
さらにCSSフレームワークを用いてスタイリッシュなデザインにしてくださいと注文してみましたが、Bootstrap 3が提示されました。ふーん最近もBootstrapがスタイリッシュなのかーCSSの世界は進化しないなあ、、、という感想です。
コード:https://github.com/yoshikawaa/ai-sample/pull/4
顧客情報の登録機能を作る
プロンプト
顧客情報テーブルに以下のカラムを追加し、入力・表示できるようにする。
* 生年月日
* 電話番号
* 住所
H2DBの初期生成レコードについても、追加したカラムを反映する。
顧客情報の登録は、入力画面→確認画面→完了画面の順で遷移する。
入力画面で入力された顧客情報をバリデーションし、バリデーションを通過しない場合はエラーメッセージを表示する。
CSRF対策を行い、確認画面からの登録にはPRGパターンを適用する。
顧客情報はMyBatisのリポジトリを利用してH2DBの顧客情報テーブルに登録する。
登録が成功したら完了画面に遷移し、完了画面から顧客情報表示画面に遷移するボタンを用意する。
パスワードは2つの欄で入力させ、一致することをチェックする。
パスワードはSpring Bootで推奨されるエンコーダを利用してハッシュ化し、H2DBに登録する。
登録日は入力させず、システム日を設定する。
入力された生年月日から、Serviceで未成年かどうかをチェックする。未成年の場合は例外(エラー)とし、ビジネスエラー画面に遷移する。
登録業務では、いっきにやることが増えるので、Copilotも苦戦しているようでした。
業務の複雑性に起因すると思われる問題
- DBテーブルのエンティティを入力フォームに使い回そうとする
- 登録リクエスト時に入力チェックしていない
- 登録リクエスト時の入力チェックエラーで確認画面に戻ってしまい、何もできなくなる
- フォームに適切なhidden項目をセットしてくれない(サボり)
- 確認画面に確認用パスワード(再入力)も表示しようとする(無駄)
- 確認画面からBackで入力画面に戻った場合、入力値が引き継がれない
- 未成年かどうかチェックの要件を無視する
Spring FWの複雑性に起因すると思われる問題
- バリデーションは
@Validではなく、Springの@Validatedが良い - 全メソッドの引数に
@ModelAttributeでフォームを登録しようとする(冗長) -
@ModelAttributeで登録済みのフォームをロジックでも登録しようとする(無駄) -
@DateTimeFormatの不足による日付項目引き継ぎ漏れ - パスワード一致性のチェックを、コントローラのロジックで実装しようとする
- バリデーションの依存関係が足りないことに気づかない、しかも直接Hibernateに依存しようとする
- BCryptPasswordEncoderを使うのに、Spring Securityへの依存関係が足りないことに気づかない
- Spring Securityを有効化すると、要件を無視してCSRF対策を無効化しようとしてくる
- Spring Securityを有効化し、Copilotの言う通りセッティングするとエラーで無限リダイレクトループ
Spring FW起因の問題は、何回かやりとりを経てやっと正解にだどりつくことも多く、難しさを感じました。特に無限リダイレクトループはCopilotが全く原因を特定できず、開発が頓挫しそうになりました。(最終的に回避方法を教えてあげました)
コード:https://github.com/yoshikawaa/ai-sample/pull/6
認証・認可機能を作る
プロンプト
認証・認可機能を作る。
トップ画面にログインボタンを追加し、ログイン画面に遷移する。
Spring Securityの認証・認可機能を利用して、独自のログイン画面でログインする。
ログインしたら、マイページで自分の顧客情報を参照できるようにする。
マイページでは、パスワードの変更、ログアウトができるようにする。
マイページはログイン後のみ参照可能、
それ以外の画面(顧客情報一覧、入力、確認、完了画面)はログインしていなくても参照可能とする。
ここでも、Spring FWの複雑性に起因する問題が多く出ました。
- ログイン画面を独自にした場合、リクエストパスに対するコントローラが必要なことに気づかない(解決できなかった)
- ログイン画面で認証失敗時に適切にメッセージを表示しない
- ユーザ情報(UserDetails)を設計してくれない
- 画面(Thymeleaf)で直接取得すればよいユーザ情報を、コントローラでModelに登録しようとする
- 同じオブジェクトからプロパティを複数回取得するのに、th:objectを使わない
-
#authenticationを利用するため、ThymeleafのSpring Security連携する依存関係が足りないことに気づかない(しかも聞いても必要ないと言い放つ) - th:actionでCSRFトークンが自動補完されるのに、追加で送信しようとする
- inputタグに適切にth:fieldをつけない(フォームオブジェクトにバインド漏れ)
- 現在のパスワード一致性をチェックする際、Bean Validationではなくサービスでチェックしようとする
- Bean Validationのバリデータを作る際、未入力の値をチェックエラーにしようとする(標準的実装ではない)
- Bean ValidationのバリデータをSpringで使うにも関わらず、
@Component化しようとしない - Spring Securityにも関わらず、ログアウトにGETリクエストを送信しようとする
等々、Spring FWの難しさに対応しきれていない印象があります。
一方で、ここではユーザ情報の設計について、UserDetailsインターフェイス実装とUserクラス拡張のどちらを選択すべきかについて、質問したらちゃんと指針を提示してくれました。TERASOLUNAガイドラインより丁寧な説明で分かりやすかったです。
コード:https://github.com/yoshikawaa/ai-sample/pull/8
パスワード変更の機能妥当性をチェックする
プロンプト
現状のパスワード変更機能は、おかしいところがある。
これを調査して、適切な機能に修正する。
これだけのプロンプトで、Copilotは問題を発見できるのか?と雑なスタートをきってみました。結論を言うとCopilotはいろいろ提案してくれたものの、私が想定した問題は発見してくれませんでした。
以下が修正した問題です。
- 現在のパスワードと新しいパスワードが同じ場合にパスワード変更を許可してしまう
- パスワード変更後にもう一度パスワード変更しようとした場合、現在のパスワードの一致性チェックに失敗する
コード:https://github.com/yoshikawaa/ai-sample/pull/10
CSSの見直し
プロンプト
Bootstrap3のシンプルな画面に飽きてきました。HTML5 Upのようなリッチなデザインにしたいのですが、どのような提案が可能ですか?
HTML5 Upのいくつかのテンプレートを提案してくれました。その中の1つを選択し、意気揚々とThymeleafの換装に挑みました。
しかし、画面を構築する中で独自にスタイルを追加したり、HTML5 Upのmain.cssを修正する提案をしてくる場面が多く、HTML5 Upのテンプレートを使いこなせていないように感じました。また、指摘を重ねて修正させるとBootstrapに戻そうとするようなトラブルもありました。このため、HTML5 Up化は途中で挫折しました。
思うに、BootstrapのようなCSSは説明書や例が充実しており学習しやすいのに対し、HTML5 Upはデモページのみでコードとして学習する方法に乏しいからだと思います。
新たなCSSの選択
とはいえ、BootstrapからCSSは変更したいので、次のプロンプトに変更しました。
CSSフレームワークをBootstrap3からTailwindに変更したいです。
Tailwind CSSは「State of CSS 2025」で最も使われているCSSフレームワークです。
Tailwindの適用は、多少の指摘はあるものの、すべてにおいてCSSフレームワークの知識を必要とせず、スムーズに進みました。やはり上述の推測は正しかったように思います。
コード:https://github.com/yoshikawaa/ai-sample/pull/12
まとめ
今回は、Github Copilotを利用してSpring Boot、Thymeleaf、CSSフレームワークを利用したアプリケーションを作ってみました。
バイブコーディングしてみた結果としては、まだまだ介助が必要なパートナーという感じですね。
手がかかるけどそこらへんの人に任せるよりはまあいいか、という感想。
- 簡単な知識で実装できる部分を大量に実装するのは得意そうだが、その中で一貫性を保つのは苦手そう
- Spring FWを深く理解して一貫性のあるものを作るのは難しそう、とはいえ個々の知識は十分にある
- CSSフレームワークは得意そうだが、ドキュメントがしっかりしてないと学習できなさそう
- 知識を一度で出し切ることはなく、またサボり癖もあるのでレビューしながら実装させると良さそう
次回は、今回実装したアプリケーションを利用して、Github CopilotにSpring Boot Testを実装してもらおうと思います。