ひとことで言うと#
APIのエンドポイント・リクエスト・レスポンスの仕様をコードを書く前に定義し、その仕様をフロントエンド・バックエンド双方の「契約」として開発を進めるアプローチ。実装より先に合意を取ることで、チーム間の手戻りと不整合を大幅に減らす。
押さえておきたい用語#
- APIスキーマ(API Schema)
- エンドポイントのURL、HTTPメソッド、リクエスト/レスポンスの型を機械可読な形式で記述した仕様書。OpenAPI、GraphQL SDL、Protocol Buffersなどが代表的。
- コードファースト(Code-First)
- 先にコードを書き、そこから自動的にAPIドキュメントを生成するアプローチ。コントラクトファーストの対義語にあたる。
- モックサーバー(Mock Server)
- APIスキーマに基づいてダミーのレスポンスを返すサーバー。バックエンドの実装完了を待たずにフロントエンド開発を進められる。
- コード生成(Code Generation)
- APIスキーマから型定義、クライアントSDK、バリデーションコードなどを自動生成すること。openapi-generator、orvalなどのツールが使われる。
- 破壊的変更(Breaking Change)
- 既存のクライアントが動かなくなる後方互換性のないAPI変更。フィールドの削除、型の変更、必須パラメータの追加などが該当する。
コントラクトファースト設計の全体像#
こんな悩みに効く#
- フロントエンドがバックエンドの実装完了を待つ「直列開発」でスケジュールが伸びる
- APIの仕様が口頭やSlackで共有され、実装段階で認識のズレが発覚する
- レスポンスの型が想定と違い、フロント側で大量のif分岐が必要になる
- API変更のたびにフロント・バック両方のテストが壊れ、原因調査に時間がかかる
基本の使い方#
エンドポイント・リクエスト・レスポンスの仕様をOpenAPIやGraphQL SDLで定義し、フロントエンド・バックエンド双方でレビューする。
- URLパス、HTTPメソッド、ステータスコード、リクエストボディ、レスポンスボディを明記する
- 必須/任意フィールド、型制約(文字列長、数値範囲)、列挙型も定義する
- スキーマファイルはGitで管理し、PRレビューの対象にする
スキーマからモックサーバーとクライアントコードを自動生成する。
- モックサーバー: Prism(OpenAPI対応)、MSW(フロントエンドテスト用)など
- クライアント生成: openapi-generator、orval、graphql-codegenなど
- バックエンド側もスキーマからバリデーションミドルウェアを生成すると一貫性が高まる
スキーマが合意された時点で、フロントはモックサーバー、バックはスキーマ準拠でそれぞれ開発を始める。
- フロント: モックサーバーのレスポンスを使ってUI実装を進める
- バック: スキーマで定義した型・制約をそのままバリデーションに使う
- スキーマの変更が必要になったら、必ずPRを出してチームで合意してから変更する
CIパイプラインで、実装がスキーマに準拠しているか自動テストする。
- バックエンド: 実際のレスポンスがスキーマの型・制約に一致するかを検証(Schemathesis、Dredd等)
- フロントエンド: 生成された型で型チェックが通ること
- スキーマに破壊的変更がないかをCIでチェックするツール(openapi-diff等)も組み込む
具体例#
従業員50名のECプラットフォーム企業。バックエンド(Go)とフロントエンド(Next.js)で商品検索APIのリニューアルを進めていた。従来はバックエンドが先に実装し、Swagger UIでドキュメントを出してからフロントが着手する直列フローだった。
課題:
- バックエンドの実装完了までフロントが平均2週間待機していた
- 実装後にレスポンス形式の認識ズレが発覚し、直近3か月で7回の仕様修正が発生
導入: OpenAPI 3.1でスキーマを先に定義。Prismでモックサーバーを立て、orvalでTypeScriptの型とAPIクライアントを自動生成。
結果:
- フロントの待機時間: 2週間 → 0日(スキーマ合意後すぐ開発開始)
- 仕様のズレによる手戻り: 月2〜3回 → 四半期に1回
- 商品検索APIリニューアルの全体工期: 8週間 → 5週間(37%短縮)
- 型の自動生成により、フロントのAPI呼び出しコードのバグが60%減少
100名規模のHRテック企業。5つのマイクロサービス(認証・従業員管理・勤怠・給与計算・通知)がREST APIで連携していた。各サービスチームが独自にAPIを設計・変更しており、月に4〜5件のサービス間不整合が本番で発生していた。
導入:
全サービスのAPIスキーマをモノレポのschemas/ディレクトリに集約。CIでスキーマの破壊的変更を検出し、影響を受けるサービスのコントラクトテストを自動実行する仕組みを構築。
ルール:
- スキーマの変更は必ずPRで提出し、影響を受けるチームのApprovalを必須とする
- 破壊的変更はバージョニング(v1→v2)で対応し、旧バージョンは3か月の移行期間を設ける
結果:
- サービス間のAPI不整合インシデント: 月4〜5件 → 月0.3件(年間3〜4件に激減)
- 新しいサービス間連携の実装スピード: 平均5日 → 平均2日
- オンコールの「API仕様調査」にかかる時間: 月平均8時間 → 1時間
エンジニア8名のスタートアップ。フロント3名・バック3名・フルスタック2名の構成で、タスク管理SaaSを開発していた。GraphQLを採用していたが、スキーマは「バックエンドが実装しながら決める」コードファースト方式だった。
課題:
- フロントが「このフィールド欲しい」と後から依頼し、バックエンドのスキーマ変更が週に3〜4回発生
- 型の変更がフロントのクエリを壊すことが頻発(月6〜8件の型エラー)
導入: GraphQL SDLをGitで管理し、スキーマの変更はPRで合意してから実装する流れに切り替え。GraphQL Codegenでフロントの型とhooksを自動生成。
結果:
- スキーマの「後出し変更」: 週3〜4回 → 週0.5回
- フロントの型エラー: 月6〜8件 → 月1件以下
- スキーマPRのレビューで「この設計だと将来困る」という議論が生まれ、API品質が主観的に「大幅に向上」したとチーム全員が回答
やりがちな失敗パターン#
- スキーマ設計に時間をかけすぎる — 完璧なスキーマを最初から作ろうとすると着手が遅れる。まず主要エンドポイントを定義して開発を始め、詳細は反復的に詰める
- スキーマを書くが誰もレビューしない — フロント・バック双方が合意しなければ「契約」にならない。スキーマPRには両チームのApprovalを必須にする
- コード生成を使わない — スキーマを手動で型定義に転記すると、結局ズレが生じる。自動生成をCIに組み込んでこそコントラクトファーストの効果が出る
- 破壊的変更のルールがない — フィールド削除や型変更を気軽にやると、他チームのビルドが壊れる。バージョニングと移行期間のルールを最初に決めておく
まとめ#
コントラクトファースト設計は、APIスキーマを「契約」としてチームで合意してから実装を進めるアプローチである。モックサーバーとコード生成を組み合わせることで、フロントエンドとバックエンドの並行開発が可能になり、仕様のズレによる手戻りを大幅に減らせる。大事なのはスキーマを書くことではなく、スキーマをチーム間の合意形成プロセスに組み込むこと。CIでコントラクトテストを回し、破壊的変更のルールを定めることで、サービスが増えてもAPI品質を維持できる。