REST 成熟度モデル

Leonard Richardson が定義した REST API の成熟度を 4 段階で評価するモデル

API設計

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

全体像を把握するには関連書籍も有用。

関連用語