本文へ移動

ホーム / Web / 第4部 バックエンド

第4部 バックエンド・第9章

API の仕様書(OpenAPI)と契約

★★★ 必須7トピック・面接 5問

API の仕様書は、フロント・App・他のチームとの約束(契約)です。書き方・レビューの観点・CI で守る運用までを押さえ、仕様書が実装とずれない状態を作ります。

9.1OpenAPI の基本の形

用語★★★ 必須
ひとことで

HTTP の API の仕様を YAML・JSON で書く標準の形式。paths に操作を、components に使い回すスキーマを書き、$ref で参照する。

OpenAPI は、HTTP の API のパス・パラメータ・リクエストとレスポンスの形を YAML か JSON で書く標準の形式です(以前の名前は Swagger)。2026年時点では 3.1 系が広く使われ、2025年9月に 3.2.0 も公開されています(3.1 と互換)。1つの仕様書から、ドキュメント・型・モックなどを作れるのが一番の利点です。

1つの仕様書から、いろいろ作れるOpenAPI の仕様YAML・JSONドキュメントSwagger UI・Redocクライアントの型TypeScript などモック・検証CI で差分を検出
OpenAPI の仕様から作れるもの

最小の例

openapi: 3.1.0
info: { title: Shop API, version: 1.0.0 }
paths:
  /orders/{orderId}:
    get:
      summary: 注文を1件取得
      parameters:
        - name: orderId
          in: path
          required: true
          schema: { type: string }
      responses:
        "200":
          description: 成功
          content:
            application/json:
              schema: { $ref: "#/components/schemas/Order" }
        "404":
          $ref: "#/components/responses/NotFound"
  /orders:
    post:
      summary: 注文を作成
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: "#/components/schemas/NewOrder" }
      responses:
        "201": { description: 作成した }
components:
  schemas:
    Order:
      type: object
      required: [id, status, total]
      properties:
        id: { type: string }
        status: { type: string, enum: [pending, paid, shipped] }
        total: { type: integer, description: 税込みの金額(円) }
        note: { type: [string, "null"] }   # 3.1 は null を型で書く
    NewOrder:
      type: object
      required: [itemId, quantity]
      properties:
        itemId: { type: string }
        quantity: { type: integer, minimum: 1 }
  responses:
    NotFound:
      description: ない
      content:
        application/problem+json:
          schema: { type: object }
要素書くこと
pathsURL とメソッドごとの操作。{orderId} はパスの変数
parametersパス・クエリ・ヘッダーの値。in と required・schema
requestBody送る本文の形式とスキーマ
responsesステータスコードごとの応答。エラーも書く
components使い回す部品(schemas・responses・parameters・securitySchemes)
$ref部品を参照する。同じ形を何度も書かない

スキーマの部分は JSON Schema の書き方です。3.1 は JSON Schema(2020-12)にそろえられたので、3.0 の nullable: true は type: [string, "null"] と書きます。どの版で書くかは、使う道具の対応を見て決めます。

エラーの返し方(Problem Details)

面接ではこう答える

OpenAPI は、HTTP の API の仕様を YAML か JSON で書く標準の形式です。paths に URL とメソッドごとの操作を書き、parameters・requestBody・responses で入力と出力の形を決めます。何度も出てくるデータの形は components の schemas にまとめて、$ref で参照します。1つの仕様書からドキュメント、クライアントの型、モックサーバーを作れるので、フロントや App のチームと並行して開発しやすくなります。

ひとことで

スキーマファーストは仕様書を先に書いてから実装し、コードファーストは実装から仕様書を生成する。どちらも仕様の差分をレビューする。

仕様を先に決めるか、実装から作るかスキーマファースト・仕様書を書いてレビュー・フロント・App が並行して作れる・実装とのずれを CI で検出コードファースト・実装の型・注釈から生成・書く量が少ない・設計のレビューが後回しに
スキーマファーストとコードファーストの進め方
進め方良い点注意
スキーマファースト(仕様を先に書く)フロント・App と並行して作れる。レビューしやすい実装とずれないよう CI で検証
コードファースト(実装から生成)書く量が少ない。実装と必ず一致する設計のレビューが後回しになりがち。生成結果の差分をレビューする

