REST 成熟度モデル
Leonard Richardson が定義した REST API の成熟度を 4 段階で評価するモデル
REST 成熟度モデルとは
REST 成熟度モデル (Richardson Maturity Model) は、Leonard Richardson が 2008 年の QCon カンファレンスで発表した、REST API の成熟度を 4 段階 (レベル 0〜3) で評価するフレームワークである。Martin Fowler が 2010 年のブログ記事で広く紹介し、REST API の設計品質を議論する際の共通言語として定着した。
4 つのレベル
レベル 0 - The Swamp of POX
単一のエンドポイントに全操作を集約する。HTTP は単なるトランスポートとして使い、操作の種別はリクエストボディで指定する。
POST /api
{ "action": "getUser", "userId": "123" }
POST /api
{ "action": "createOrder", "items": [...] }
XML-RPC や SOAP がこのレベルに該当する。URL もHTTP メソッドも意味を持たない。
レベル 1 - Resources
操作対象をリソースとして URL で識別する。ただし HTTP メソッドは POST のみ。
POST /users/123
{ "action": "get" }
POST /orders
{ "action": "create", "items": [...] }
リソースの概念が導入されたが、HTTP メソッドの意味を活用していない。
レベル 2 - HTTP Verbs
HTTP メソッド (GET, POST, PUT, DELETE) をリソースへの操作に対応させる。ステータスコードも適切に使い分ける。現代の REST API の大半がこのレベルだ。
GET /users/123 → 200 OK
POST /orders → 201 Created
PUT /orders/456 → 200 OK
DELETE /orders/456 → 204 No Content
GET /users/999 → 404 Not Found
POST /orders (不正データ) → 400 Bad Request
レベル 3 - Hypermedia Controls (HATEOAS)
レスポンスにリンクを含め、クライアントが次に取れるアクションを動的に発見できる。
{
"orderId": "456",
"status": "pending",
"_links": {
"self": { "href": "/orders/456" },
"cancel": { "href": "/orders/456/cancel", "method": "POST" },
"payment": { "href": "/orders/456/payment", "method": "POST" }
}
}
実務ではどのレベルを目指すべきか
レベル 2 が実務上の標準だ。レベル 3 (HATEOAS) は理論的には理想だが、実装コストが高く、フロントエンドフレームワークとの相性も良くないため、完全な実装は稀である。
| レベル | 実務での採用率 | 推奨度 |
|---|---|---|
| レベル 0 | レガシーシステム | 新規開発では避ける |
| レベル 1 | 一部の内部 API | 不十分 |
| レベル 2 | 大半の REST API | 推奨 (標準) |
| レベル 3 | 少数の公開 API | 部分的に採用 |
レベル 2 を確実に実装した上で、ページネーションのリンクや状態遷移のリンクなど、レベル 3 の要素を部分的に取り入れるのが現実的なアプローチだ。
レベル 2 でよくある設計ミス
GET で副作用を起こす
// ❌ GET でデータを削除
GET /users/123/delete
// ✅ DELETE メソッドを使う
DELETE /users/123
GET はべき等 (何度呼んでも結果が同じ) であるべきだ。キャッシュやプリフェッチで意図せず実行される可能性がある。
ステータスコードの誤用
// ❌ エラーでも常に 200 を返す
HTTP 200 OK
{ "success": false, "error": "User not found" }
// ✅ 適切なステータスコードを返す
HTTP 404 Not Found
{ "error": "User not found", "code": "USER_NOT_FOUND" }
URL に動詞を含める
// ❌ URL に動詞
POST /users/123/activate
POST /orders/456/sendEmail
// ✅ リソースの状態変更として表現
PATCH /users/123 { "status": "active" }
POST /orders/456/notifications (通知をリソースとして扱う)
ただし、CRUD に収まらない操作 (パスワードリセット、バッチ処理の開始など) は動詞を含む URL が許容される場合もある。
API Gateway での実装
API Gateway + Lambda の構成では、レベル 2 の実装が自然に行える。SAM テンプレートでリソースとメソッドを定義する。
Events:
GetUser:
Type: Api
Properties:
Path: /users/{id}
Method: GET
CreateUser:
Type: Api
Properties:
Path: /users
Method: POST
全体像を把握するには関連書籍も有用。