DEV Community

Cover image for API仕様をコードとして扱うとは?意味とメリット
Akira
Akira

Posted on • Originally published at apidog.com

API仕様をコードとして扱うとは?意味とメリット

API契約は、Wikiの図、前四半期にエクスポートされたPostmanコレクション、そして実装から2リリース分遅れたMarkdownドキュメントに分散しがちです。これらが食い違うと、チームは推測で実装することになります。推測はインテグレーション障害の原因になります。

今すぐApidogを試す

API仕様をコードとして扱うと、この問題を減らせます。OpenAPIファイルを1つ作成し、Gitにコミットし、通常のソースコードと同じようにレビューします。その仕様からモック、テスト、ドキュメント、SDKを生成します。仕様は「後で更新する資料」ではなく、全員が従う契約になります。

この記事では、Spec-as-Codeの考え方、OpenAPIをGit管理する理由、そして実装しやすいワークフローを説明します。

Spec-as-Codeとは何か

Spec-as-Codeとは、API定義をバージョン管理されたプレーンテキストファイルとして扱うことです。共有リンクのドキュメントやツール内のデータではなく、git diff、ブランチ、マージ、レビューができるファイルにします。

Spec-as-Code

この考え方はDocs-as-Codeに近いものです。Docs-as-Codeでは、ドキュメントをコードと同じリポジトリに置き、同じパイプラインで管理します。Spec-as-Codeでは、その対象をAPI契約に広げます。

実務では、OpenAPIドキュメント、つまりYAMLまたはJSONファイルを成果物の中心にします。

api/
  openapi.yaml
src/
  ...
Enter fullscreen mode Exit fullscreen mode

開発者が/users/{id}のレスポンスを確認したい場合は、WikiではなくOpenAPIファイルを見ます。QAはその仕様に対してテストを作ります。外部パートナーは仕様から生成されたSDKやドキュメントを使います。

つまり、1つの仕様ファイルから複数の成果物を生成します。

なぜ仕様をコードのように扱うのか

仕様をGit内のファイルにすると、ソースコードで使っているワークフローをそのまま適用できます。

1. プルリクエストで変更をレビューできる

エンドポイントの変更はPRの差分として確認できます。

たとえば、次のような変更がすぐに見えます。

 status:
   type: string
-  enum: [pending, shipped, delivered]
+  enum: [pending, shipped, delivered, canceled]
Enter fullscreen mode Exit fullscreen mode

レビュー担当者は以下を確認できます。

  • フィールドが追加・削除されたか
  • ステータスコードが変更されたか
  • レスポンス形式が後方互換性を壊していないか
  • 既存クライアントに影響があるか

破壊的変更は本番で発覚するのではなく、マージ前のPRで議論できます。これはGitネイティブAPIワークフローの中心です。

2. YAMLは差分を読みやすい

OpenAPIをYAMLで管理すると、差分が読みやすくなります。

paths:
  /orders/{orderId}:
    get:
      summary: Get an order by ID
Enter fullscreen mode Exit fullscreen mode

バイナリ形式のエクスポートや、ツール内だけで完結する変更履歴と比べると、Git上のYAMLは扱いやすいです。

Gitに仕様を置けば、以下が機能します。

  • git diff
  • git blame
  • コミット履歴
  • タグ
  • ブランチ
  • git revert

3. APIの履歴を監査できる

すべての仕様変更には、コミット、著者、タイムスタンプが付きます。

たとえば次のような運用ができます。

git tag api-v1.2.0
git checkout -b api-v2-redesign
git revert <commit>
Enter fullscreen mode Exit fullscreen mode

リリースごとに仕様へタグを付けると、過去バージョンの契約も追跡できます。タグ付けとブランチ戦略については、GitでのOpenAPIバージョン管理も参考になります。

4. 仕様を唯一の真実の情報源にできる

モック、テスト、ドキュメント、SDKを同じOpenAPIファイルから生成すれば、それぞれが別々に乖離しにくくなります。

懸念事項 ホスト型ツールでの仕様 コードとしてのAPI仕様
変更レビュー 手動、見落としやすい PR差分、レビューでブロック可能
履歴 制限されるかベンダーロックされる 完全なGitログ
ロールバック 多くの場合手動 git revert
真実の情報源 曖昧 コミットされたファイル
CI統合 後付け ネイティブ

成果物としてのOpenAPI

OpenAPIは機械可読で、モック、テスト、ドキュメント、SDK生成に広く対応しています。