どちらでも、仕様書の変更をプルリクエストでレビューすることが大事です。コードファーストなら、生成した仕様書もリポジトリに入れて差分を見られるようにします。複数のチーム・会社が使う API ほど、スキーマファーストが向いています。

面接ではこう答える

API の仕様書の作り方には2つあります。スキーマファーストは、先に OpenAPI を書いてレビューし、それに合わせて実装する方法で、フロントや App のチームがモックを使って並行して作れます。コードファーストは、実装の型や注釈から仕様書を生成する方法で、書く量が少なく実装と一致しやすいです。どちらを選んでも、仕様書の差分をプルリクエストでレビューし、CI で実装とずれていないかを確かめます。

ひとことで

仕様書のレビューは、使う人が迷わないか・あとで壊さずに変えられるかを見る。命名・エラー・ページング・必須と任意・null・後方互換が観点。

仕様書のレビューでは、「今動くか」より「使う人が迷わないか」「あとで壊さずに変えられるか」を見ます。チームで観点を決めておき、機械で見られるものはリンター(Spectral など)に任せます。

観点確かめること
命名リソースは名詞の複数形、キーの形(camelCase か snake_case)がそろっているか。略語の使い方
エラーの形すべての操作に 4xx・5xx の応答があり、形(Problem Details など)が共通か
ページング一覧に limit の上限とカーソル(next_cursor)があるか
必須と任意required が正しいか。応答の項目は「必ずある」と書いてよいか
null「項目がない」と「値が null」を区別して書いているか(3.1 は type に "null")
列挙値enum に値を足したとき、古いクライアントが壊れないか(知らない値の扱い)
型と形式日時は format: date-time(ISO 8601)、金額は整数か文字列か、ID は文字列か
後方互換項目の削除・名前の変更・必須の追加をしていないか(下の CI で自動検出)
認証と権限security が付いているか。誰が呼べる操作か説明があるか
説明と例description と example があり、単位(円・秒)が書いてあるか

レビューで一番効くのは、実際に使う側(フロント・App)の人に見てもらうことです。画面を作る人が「この画面を出すのに何回呼ぶか」を考えると、足りない項目や無駄な往復が見つかります。

面接ではこう答える

API 仕様書のレビューでは、今動くかよりも、使う人が迷わないか、あとで壊さずに変えられるかを見ます。具体的には、命名とキーの形がそろっているか、エラーの形が共通か、一覧にページングと上限があるか、必須と任意、null の扱いが正しいかを確かめます。列挙値の追加や項目の削除のような後方互換を壊す変更は、CI のツールで自動で検出します。そして必ず、使う側のフロントや App の人に見てもらいます。

ひとことで

仕様書と実装のずれ・破壊的変更を、リンター・差分の比較・応答の検証で CI に止めさせ、仕様書を唯一の情報源にする。

仕様書の変更は、CI の3つの関門を通すリンターSpectral で書き方破壊的変更oasdiff で前と比較実装との一致テストで応答を検証公開・生成ドキュメント・型
仕様書をプルリクエストで検証する流れ

仕様書が実装とずれると、誰も仕様書を信じなくなり、結局コードを読んで確かめることになります。仕様書を「信頼できる唯一の情報源」にするには、ずれを人の注意ではなく CI で止めます。

検証やり方の例止めるもの
書き方のルールSpectral などのリンターに、チームの命名・エラー形式のルールを書く命名のぶれ、説明の抜け
破壊的変更oasdiff などで main の仕様と比べる。破壊的なら PR を落とすか、承認を必須に項目の削除・型の変更・必須の追加
実装との一致テストで実際の応答を仕様のスキーマで検証する。Schemathesis などで仕様から入力を自動生成して叩く仕様にない項目・形の違う応答
生成物の差分生成した型・クライアントをコミットし、再生成して差分がないか見る仕様を変えたのに型を作り直し忘れ
# 例:破壊的変更があれば CI を失敗させる
oasdiff breaking main/openapi.yaml openapi.yaml --fail-on ERR

