2026 年の REST: ベスト プラクティス、バージョニング、および Richardson 成熟度モデル
自らを「RESTful」と呼ぶほとんどの API は、RESTful ではありません。彼らはHTTPのようなものを使用します トランスポート、形式として JSON を選択し、そこで停止します。の リチャードソン成熟度モデル、 2008 年にレナード・リチャードソンによって導入され、マーティン・ファウラーによって広められたこの手法は、 汎用 HTTP API (レベル 0) と真の API を区別する 4 つのレベルでスケールします。 RESTful (HATEOAS のレベル 3)。
ただし、アーキテクチャの完璧主義はこのガイドの目的ではありません。目標はあなたに教えることです 次の REST API を構築します。 正しく、保守可能で、十分に文書化されている: 適切な HTTP セマンティクスを使用し、長期にわたって持続可能なバージョン管理を実装し、管理します ETag を使用して効果的にキャッシュし、OpenAPI 3.1 を使用してコントラクトを文書化します。これらは プロフェッショナルな API と消費者に問題を引き起こす API との本当の差別化要因。
何を学ぶか
- Richardson 成熟度モデルの 4 つのレベルと具体的な例
- 正しい HTTP セマンティクス: メソッド、ステータス コード、ヘッダー
- 冪等性と安全な方法: 理論的基礎と実際の応用
- バージョニング戦略: URI、ヘッダー、追加変更によるバージョニング
- ETag と条件付きリクエストによる効率的なキャッシュ
- OpenAPI 3.1: ドキュメントの構造とベスト プラクティス
リチャードソン成熟度モデル: 4 つのレベル
Richardson 成熟度モデルは、API の「RESTfulness」をスケールで測定します。 0 ~ 3。これらのレベルを理解すると、アーキテクチャ上のギャップを特定するのに役立ちます 既存の API に組み込み、適切なレベルで新しい API を構築します。
レベル 0: トランスポートとしての HTTP (トンネリング)
// Livello 0: tutto su un unico endpoint, azione nel body
POST /api
Content-Type: application/json
{
"action": "getUser",
"id": 123
}
POST /api
{
"action": "createUser",
"name": "Federico",
"email": "federico@example.com"
}
// HTTP e solo un canale: la semantica e tutta nell'applicazione
// Nessun caching possibile, nessuna semantica uniforme
レベル 1: リソース (意味のある URI)
// Livello 1: URL per risorse, ma ancora solo POST
POST /users/123 // Non ha senso: POST per leggere?
POST /users/create
POST /users/delete/123
POST /users/get/all
// Migliore, ma i verbi HTTP non sono usati semanticamente
レベル 2: HTTP 動詞 (標準レベル)
// Livello 2: URL meaningful + verbi HTTP corretti + status codes
GET /users -> 200 OK con lista
GET /users/123 -> 200 OK con utente, 404 Not Found
POST /users -> 201 Created con Location header
PUT /users/123 -> 200 OK aggiornato, 404 Not Found
PATCH /users/123 -> 200 OK parzialmente aggiornato
DELETE /users/123 -> 204 No Content, 404 Not Found
// Questo e il livello che la maggior parte delle API raggiunge
// ed e generalmente sufficiente per la produzione
レベル 3: HATEOAS (アプリケーション状態のエンジンとしてのハイパーメディア)
// Livello 3: ogni risposta contiene link alle azioni disponibili
GET /users/123
-> 200 OK
{
"id": 123,
"name": "Federico",
"email": "federico@example.com",
"status": "active",
"_links": {
"self": { "href": "/users/123" },
"orders": { "href": "/users/123/orders" },
"deactivate": { "href": "/users/123/deactivate", "method": "POST" },
"update": { "href": "/users/123", "method": "PUT" }
}
}
// Il client non deve "sapere" a priori gli URL: li scopre dalle risposte
// Permette di cambiare URL senza rompere i client (in teoria)
ハテオアス: それは価値がありますか?
HATEOAS は理論的にはエレガントですが、実際に実装されることはほとんどありません。理由:
- 応答サイズが大幅に増加する
- ただし、クライアントはパフォーマンスのために URL を「ハードコーディング」することがよくあります。
- リンクを移動するには特定のツールが必要です
- ほとんどのチームは代わりに OpenAPI をコントラクトとして使用します
レベル 2 + OpenAPI 3.1、および 2026 年のほとんどの API にとって実用的なスイート スポット。 HATEOAS は、主に URL の安定性が長期にわたるパブリック API で有効です 用語と批判。
正しいHTTPセマンティクス
HTTP 動詞を正しいセマンティクスで使用することは、見た目の問題だけではなく、影響を及ぼします。 キャッシュ、冪等性、クライアントがリクエストを安全に取り消す機能。
// Proprietà dei metodi HTTP
Metodo | Safe | Idempotente | Body richiesta | Uso corretto
--------|------|-------------|----------------|----------------------------------
GET | SI | SI | No | Lettura, query, ricerca
HEAD | SI | SI | No | Verifica esistenza, metadata
OPTIONS | SI | SI | No | CORS preflight, capabilities
POST | NO | NO | SI | Creazione, azioni non-idempotenti
PUT | NO | SI | SI | Sostituzione completa di risorsa
PATCH | NO | NO* | SI | Modifica parziale
DELETE | NO | SI | Opzionale | Eliminazione
// *PATCH puo essere reso idempotente con patch semantics JSON Patch (RFC 6902)
安全 これは、リクエストにサーバー側の副作用がないことを意味します。 (サーバーは状態を変更しません)。クライアントは、GET で「F5 キーを押しても」影響はありません。
べき等 複数の同一のリクエストが同じものを生成することを意味します 単一のリクエストの結果。再試行が重要: DELETE 中にネットワークがダウンした場合、 クライアントは複数回削除することを恐れることなく、再試行できます。
ステータス コード: 正しいものを使用する
の虐待 200 OK すべて (本体エラーを含む) とアンチパターンの 1 つについて
より一般的です。正しいコードを使用すると、クライアント、プロキシ、および監視ツールで次のことが可能になります。
答えを正しく解釈してください:
// Status codes piu importanti con esempi di uso corretto
// 2xx: Success
200 OK - GET, PUT, PATCH con risorsa nel body
201 Created - POST che crea una risorsa (+ Location header)
202 Accepted - Operazione asincrona accettata (non ancora completata)
204 No Content - DELETE, PUT/PATCH senza body di risposta
// 3xx: Redirection
301 Moved Permanently - Redirect permanente (aggiornare i bookmark)
302 Found - Redirect temporaneo
304 Not Modified - ETag/If-None-Match: risorsa non cambiata, usa la cache
// 4xx: Client Error (il client ha sbagliato)
400 Bad Request - Input malformato, schema validation fallita
401 Unauthorized - Non autenticato (serve login)
403 Forbidden - Autenticato ma non autorizzato
404 Not Found - Risorsa non trovata
405 Method Not Allowed - Metodo HTTP non supportato su questo endpoint
409 Conflict - Conflitto di stato (es: email gia esistente)
410 Gone - Risorsa eliminata permanentemente (vs 404)
422 Unprocessable Entity - Sintassi ok ma semantica invalida
429 Too Many Requests - Rate limit raggiunto (+ Retry-After header)
// 5xx: Server Error (colpa del server)
500 Internal Server Error - Errore generico non gestito
502 Bad Gateway - Errore dal backend upstream
503 Service Unavailable - Server temporaneamente non disponibile
504 Gateway Timeout - Timeout dal backend upstream
PUT と PATCH: 重要な違い
PUT と PATCH の混同はよくありますが、具体的な意味があります。
// PUT: sostituzione COMPLETA della risorsa (idempotente)
// Se ometti un campo, viene azzerato!
PUT /users/123
{
"name": "Federico Calo",
"email": "federico@example.com"
// Se il campo "phone" non e incluso, viene rimosso!
}
// PATCH: modifica PARZIALE (solo i campi specificati)
PATCH /users/123
{
"name": "Federico Calo"
// Solo name viene aggiornato, email e phone rimangono invariati
}
// PATCH con JSON Patch (RFC 6902): piu preciso e idempotente
PATCH /users/123
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/name", "value": "Federico Calo" },
{ "op": "add", "path": "/phone", "value": "+39 333 1234567" },
{ "op": "remove", "path": "/tempNote" }
]
バージョン管理戦略
バージョン管理は、パブリック API の設計において最も重要な決定事項の 1 つです。一度 クライアントが API に依存しているため、コントラクトを変更するとアプリケーションが壊れてしまいます。ル 主な戦略にはさまざまなトレードオフがあります。
1. URI のバージョン管理 (最も一般的)
GET /api/v1/users // Versione 1
GET /api/v2/users // Versione 2 con campi aggiuntivi
// Vantaggi:
// - Visibile e ovvio
// - Cacheable a livello HTTP (l'URL e diverso)
// - Facile da esplorare con il browser
// - Semplice da loggare e monitorare
// Svantaggi:
// - "Sporco" semanticamente (la versione non e parte della risorsa)
// - Proliferazione di URL nel tempo
2. ヘッダーのバージョン管理
GET /api/users
Accept: application/vnd.myapi.v2+json
// oppure
API-Version: 2
// Vantaggi:
// - URL "puliti"
// - Piu vicino alla semantica HTTP originale
// Svantaggi:
// - Non cacheable con HTTP standard (Cache-Vary header necessario)
// - Invisibile dalla URL (difficile da debuggare)
// - Meno intuitivo per i nuovi consumatori dell'API
3. 追加的な変更によるバージョン管理 (最良)
// Strategia: non cambiare mai, solo aggiungere (non rompere mai i client)
// V1 risposta:
GET /api/users/123
{
"id": 123,
"name": "Federico",
"email": "federico@example.com"
}
// Aggiungi campi senza versione (i client vecchi ignorano i nuovi campi):
GET /api/users/123
{
"id": 123,
"name": "Federico",
"email": "federico@example.com",
"createdAt": "2025-01-15T10:30:00Z", // AGGIUNTO: non rompe i client vecchi
"avatarUrl": null // AGGIUNTO: nullable per retrocompat
}
// Quando DEVI rompere (rare):
// - Rimuovere un campo -> versione nuova
// - Cambiare tipo di un campo -> versione nuova
// - Cambiare semantica di un campo -> versione nuova
ETag と条件付きリクエスト
L'Eタグ (エンティティ タグ) とキャッシュを管理するための HTTP メカニズム 楽観的な競争。各リソースには、そのバージョンを識別するハッシュまたはタイムスタンプがあります。 現在:
// Server: risposta con ETag
GET /users/123
->
200 OK
ETag: "abc123def456"
Cache-Control: max-age=300
{
"id": 123,
"name": "Federico",
"version": 3
}
// Client: richiesta condizionale con If-None-Match
GET /users/123
If-None-Match: "abc123def456"
->
304 Not Modified // Risorsa non cambiata, usa la cache!
// Nessun body = traffico ridotto
// Se la risorsa e cambiata:
GET /users/123
If-None-Match: "abc123def456"
->
200 OK
ETag: "xyz789new123" // Nuovo ETag
{ /* dati aggiornati */ }
// ETag per concorrenza ottimistica (prevenire aggiornamenti in conflitto):
PUT /users/123
If-Match: "abc123def456" // "Aggiorna SOLO se la versione e ancora questa"
{...}
->
200 OK // Aggiornamento riuscito, nessun conflitto
// oppure
412 Precondition Failed // Qualcun altro ha modificato la risorsa!
// Il client deve rileggere prima di riaggiornare
OpenAPI 3.1 を使用したドキュメント作成
OpenAPI 3.1 は、REST API を文書化するための業界標準です。素晴らしい OpenAPI ドキュメント 書面による契約は正式な契約として機能し、クライアント SDK の生成と権限を有効にします。 Swagger UI または Redoc を使用した対話型ドキュメント:
// openapi.yaml - Struttura base di un documento OpenAPI 3.1
openapi: 3.1.0
info:
title: User Management API
version: 1.2.0
description: |
API per la gestione degli utenti dell'applicazione.
## Autenticazione
Usa Bearer token JWT nell'header Authorization.
contact:
name: API Support
email: api@example.com
license:
name: MIT
servers:
- url: https://api.example.com/v1
description: Production
- url: https://staging-api.example.com/v1
description: Staging
paths:
/users:
get:
operationId: listUsers
summary: Lista utenti
tags: [Users]
parameters:
- name: page
in: query
schema: { type: integer, minimum: 1, default: 1 }
- name: limit
in: query
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
- name: search
in: query
schema: { type: string }
responses:
'200':
description: Lista utenti paginata
content:
application/json:
schema:
$ref: '#/components/schemas/UserListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
post:
operationId: createUser
summary: Crea utente
tags: [Users]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
description: Utente creato
headers:
Location:
schema: { type: string }
description: URL del nuovo utente
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
$ref: '#/components/responses/BadRequest'
'409':
description: Email gia esistente
components:
schemas:
User:
type: object
required: [id, name, email, createdAt]
properties:
id: { type: integer, format: int64, readOnly: true }
name: { type: string, minLength: 1, maxLength: 100 }
email: { type: string, format: email }
createdAt: { type: string, format: date-time, readOnly: true }
CreateUserRequest:
type: object
required: [name, email, password]
properties:
name: { type: string, minLength: 1, maxLength: 100 }
email: { type: string, format: email }
password: { type: string, minLength: 8, writeOnly: true }
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
security:
- bearerAuth: []
エラー応答のパターン
エラー応答の一貫した構造により、開発者のパフォーマンスが大幅に向上します API コンシューマー エクスペリエンス。標準 RFC 9457 (問題の詳細) そして 2026 年には次のような選択肢が選ばれるようになりました。
// RFC 9457 Problem Details for HTTP APIs
// Content-Type: application/problem+json
// 400 Bad Request
{
"type": "https://example.com/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "The request body contains invalid data",
"instance": "/api/users",
"errors": [
{
"field": "email",
"message": "Invalid email format",
"value": "not-an-email"
},
{
"field": "password",
"message": "Password must be at least 8 characters",
"value": null
}
]
}
// 409 Conflict
{
"type": "https://example.com/errors/duplicate-email",
"title": "Duplicate Email",
"status": 409,
"detail": "An account with this email already exists",
"instance": "/api/users",
"email": "federico@example.com"
}
// 429 Too Many Requests
{
"type": "https://example.com/errors/rate-limited",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "Too many requests. Retry after 60 seconds.",
"retryAfter": 60
}
結論と次のステップ
2026 年のプロフェッショナル REST API は、Richardson 成熟度モデルのレベル 2 で動作します (リソース + 正しい HTTP 動詞 + 適切なステータス コード)、キャッシュとオプティミスティック同時実行に ETag を使用します。 追加的な変更に基づいて持続可能なバージョン管理を採用し、正式な契約を文書化します。 OpenAPI 3.1。ほとんどの状況では、HATEOAS レベル 3 に到達する必要はありません。
次の記事で考察します GraphQL の詳細: システムの仕組み N+1 問題は最も一般的なアーキテクチャ上のリスクであるため、リゾルバーの データベースクエリのバッチ処理を解決します。
シリーズ: API 設計 — REST、GraphQL、gRPC、tRPC の比較
- 記事 1: 2026 年の API の展望 — 意思決定マトリックス
- 第 2 条 (本): 2026 年の REST — ベスト プラクティス、バージョニング、Richardson 成熟度モデル
- 記事 3: GraphQL — クエリ言語、リゾルバー、および N+1 問題
- 第 4 条: GraphQL フェデレーション — スーパーグラフ、サブグラフ、および Apollo ルーター
- 第 5 条: gRPC — Protobuf、パフォーマンス、およびサービス間通信
- 第 6 条: tRPC — コード生成を必要としないエンドツーエンドのタイプセーフティ
- 第 7 条: Webhook — パターン、セキュリティ、および再試行ロジック
- 第 8 条: API のバージョン管理 — URI、ヘッダー、非推奨ポリシー
- 第 9 条: レート制限とスロットリング — アルゴリズムと実装
- 第 10 条: ハイブリッド API アーキテクチャ — 2026 年の REST + tRPC + gRPC