以下は、リポジトリに置けるOpenAPI 3.1ファイルの最小例です。

openapi: 3.1.0
info:
  title: Orders API
  version: 1.2.0

paths:
  /orders/{orderId}:
    get:
      summary: Get an order by ID
      operationId: getOrder
      parameters:
        - name: orderId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: The requested order
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Order"
        "404":
          description: Order not found

components:
  schemas:
    Order:
      type: object
      required: [id, status, total]
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
          enum: [pending, shipped, delivered]
        total:
          type: number
          format: float
Enter fullscreen mode Exit fullscreen mode

このファイルが契約です。

たとえばOrdercurrencyを追加する場合、変更は明確です。

 required: [id, status, total]
 properties:
   total:
     type: number
     format: float
+  currency:
+    type: string
+    example: JPY
Enter fullscreen mode Exit fullscreen mode

このように、API仕様をapi/openapi.yamlなどの固定パスに置き、サービスコードの近くで管理します。

仕様から生成するもの

OpenAPIファイルを1つ管理するだけでは十分ではありません。重要なのは、その仕様から実際の成果物を生成することです。

モックを生成する

モックサーバーを仕様に合わせると、バックエンド実装前でもフロントエンドやモバイルチームが統合を開始できます。

流れは次のようになります。

  1. api/openapi.yamlを更新する
  2. モックサーバーを仕様から起動する
  3. フロントエンドがモックAPIに接続する
  4. 仕様変更時にモックも更新する

これにより、実装待ちによるブロッカーを減らせます。

契約テストを追加する

稼働中のAPIが仕様と一致しているかをCIで検証します。

確認すべき例は以下です。

  • 仕様にないフィールドを返していないか
  • 必須フィールドが欠落していないか
  • ステータスコードが仕様と一致しているか
  • レスポンスの型が一致しているか

契約テストを入れると、仕様と実装の乖離を顧客より先にビルドで検出できます。

ドキュメントを生成する

エンドポイント表を手書きするのではなく、OpenAPIから参照ドキュメントをレンダリングします。

仕様が更新されると、ドキュメントも同じ定義から更新されます。つまり、ドキュメントは「仕様を説明する別ファイル」ではなく、「仕様そのものを表示したもの」になります。

SDKを生成する

同じOpenAPIファイルから、複数言語のクライアントライブラリを生成できます。

たとえば、パートナーや社内チームに次のような型付きSDKを提供できます。

  • TypeScript
  • Python
  • Java
  • Go
  • Kotlin

仕様を更新し、SDKを再生成すれば、クライアント側も最新の契約に追従しやすくなります。

OpenAPIから生成される成果物

Apidogで仕様を唯一の真実の情報源にする

Spec-as-Codeを手作業で構築する場合、以下を組み合わせる必要があります。

  • OpenAPIエディタ
  • モックサーバー
  • ドキュメントジェネレーター
  • 契約テスト
  • Git同期
  • CI設定

Apidogは、これらを1つのワークフローにまとめます。

ApidogのSpec-Firstモードでは、OpenAPIファイルを権威ある定義として扱います。仕様に沿ってエンドポイントを設計し、モック、テスト、ドキュメントを同期させます。

Apidog Spec-First

実務で重要なのは、双方向Git同期です。

ApidogはリポジトリからOpenAPIファイルを読み込み、変更を書き戻せます。そのため、Git内のopenapi.yamlとApidog内のプロジェクトを一致させられます。

使い分けはシンプルです。

  • YAMLを直接編集したい場合: エディタでopenapi.yamlを編集する
  • 視覚的に設計したい場合: Apidog上で編集する
  • どちらの場合も: 最終的な変更はGit上の仕様に反映する

これにより、チームは視覚的なAPI設計ツールを使いながら、PRレビューとGit履歴を維持できます。仕様変更をGitHubへ同期する方法は、GitHubにOpenAPI仕様を同期する方法を参照してください。

結果として、OpenAPIファイルは唯一の真実の情報源であり続けます。視覚的なツールは仕様の上にある編集レイヤーであり、仕様そのものを置き換えるものではありません。

よくある落とし穴

Spec-as-Codeはシンプルですが、導入時によく失敗するパターンがあります。

仕様と実装が乖離する

仕様を書くだけでは不十分です。実装が仕様に一致しているかを検証しなければ、両者は徐々に乖離します。

対策は、CIに契約テストを追加することです。

PR作成
  ↓
OpenAPIのlint
  ↓
契約テスト
  ↓