破壊的変更がどうしても必要なときは、バージョニングと廃止の手順に進みます。

面接ではこう答える

仕様書は、実装とずれた瞬間に誰も信じなくなるので、ずれを CI で止める運用にしています。プルリクエストでは、Spectral のようなリンターで書き方のルールを確かめ、oasdiff で main の仕様と比べて項目の削除や必須の追加といった破壊的変更を検出します。さらにテストで実際の応答を仕様のスキーマで検証し、生成した型の差分もチェックします。こうすると仕様書だけを見て開発できる状態が保てます。

ひとことで

仕様書から型・クライアント・モックサーバーを生成し、サーバーの完成を待たずにフロントや App の開発を進める。

サーバーの完成を待たずに、モックに向けて作り始めるopenapi.yaml唯一の情報源TypeScript の型フロントクライアント・SDKApp・他チームモックサーバーexample から応答画面の開発本物の API に差し替え
仕様書から生成するものと、並行開発

仕様書があると、使う側はサーバーの完成を待たずに開発を始められます。

作るもの道具の例使いどころ
TypeScript の型openapi-typescriptfetch のラッパー(openapi-fetch など)と組み合わせて型安全に呼ぶ
クライアント・フックorval、OpenAPI GeneratorTanStack Query のフックや各言語の SDK を生成
サーバーの枠組みOpenAPI Generator、各言語のライブラリスキーマファーストで、入力の検証とルーティングを生成
モックサーバーPrism、MSW(生成したハンドラー)仕様の example から応答を返す。フロントの開発・E2E

生成したコードは手で直しません。直したくなったら、仕様書か生成の設定を直します。モックは便利ですが、仕様どおりの「正常な応答」しか返さないことが多いので、エラーや遅い応答の確認は別に用意します。

API の型の共有と実行時の検証

面接ではこう答える

仕様書があると、そこから TypeScript の型やクライアント、モックサーバーを生成できます。フロントや App のチームは、サーバーの完成を待たずに、モックに向けて画面を作り始められます。生成したコードは手で直さず、直したいときは仕様書を直して作り直します。モックは正常な応答が中心なので、エラーや遅延の確認は別に用意します。

ひとことで

使う側の期待(契約)を記録し、提供する側がそれを満たすかを、本物をつながずに検証するテスト。どの変更で誰が壊れるかが分かる。

使う側が契約を書き、提供する側が検証する使う側のテスト期待するリクエストと応答契約ファイルブローカーで共有提供する側契約を流して検証作る取りに行く提供する側が変更したとき、どの使う側の契約を壊すかが CI で分かる本物の相手を立ち上げないので速い(E2E より軽い)
コンシューマー駆動の契約テストの流れ

契約テストは、API を使う側(コンシューマー)と提供する側(プロバイダー)が、お互いの期待どおりに動くかを、相手の本物を立ち上げずに確かめるテストです。代表的な道具の Pact は使う側が期待を書く方式(コンシューマー駆動)です。

仕様書の検証(前のトピック)契約テスト
確かめること実装が仕様書どおりか使う側が実際に使っている項目・形が満たされるか
誰が書く提供する側使う側が期待を書き、提供する側が検証する
分かること仕様からのずれ「この変更で、どのクライアントが壊れるか」
向いている場面公開 API・利用者が多いマイクロサービス・社内の決まった利用者

仕様書(OpenAPI)と契約テストは、どちらか一方ではなく組み合わせて使えます。仕様書は「できること全部」、契約は「実際に使われていること」を表します。

面接ではこう答える

