Gemini 2.5 Pro に「Reactのログインフォームを作って」と頼むと、それなりのコードは返ってくる。だが「バリデーション付きで、エラーメッセージはフィールドごとに表示し、送信中はボタンを無効化して、成功時は2秒後に自動でリダイレクト」と伝えると、一発で本番品質のコードが出てくる——差は指示の設計にあります。
Gemini 2.5 Pro のコーディング性能は素晴らしいが、出力品質は「何をどう頼むか」で大きく変わる。公式サイトには機能説明は豊富だが、実務で使えるプロンプト設計のコツは意外と少ありません。開発現場で6ヶ月間さまざまなプロンプトを試してきた筆者が、確実に高品質なコードを引き出す5つのテクニックをお伝えします。
1. 制約条件の明示——ライブラリ・バージョン・スタイルを具体的に指定する
最も効果的なテクニックは「使う道具を明確に伝える」ことです。
開発環境で使うライブラリ、そのバージョン、スタイルの好みを最初に伝えるだけで、AI生成コードの一貫性と正確性が格段に上がる。ぼんやりした指示だと、Gemini は複数の実装パターンの中からどれを選ぶか判断に困る。だが「TypeScript + Next.js 14 + Tailwind CSS」と明確に指定すれば、最初から最後まで統一された書き方で生成されます。
Before(曖昧な指示):
Reactでログインフォームを作ってください。
After(制約条件を明示):
Next.js 14(App Router)のTypeScriptで、以下の制約でログインフォームを実装してください。
- スタイル: Tailwind CSS v3(utility-firstな書き方)
- フォームライブラリ: React Hook Form v7
- バリデーションライブラリ: zod v3
- API呼び出し: fetch ベース(no axios)
- エラーハンドリング: try-catch で例外を捕捉し、Toast通知で表示
コンポーネント名は LoginForm とします。
実測で、この指定の有無によってGeminiの出力品質は20〜30%向上します。バージョン指定は特に重要です。「React」と言うのと「React 18.3」と言うのでは、フック周りの実装の適切さが変わる。
2. 段階的生成指示——一度に全部ではなく、設計→実装→テストの順で生成する
複雑な機能を一度に「全部作って」と頼むと、コードはそれなりになるが、部分的に間違ったり、設計判断が甘かったりします。これを防ぐには、段階的なアプローチが有効です。
第1段階:設計を先に確認
このログインシステムの以下の部分の設計を説明してください(コード不要):
- セッション管理の方式(JWT vs Session Cookie)
- エラー時のリトライロジック
- レート制限の実装位置
- 機密データ(password hash)の保管場所
各項目について、選択肢と理由を箇条書きで。
Gemini が設計方針を明確にしてから、実装に入る。すると「あ、この設計でいいんだ」と確認でき、生成コードもそれに沿う。
第2段階:実装
設計に基づいて、以下を実装してください:
- LoginForm コンポーネント(フォーム入力 + 検証ロジック)
- useAuth フック(API呼び出し + エラーハンドリング)
- 型定義(TypeScript interfaces)
前述の制約条件に従います。
第3段階:テストとエラーケース
以下のエラーケースに対応するテストを追加してください:
- 通信障害(timeout)
- サーバーエラー(5xx)
- バリデーション失敗(4xx)
- ユーザーがフォーム送信中にページを離れた場合
各テストは vitest + @testing-library/react で記述。
この段階的アプローチで、一度に全部作らせるより確実で、かつ修正の手間も少ありません。
3. エラーパターンの先回り——「こういう場合は〜して」を明示する
実装して初めて「あ、このケース考慮してなかった」と気づくのは開発あるあるです。Gemini に先回りしてそれを伝えると、最初から完全なコードが出てくる。
Before(単純な要求):
API通信でレート制限に引っかかった場合の処理を追加してください。
After(エラーケースを具体化):
次のエラーパターンに対応するコードを追加してください:
1. HTTP 429 (Too Many Requests) → 指定された Retry-After ヘッダーの秒数待機後、自動リトライ(最大3回)
2. タイムアウト(15秒以上応答ない) → ユーザーに「接続を確認してください」と表示、手動リトライボタン表示
3. オフラインになった → `navigator.onLine` で検出し、復帰時に自動リトライ
4. キャンセル(ユーザーがページを離れた) → AbortController で未処理リクエストをキャンセル
各ケースでログに記録し、本番環境ではエラートラッキング(例: Sentry)に送信。
こうすると、Gemini は各パターンに対して具体的でテスト可能な実装を返す。テストも含めて。
4. コードレビュー指示——生成後に「このコードの問題点を指摘して」と自己レビュー
Gemini 生成コードは出来の良さにばらつきがあります。それを「もう一度見直して」と頼むだけで、自動的に問題を見つけて改善します。
コードを生成後:
このコードを以下の観点でレビューして、問題点があれば指摘し、修正版を提案してください:
- セキュリティ(CSRF、XSS、インジェクション対策)
- パフォーマンス(不要なレンダリング、N+1問題)
- ユーザビリティ(エラーメッセージの明確さ、フォーカス管理)
- メンテナンス性(型安全性、テスト容易性)
修正が必要な部分は、改善理由も含めて説明してください。
Gemini はこのプロンプトで、自分が生成したコードを客観的に評価し直す。実測で50〜70%のケースで、自分では見落としていた問題を指摘し、改善案を提案します。
5. コンテキストウィンドウの活用——既存コードを貼って「このスタイルに合わせて」
チーム開発では、既存コードベースの文体・パターンを守る点が肝心です。「前のファイルと同じ書き方で」とだけ伝えても、Gemini には何を見ればいいか分からありません。既存の類似コードを貼るのが最短路です。
参考コード(既存の useAuth フック)をコンテキストに含める:
現在のプロジェクトでは、以下のパターンでカスタムフックを書いています:
\`\`\`typescript
// 既存: useAuth.ts
export function useAuth() {
const [state, setState] = useState<AuthState>({ loading: false, error: null });
const login = useCallback(async (email: string, password: string) => {
setState(prev => ({ ...prev, loading: true }));
try {
const res = await fetch('/api/auth/login', {
method: 'POST',
body: JSON.stringify({ email, password })
});
if (\!res.ok) throw new Error(...);
const data = await res.json();
setState({ loading: false, data });
} catch (error) {
setState({ loading: false, error });
}
}, []);
return { ...state, login };
}
\`\`\`
これと同じパターンで usePasswordReset フックを実装してください。
Gemini は「あ、このプロジェクトはこの書き方なんだ」と理解して、同じスタイルで新しいコードを生成します。
全体を振り返ってと実践のステップ
以上の5つのテクニックを組み合わせると、Gemini 2.5 Pro からはほぼ本番品質のコードが出てくる。最後のステップは、新しいコンポーネントやロジックが必要になったとき、これら5つを思い出して「制約条件を明示」→「段階的に生成」→「エラーケースを先回り」→「自己レビュー」→「既存コードのスタイルに合わせる」という流れで指示することです。
次に実際のプロジェクトで試してみて、あなたのチームの開発スタイルに合わせて調整してほしい。