マージ
Enter fullscreen mode Exit fullscreen mode

不一致があれば、顧客ではなくビルドが検出します。

生成元が複数ある

仕様を手書きするのか、コードアノテーションから生成するのかを決めてください。

混在すると、どちらが正しいのか分からなくなります。

悪い例:

コードアノテーション → OpenAPI生成
手書きOpenAPI → 別の変更
Apidog上の仕様 → さらに別の変更
Enter fullscreen mode Exit fullscreen mode

良い例:

OpenAPIファイルを唯一の真実の情報源にする
Enter fullscreen mode Exit fullscreen mode

または、

コードアノテーションを唯一の生成元にする
Enter fullscreen mode Exit fullscreen mode

どちらでも構いません。重要なのは、マスターコピーを1つにすることです。

仕様をドキュメントとしてしか使わない

読むだけの仕様はドキュメントです。

モック、テスト、SDK、ドキュメントを生成する仕様は契約です。

Spec-as-Codeの価値は、ファイルを置くことではなく、そのファイルから下流の成果物を動かすことにあります。

レビューなしでマージする

Gitに置いただけでは不十分です。レビューされない仕様変更は、ただのファイル変更です。

最低限、次のルールを設定します。

  • API仕様の変更はPR必須
  • レビュー担当者を指定する
  • 破壊的変更は明示的にコメントする
  • CIでOpenAPIの妥当性を検証する

始め方

Spec-as-Codeは一度に全部導入する必要はありません。段階的に進められます。

1. OpenAPIファイルをコミットする

まず、仕様ファイルをリポジトリに置きます。

api/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

既存の仕様がある場合は、エクスポートしてこの場所に移動します。

2. PRレビューを必須にする

仕様変更がコード変更と同じレビューゲートを通るようにします。

たとえば、ブランチ保護ルールで以下を設定します。

  • PR必須
  • 1人以上のレビュー必須
  • CI成功必須

3. 1つの成果物を生成する

最初からすべてを自動化する必要はありません。

まずは次のどちらかから始めます。

  • モック
  • ドキュメント

OpenAPIファイルを更新したら、生成物も更新されるようにします。

4. CIでOpenAPIを検証する

すべてのPRで仕様の妥当性をチェックします。

チェック対象は以下です。

  • YAML構文
  • OpenAPIスキーマの妥当性
  • 必須項目の欠落
  • 命名規則
  • 破壊的変更

5. 契約テストを追加する

最後に、稼働中のサービスが仕様と一致しているかを検証します。

これでフィードバックループが閉じます。

仕様を書く
  ↓
実装する
  ↓
CIで仕様と実装を照合する
  ↓
不一致があれば失敗する
Enter fullscreen mode Exit fullscreen mode

この状態になると、仕様は単なるドキュメントではなく、強制力のある契約になります。

Spec-as-Codeの導入は小さく始められます。まずOpenAPIファイルをGitに置き、PRでレビューし、1つの成果物を生成します。そこからモック、ドキュメント、SDK、契約テストへ広げていけば、API契約の乖離を継続的に減らせます。

視覚的な編集とGit同期を組み込みたい場合は、ApidogのSpec-Firstモードをお試しください。OpenAPIファイルを唯一の真実の情報源として維持できます。

よくある質問

「API Spec as Code」は「Docs-as-Code」と同じですか?

同じ哲学を共有していますが、対象が異なります。

Docs-as-Codeはドキュメントをバージョン管理下に置きます。Spec-as-CodeはAPI契約そのものをバージョン管理下に置きます。

ただし、コミットされたOpenAPI仕様からドキュメントを生成する場合、両者は自然に連携します。

仕様ファイルはどのフォーマットを使うべきですか?

一般的にはYAML形式のOpenAPIが扱いやすいです。

理由は次のとおりです。

  • PRで差分を読みやすい
  • 人間が編集しやすい
  • ツールが解析しやすい
  • モック、テスト、SDK生成に対応しやすい

JSONも使えますが、日常的なレビューではYAMLの方が見通しがよくなります。

仕様が実際のAPIから乖離するのをどう防ぎますか?

CIに契約テストを追加します。

稼働中のサービスをOpenAPI仕様と照合し、以下のような不一致があればビルドを失敗させます。

  • 宣言されていないフィールドを返す
  • 必須フィールドを返さない
  • 型が仕様と異なる
  • ステータスコードが仕様と異なる

このフィードバックループが、仕様を希望的なドキュメントから実行可能な契約へ変えます。

Top comments (0)