契約テストは、API を使う側と提供する側が、お互いの期待どおりに動くかを、相手の本物を立ち上げずに確かめるテストです。Pact では、使う側がテストの中で「このリクエストにこの形の応答が来るはず」という契約を書き、提供する側はその契約を自分の実装に流して検証します。仕様書の検証が「仕様どおりか」を見るのに対して、契約テストは「実際に使われている部分が壊れないか」を見られます。

ひとことで

HTTP の API は OpenAPI、GraphQL は SDL、gRPC は .proto、非同期のメッセージは AsyncAPI で書く。データの形だけなら JSON Schema。

OpenAPI は HTTP の API 向けです。通信の方式が違えば、仕様の形式も変わります。

形式対象書くもの破壊的変更の検出の例
OpenAPIHTTP の API(REST など)パス・メソッド・パラメータ・応答oasdiff
GraphQL のスキーマ(SDL)GraphQL型・フィールド・Query・MutationGraphQL Inspector など
Protocol Buffers(.proto)gRPC・メッセージサービス・メソッド・メッセージ(番号付きのフィールド)buf breaking
AsyncAPI非同期のメッセージ(Kafka・MQTT・WebSocket など)。Kafka は、メッセージを順番に溜めて、複数の受け手が別々に読める仕組みチャンネル・送受信するメッセージAsyncAPI の比較ツール
JSON SchemaJSON のデータの形(単体)型・必須・値の範囲-(OpenAPI の中でも使われる)

どの形式でも考え方は同じで、仕様を1か所に置き、そこから型を作り、変更を CI で比べることです。.proto ではフィールドの番号を使い回さない、GraphQL ではフィールドを消す前に @deprecated を付ける、のように形式ごとの互換のルールがあります。

GraphQL・gRPC

面接ではこう答える

仕様の形式は通信の方式で使い分けます。HTTP の API は OpenAPI、GraphQL はスキーマ定義言語の SDL、gRPC は Protocol Buffers の .proto、Kafka や WebSocket のような非同期のメッセージは AsyncAPI で書きます。JSON Schema はデータの形だけを書く形式で、OpenAPI の中でも使われています。どれも仕様を1か所に置き、型を生成し、破壊的変更を CI で検出するという運用は同じです。

この章のまとめ

🖨 まとめシート(印刷・PDF)
  • OpenAPI の基本の形(paths・parameters・requestBody・responses・components・$ref)を読み書きできる
  • 仕様書をレビューし、CI で実装とのずれと破壊的変更を検出して「信頼できる唯一の情報源」にする
  • 型・クライアント・モックの生成と契約テストで、フロント・App・他チームと並行して開発する
  • OpenAPI の基本の形:HTTP の API の仕様を YAML・JSON で書く標準の形式。paths に操作を、components に使い回すスキーマを書き、$ref で参照する。
  • スキーマファーストとコードファースト:スキーマファーストは仕様書を先に書いてから実装し、コードファーストは実装から仕様書を生成する。どちらも仕様の差分をレビューする。
  • API 仕様書のレビューの観点:仕様書のレビューは、使う人が迷わないか・あとで壊さずに変えられるかを見る。命名・エラー・ページング・必須と任意・null・後方互換が観点。
  • 仕様を唯一の情報源にする(CI での検証):仕様書と実装のずれ・破壊的変更を、リンター・差分の比較・応答の検証で CI に止めさせ、仕様書を唯一の情報源にする。
  • 型・クライアントの生成とモックサーバー:仕様書から型・クライアント・モックサーバーを生成し、サーバーの完成を待たずにフロントや App の開発を進める。
  • 契約テスト(Pact など):使う側の期待(契約)を記録し、提供する側がそれを満たすかを、本物をつながずに検証するテスト。どの変更で誰が壊れるかが分かる。
  • 他の仕様の形式との違い:HTTP の API は OpenAPI、GraphQL は SDL、gRPC は .proto、非同期のメッセージは AsyncAPI で書く。データの形だけなら JSON Schema。

この章のクイズ

面接ではこう聞かれる

まず答えを見ずに声に出して答え、そのあと開いて比べる。

Q1API 仕様書(OpenAPI など)をどう運用していますか?

模範回答

