要点
URLバージョニング(/v1/pets)は、ほとんどのチームにとって最も実用的なAPIバージョニング戦略です。視認性が高く、キャッシュ可能で、テストも簡単です。ヘッダーバージョニングとコンテンツネゴシエーションは、より「純粋な」RESTではありますが、複雑さを増します。Modern PetstoreAPIは、セマンティックバージョニングと明確な非推奨ポリシーを持つURLバージョニングを使用しています。
はじめに
あなたのAPIに破壊的変更が必要です。/petsのレスポンス形式を、単なる配列からページネーションメタデータを含むラップされたオブジェクトに変更するからです。既存のクライアントは機能しなくなります。どうしますか?
APIバージョニングが必要です。しかし、どの戦略を選びますか?URLバージョニング(/v1/pets vs /v2/pets)?ヘッダーバージョニング(Accept: application/vnd.petstore.v1+json)?それともコンテンツネゴシエーション?それぞれの方法には熱心な支持者と強い意見があります。
結論から言うと、URLバージョニングがほとんどのチームにとって最適です。実用的で、視認性が高く、すべてのHTTPツールで機能します。ヘッダーバージョニングとコンテンツネゴシエーションは理論的にはよりクリーンですが、ほとんどのチームには不要な複雑さを加えます。
Modern PetstoreAPIは、セマンティックバージョニングと明確な非推奨ポリシーを持つURLバージョニングを使用しています。現在のバージョンはv1で、v2は将来の破壊的変更のために計画されています。
このガイドでは、主要な3つのバージョニング戦略、それぞれのトレードオフ、そしてModern PetstoreAPIを参考にバージョニングを正しく実装する方法を学びます。
APIにバージョニングが必要な理由
APIは進化します。機能を追加し、バグを修正し、設計を改善します。これらの変更が既存のクライアントを破壊することがあります。
破壊的変更
既存のクライアントを破壊する変更点:
1. フィールドの削除:
// v1
{"id": "123", "name": "Fluffy", "age": 3}
// v2 (破壊的変更: ageフィールドが削除された)
{"id": "123", "name": "Fluffy"}
2. フィールドの型の変更:
// v1
{"price": "19.99"}
// v2 (破壊的変更: 文字列から数値へ)
{"price": 19.99}
3. レスポンス構造の変更:
// v1 (単純な配列)
[{"id": "123"}]
// v2 (破壊的変更: ラップされたオブジェクト)
{"data": [{"id": "123"}], "pagination": {...}}
4. URL構造の変更:
// v1
GET /pet/123
// v2 (破壊的変更: 複数形)
GET /pets/123
5. 認証方法の変更:
// v1: クエリパラメータにAPIキー
GET /pets?api_key=xxx
// v2 (破壊的変更: Bearerトークン)
GET /pets
Authorization: Bearer xxx
非破壊的変更
クライアントを破壊しない変更点:
- 新しいエンドポイントの追加
- リクエストへのオプションフィールドの追加
- レスポンスへの新しいフィールドの追加(クライアントは不明なフィールドを無視すべきです)
- 新しいクエリパラメータの追加
- 既存のリソースへの新しいHTTPメソッドの追加
バージョニングの決定
破壊的変更が必要な場合、2つの選択肢があります:
1. すべてのクライアントにアップグレードを強制する - シンプルですが、既存の統合を破壊します
2. 複数のバージョンをサポートする - 手間はかかりますが、後方互換性を維持します
ほとんどの公開APIはオプション2を選択します。バージョニングにより、APIを進化させつつ、クライアントに移行の時間を与えることができます。
URLバージョニング
URLバージョニングは、バージョン番号をURLパスに含めます。
仕組み
GET /v1/pets
GET /v2/pets
バージョンはリソース識別子の一部です。異なるバージョンは異なるリソースです。
利点
1. 視認性が高く、明示的
バージョンはURL内にあります。ログ、ブラウザ履歴、ドキュメントで確認できます。覚えておくべき隠れたヘッダーはありません。
2. テストしやすい
curl https://petstoreapi.com/v1/pets
curl https://petstoreapi.com/v2/pets
シンプルなHTTPリクエストで両方のバージョンをテストできます。
3. すべてのHTTPツールで機能する
ブラウザ、キャッシュ、プロキシ、ロードバランサーは異なるURLとして認識します。各バージョンを独立してルーティング、キャッシュ、ログ記録できます。
4. クライアントにとってシンプル
クライアントはURLを変更するだけです。カスタムヘッダーやコンテンツネゴシエーションロジックは不要です。
5. 廃止しやすい
/v1エンドポイントを削除しても/v2には影響しません。
欠点
1. 「純粋な」RESTではない
RESTの純粋主義者は、/v1/pets/123と/v2/pets/123は同じリソースであるため、同じURLを持つべきだと主張します。バージョンはヘッダーまたはコンテンツネゴシエーションで指定すべきだと考えます。
2. URLの汚染
APIには複数のURL空間が存在します:/v1/*、/v2/*など。
3. 個々のリソースをバージョニングするのが難しい
1つのエンドポイントだけをバージョニングしたい場合、API全体をバージョニングするか、一貫性を欠くことになります。
実装
URLにメジャーバージョンを含める:
/v1/pets
/v2/pets
マイナーバージョンを含めない:
❌ /v1.2/pets (細かすぎる)
✅ /v1/pets (メジャーバージョンのみ)
内部的にセマンティックバージョニングを使用する:
- v1.0.0 - 初回リリース
- v1.1.0 - 新しいフィールドを追加(非破壊的)
- v1.2.0 - 新しいエンドポイントを追加(非破壊的)
- v2.0.0 - 破壊的変更(新しいURL: /v2)
Modern PetstoreAPIは、現在のバージョンとして/v1を持つURLバージョニングを使用しています。
ヘッダーバージョニング
ヘッダーバージョニングは、バージョンをカスタムHTTPヘッダーに含めます。
仕組み
GET /pets
API-Version: 1
GET /pets
API-Version: 2
URLは同じままで、ヘッダーがバージョンを指定します。
利点
1. クリーンなURL
/petsはすべてのバージョンで同じです。/v1や/v2のようなプレフィックスはありません。
2. より「RESTful」
リソース識別子(/pets/123)は変更されません。表現がヘッダーに基づいて変更されます。
3. きめ細かいバージョニング
個々のリソースをバージョニングできます:
GET /pets
API-Version: 2
GET /orders
API-Version: 1
欠点
1. 見えない
バージョンはURLにはありません。ヘッダーを確認せずにログやブラウザ履歴で確認することはできません。
2. テストが難しい
curl -H "API-Version: 1" https://petstoreapi.com/pets
curl -H "API-Version: 2" https://petstoreapi.com/pets
ヘッダーを含めるのを忘れてはなりません。
3. キャッシュの複雑さ
キャッシュはAPI-Versionヘッダーを考慮する必要があります。レスポンスにVary: API-Versionが必要です。
4. クライアントの複雑さ
クライアントはカスタムヘッダーロジックを実装する必要があります。すべてのHTTPクライアントがこれを簡単にできるわけではありません。
5. デフォルトバージョンの曖昧さ
クライアントがヘッダーを送信しない場合、どうなりますか?デフォルトを設定する必要がありますが、それは暗黙の動作を生み出します。
実装
カスタムヘッダー:
API-Version: 1
またはAcceptヘッダーを使用:
Accept: application/vnd.petstore.v1+json
Varyヘッダーを含める:
Vary: API-Version
これは、キャッシュ時にヘッダーを考慮するようキャッシュに指示します。
コンテンツネゴシエーション
コンテンツネゴシエーションは、カスタムメディアタイプとともにAcceptヘッダーを使用します。
仕組み
GET /pets
Accept: application/vnd.petstore.v1+json
GET /pets
Accept: application/vnd.petstore.v2+json
バージョンはメディアタイプの一部です。
利点
1. 最も「RESTful」
これはRESTが設計された方法です。同じリソースの異なる表現を扱います。
2. HTTP標準に従う
標準的なHTTPコンテンツネゴシエーションを使用します。
3. 複数のフォーマットをサポート
バージョンとフォーマットを同時に指定できます:
Accept: application/vnd.petstore.v1+json
Accept: application/vnd.petstore.v1+xml
欠点
1. 複雑
クライアントはメディアタイプとコンテンツネゴシエーションを理解する必要があります。
2. テストが難しい
curl -H "Accept: application/vnd.petstore.v1+json" https://petstoreapi.com/pets
3. ツールのサポートが不十分
多くのHTTPクライアントやツールは、カスタムメディアタイプをうまく扱えません。
4. キャッシュの複雑さ
キャッシュはAcceptヘッダーを考慮する必要があります。Vary: Acceptが必要です。
5. ほとんどのAPIには過剰
ほとんどのAPIは、これほどの洗練度を必要としません。
実装
ベンダー固有のメディアタイプ:
Accept: application/vnd.petstore.v1+json
レスポンス:
Content-Type: application/vnd.petstore.v1+json
Vary: Accept
Modern PetstoreAPIがバージョニングを実装する方法
Modern PetstoreAPIは、明確なポリシーを持つURLバージョニングを使用しています。
現在のバージョン: v1
https://petstoreapi.com/v1/pets
https://petstoreapi.com/v1/orders
https://petstoreapi.com/v1/users
すべてのエンドポイントは/v1の下にあります。
バージョンレスポンスヘッダー
すべてのレスポンスにはAPIバージョンが含まれています:
X-API-Version: 1.2.0
これにより、URLにはメジャーバージョンのみが表示されていても、正確なバージョン(メジャー.マイナー.パッチ)がわかります。
非推奨警告
バージョンが非推奨になった場合、レスポンスには以下が含まれます:
Deprecation: true
Sunset: Sat, 31 Dec 2026 23:59:59 GMT
Link: <https://docs.petstoreapi.com/migration/v1-to-v2>; rel="deprecation"
Deprecation- そのバージョンが非推奨であることを示すSunset- そのバージョンがいつ削除されるかを示すLink- 移行ガイド
バージョンの発見
ルートエンドポイントは利用可能なバージョンを一覧表示します:
GET https://petstoreapi.com/
{
"versions": [
{
"version": "v1",
"status": "current",
"docsUrl": "https://docs.petstoreapi.com/v1"
}
]
}
セマンティックバージョニング
Modern PetstoreAPIは内部的にセマンティックバージョニングに従います:
- メジャー(v1, v2) - 破壊的変更、新しいURL
- マイナー(v1.1, v1.2) - 新機能、後方互換性あり
- パッチ(v1.1.1, v1.1.2) - バグ修正、後方互換性あり
URLにはメジャーバージョンのみが表示されます。
ApidogでAPIバージョンをテストする
Apidogは複数のAPIバージョンをテストするのに役立ちます。
複数のバージョンをインポートする
各バージョンのOpenAPI仕様をインポートします:
petstore-v1.yaml → 環境: v1
petstore-v2.yaml → 環境: v2
すべてのバージョンに対してテストを実行する
両方のバージョンに対して実行されるテストスイートを作成します:
// v1をテスト
pm.environment.set("baseUrl", "https://petstoreapi.com/v1");
pm.sendRequest(pm.environment.get("baseUrl") + "/pets");
// v2をテスト
pm.environment.set("baseUrl", "https://petstoreapi.com/v2");
pm.sendRequest(pm.environment.get("baseUrl") + "/pets");
バージョン固有の動作を検証する
v1とv2が異なる動作をすることを確認します:
// v1は単純な配列を返す
pm.test("v1は配列を返す", function() {
pm.expect(pm.response.json()).to.be.an('array');
});
// v2はラップされたオブジェクトを返す
pm.test("v2はラップされたオブジェクトを返す", function() {
pm.expect(pm.response.json()).to.have.property('data');
pm.expect(pm.response.json()).to.have.property('pagination');
});
非推奨ヘッダーを確認する
非推奨バージョンに適切なヘッダーが含まれていることをテストします:
pm.test("非推奨バージョンにはヘッダーが含まれる", function() {
pm.response.to.have.header("Deprecation");
pm.response.to.have.header("Sunset");
});
バージョン非推奨戦略
クライアントを壊すことなく古いバージョンを非推奨にする方法。
1. 早期に非推奨をアナウンスする
クライアントに少なくとも6〜12ヶ月の猶予を与えます:
Deprecation: true
Sunset: Sat, 31 Dec 2026 23:59:59 GMT
2. 移行ガイドを提供する
すべての破壊的変更と移行方法を文書化します:
Link: <https://docs.petstoreapi.com/migration/v1-to-v2>; rel="deprecation"
3. 利用状況を監視する
どのクライアントがまだ非推奨バージョンを使用しているかを追跡します:
X-API-Version: 1.2.0
X-Client-ID: abc123
必要に応じてクライアントに直接連絡します。
4. 段階的なシャットダウン
バージョンをすぐに削除しないでください:
- 1~6ヶ月目: 非推奨をアナウンス
- 7~9ヶ月目: 非推奨ヘッダーを追加
- 10~11ヶ月目: 非推奨バージョンのレート制限を減らす
- 12ヶ月目: 非推奨バージョンを削除
5. ドキュメントを保持する
削除後も、古いバージョンのドキュメントを保持してください。クライアントがそれを参照する必要があるかもしれません。
結論
URLバージョニングは、ほとんどのチームにとって最も実用的なAPIバージョニング戦略です。視認性が高く、テストが簡単で、すべてのHTTPツールで機能します。ヘッダーバージョニングとコンテンツネゴシエーションは、より「純粋な」RESTではありますが、複雑さを増します。
Modern PetstoreAPIは、現在のバージョンとして/v1を使用するURLバージョニング、内部的なセマンティックバージョニング、および明確な非推奨ポリシーを使用しています。このアプローチは、実用性と優れたAPI設計のバランスをとっています。
Apidogを使用して、複数のAPIバージョンをテストし、バージョン固有の動作を検証し、バージョン間のスムーズな移行を確実にしてください。
よくある質問
URLバージョニングとヘッダーバージョニング、どちらを使うべきですか?
特別な理由がない限り、URLバージョニングを使用してください。よりシンプルで、視認性が高く、テストも簡単です。ヘッダーバージョニングはより「RESTful」ですが、ほとんどのチームには不要な複雑さを加えます。
同時にいくつのバージョンをサポートすべきですか?
最大2つのバージョン(現在と以前)をサポートしてください。それ以上をサポートするとメンテナンスの負担が増大します。クライアントに移行のための6〜12ヶ月の猶予を与え、その後古いバージョンを削除してください。
v0からバージョニングすべきですか、v1からですか?
v1から始めてください。v0は不安定さを意味します。APIがv1にするほど安定していないのであれば、まだ公開リリースしないでください。
すべてのエンドポイントをバージョニングする必要がありますか?
いいえ。破壊的変更を行う場合にのみバージョニングしてください。既存のエンドポイントを変更せずに新しいエンドポイントを追加する場合、新しいバージョンは必要ありません。
URLのマイナーバージョンについてはどうですか?
URLにマイナーバージョンを含めないでください。/v1を使用し、/v1.2は使用しないでください。マイナーバージョンは後方互換性があるので、クライアントはURLを変更する必要がありません。
バージョン固有のバグはどのように処理しますか?
サポートされているすべてのバージョンでバグを修正してください。v1にのみバグが存在する場合、v1で修正してください。バグ修正のためにクライアントにv2へのアップグレードを強制しないでください。
セマンティックバージョニングを使うべきですか?
はい、内部的に使用してください。メジャー.マイナー.パッチバージョンを追跡しますが、URLにはメジャーバージョンのみを公開してください。これにより、非破壊的変更に対する柔軟性が得られます。
1つのエンドポイントだけをバージョニングする必要がある場合はどうすればよいですか?
URLバージョニングの場合、API全体をバージョニングするか、一貫性を欠くことになります。これはトレードオフです。ほとんどのチームは、シンプルさのためにAPI全体をバージョニングすることを受け入れています。