仕様書を「信頼できる唯一の情報源」にすることを目標にしています。例えば、仕様書はリポジトリに置き、変更はプルリクエストでフロントや App の人にもレビューしてもらいます。

CI では、リンターで命名やエラー形式のルールを確かめ、oasdiff で main と比べて破壊的変更があれば止めます。さらにテストで実際の応答を仕様のスキーマで検証し、生成した型の差分もチェックします。こうすると、仕様書だけを見て開発でき、結合のときの手戻りが減ります。

深掘りされたら

  • スキーマファーストとコードファーストのどちらを選びますか?
  • 仕様書と実装がずれていたことに気づいたら、どちらに合わせますか?

見られているポイント仕様書を書くだけでなく、レビューと CI でずれと破壊的変更を止める仕組みを話せるか

Q2API 仕様書のレビューでは、何を見ますか?

模範回答

「使う人が迷わないか」と「あとで壊さずに変えられるか」を見ます。具体的には、命名とキーの形がそろっているか、すべての操作にエラーの応答があり形が共通か、一覧に上限とカーソルがあるか、必須と任意、null の扱いが正しいかです。

列挙値の追加や項目の削除は古いクライアントを壊すことがあるので、慎重に見ます。機械で見られるものはリンターに任せ、人は「この画面を作るのに何回呼ぶか」のような使い方の観点を見ます。そのため、使う側のフロントや App の人にレビューに入ってもらいます。

深掘りされたら

  • enum に値を足すのは破壊的変更ですか?
  • 「項目がない」と「null」はどう使い分けますか?

見られているポイント具体的な観点を挙げられるか、使う側の視点があるか

Q3スキーマファーストとコードファースト、どちらで API を作りますか?

模範回答

使う人が多い API や、フロント・App と並行して作りたいときはスキーマファーストを選びます。先に仕様書を書いてレビューし、モックを用意すれば、使う側はサーバーの完成を待たずに作れます。

一方、1つのチームの中だけで使う API で、実装の型から仕様書を生成できる環境なら、コードファーストのほうが書く量が少なく、ずれも起きにくいです。どちらでも、仕様書の差分をレビューし、CI で破壊的変更を検出することは同じように行います。

深掘りされたら

  • コードファーストで設計のレビューをどう担保しますか?

見られているポイント状況に応じた選び方と、どちらでも必要な運用を話せるか

Q4契約テストとは何ですか? E2E テストとどう違いますか?

模範回答

契約テストは、API を使う側と提供する側が、お互いの期待どおりに動くかを、相手の本物を立ち上げずに確かめるテストです。例えば Pact では、使う側が「このリクエストにはこの形の応答が来るはず」という契約を書き、提供する側はその契約を自分の実装に流して検証します。

E2E は全部のサービスを立ち上げて通しで確かめるので、遅く、どこが壊れたか分かりにくいです。契約テストはサービスごとに速く回せて、「この変更でどのクライアントが壊れるか」が分かります。サービスが増えたときに、E2E を減らしてこちらに寄せるのが一般的です。

深掘りされたら

  • OpenAPI があれば契約テストは要りませんか?

見られているポイント契約テストの仕組みと、E2E・仕様書の検証との役割の違い

Q5OpenAPI の仕様書と実装がずれていることに気づきました。どう直しますか?

模範回答

まず、どちらが正しいかを使う側と確かめます。実際にクライアントが実装の動きに頼っているなら、仕様書を実装に合わせるのが安全です。仕様書が正しく、実装がバグなら、直すことで壊れるクライアントがいないかをログや利用状況で確かめてから直します。

そのうえで、ずれが二度と起きないよう、テストで実際の応答を仕様のスキーマで検証する仕組みを CI に入れます。ずれを人の注意で防ぐのは続かないので、仕組みで止めることが大事です。

深掘りされたら

  • どの API がずれているかを、まとめて見つけるにはどうしますか?

見られているポイント使う側への影響を先に確かめる判断と、再発防止を仕組みにする考え方