REST APIの設計原則を学び直す——URLの考え方から冪等性まで

「Webを支える技術」でRESTの設計原則を体系的に学び直した記録。リソース指向のURL設計・統一インターフェース・冪等性の考え方を実例とともに整理する。

「REST APIを設計してください」と言われたとき、自分は本当にRESTの原則を理解して設計していたか。

フロントエンドを長くやっていると、APIを「使う側」として慣れ親しんでいる。だが「作る側」として設計するとき、なぜそのURLにするか・なぜそのメソッドにするかを説明できない場面があった。「Webを支える技術」を読んで、RESTの設計原則には明確な根拠があることを改めて理解した。

RESTとは何か——アーキテクチャスタイルの話

RESTはRoy Fieldingが2000年の博士論文で定義したアーキテクチャスタイルだ。特定の技術仕様ではなく、Webがうまく機能するための設計上の制約の集合を指す。

RESTの主要な制約は以下の6つだ。

制約概要
クライアント-サーバUIとデータ処理を分離する
ステートレスサーバはクライアントのセッション状態を保持しない
キャッシュレスポンスはキャッシュ可否を示す
統一インターフェースHTTPメソッドとURIで操作を統一する
階層化システムクライアントは中間サーバの存在を意識しない
コードオンデマンド(任意)クライアントにコードを送って実行できる

この中で設計に直結するのが「ステートレス」と「統一インターフェース」だ。

ステートレスとは、各リクエストが独立して意味をなすということだ。「前のリクエストでログインしたから、次のリクエストは認証済みとして扱ってほしい」という前提を持ち込まない。認証情報はリクエストごとに含める必要があり、これがJWTやBearer Token形式の根拠になっている。

リソース指向のURL設計

RESTの中心にあるのは「リソース」の概念だ。URLはアクションではなくリソースを指す名詞であるべきという原則がある。

よくある悪い例と良い例を並べる。

# 悪い例(アクション指向)
POST /createUser
GET  /getUser?id=123
POST /deleteUser?id=123
POST /updateUserEmail

# 良い例(リソース指向)
POST   /users          → ユーザー作成
GET    /users/123      → ユーザー取得
DELETE /users/123      → ユーザー削除
PATCH  /users/123      → ユーザー更新

URLはリソースの「場所」を示し、何をするかはHTTPメソッドで表現する。この分離がRESTの統一インターフェースの意味だ。

ネストしたリソースの場合も同様に考える。

GET  /articles/123/comments       → 記事123のコメント一覧
POST /articles/123/comments       → 記事123にコメント作成
GET  /articles/123/comments/456   → 記事123のコメント456

ネストが深くなりすぎる場合(3階層以上)は、設計を見直すか、フラットなURLで代替する方が扱いやすい。

コレクションと単一リソースの使い分け

URLの複数形・単数形は一貫したルールで設計する。

/users       → コレクション(ユーザー一覧)
/users/123   → 単一リソース(特定のユーザー)

コレクションに対してはGETで一覧取得、POSTで新規作成する。単一リソースに対してはGETで取得、PUT/PATCHで更新、DELETEで削除する。この対応を統一しておくと、APIを使う側がURLのパターンを予測できる。

一覧取得のクエリパラメータについても規約を決めておく。

GET /articles?page=1&per_page=20          → ページネーション
GET /articles?tag=react&published=true    → フィルタリング
GET /articles?sort=created_at&order=desc  → ソート

クエリパラメータはリソースの絞り込みや並び替えに使い、リソースの識別にはパスパラメータを使うのが基本的な考え方だ。

冪等性と副作用の設計

冪等性の概念は設計に具体的な影響を与える。

あるAPIにリクエストを2回送ったとき、2回目が1回目と同じ結果になるなら冪等だ。PUT・GET・DELETEは冪等であるべきで、POSTは冪等でない(毎回新しいリソースが作られる)。

# 冪等な操作(何度実行しても結果が同じ)
PUT  /users/123   { "name": "Takashi" }  → 常に name が Takashi になる
DELETE /users/123                          → 常にユーザーが存在しない状態になる

# 冪等でない操作(実行回数によって結果が変わる)
POST /orders  { "item_id": 1, "quantity": 1 }  → 実行するたびに注文が1件増える

冪等性を意識した設計にすると、ネットワーク障害時のリトライが安全になる。DELETEを2回送っても1回目で削除済みなら2回目は 404 Not Found を返せばいい(最終的なリソース状態は同じ)。

冪等なPOSTを実現したい場合は、冪等キー(Idempotency Key)を使う設計がある。

POST /orders
Idempotency-Key: a1b2c3d4-e5f6-7890-abcd-ef1234567890

→ 同じキーで再送された場合、以前のレスポンスを返して新規作成しない

Stripeなどの決済APIが採用している設計パターンで、二重課金を防ぐ仕組みとして機能する。

バージョニングの考え方

APIを長期運用する場合、バージョン管理の方針は最初に決めておく必要がある。

代表的なアプローチは3種類ある。

# URLパスにバージョンを含める(最もよく見る)
/api/v1/users
/api/v2/users

# クエリパラメータで指定する
/api/users?version=1

# Accept ヘッダーで指定する(メディアタイプのバージョニング)
Accept: application/vnd.myapi.v1+json

URLパスへの埋め込みは可視性が高くて扱いやすい反面、「URLがリソースを指すべき」というREST原則からすると少し外れる。ヘッダーベースはREST的には正しいが、デバッグやキャッシュの扱いが複雑になる。実用上はURLパスへの埋め込みが選ばれることが多い。

エラーレスポンスの設計

一貫したエラーレスポンスの形式を決めることで、クライアント側の実装が楽になる。

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "入力値が不正です",
    "details": [
      {
        "field": "email",
        "message": "メールアドレスの形式が正しくありません"
      }
    ]
  }
}

HTTPステータスコードでエラーの種類を分類しつつ、ボディに機械可読なエラーコードと人間向けメッセージを含める。details でフィールドごとのエラーを返すとフロントエンドのバリデーション表示に直接使える。

RFC 7807「Problem Details for HTTP APIs」はエラーレスポンスの標準形式を定義しており、参考にする価値がある。

治験EDC連携APIで学んだこと(実務の補足)

この記事の内容を「Webを支える技術」で体系的に整理する以前に、実務でREST API設計の重要性を痛感した経験がある。

治験システムで外部EDC(Electronic Data Capture)との連携APIを設計したときのことだ。

EDCは治験データを電子的に収集・管理する専用システムで、自社システムとの間でデータをやり取りするAPIが必要になった。最初に受け取った連携仕様を見たとき、エンドポイントの命名がバラバラなことに気づいた。/getSubjectData/registVisit/subject/status/update など、動詞あり・動詞なし・フラットなURL・ネストしたURLが混在していた。

これを整理するためにRESTの原則を適用した。リソースを「被験者(subjects)」「来院記録(visit-records)」「症例報告(case-reports)」として定義し、操作はHTTPメソッドで表現するよう再設計した。POST /subjects/{id}/visit-records のように、リソースの関係性がURLの構造から読み取れる形になった。

医療データAPIで特に気をつけたのは2点だ。

冪等性については、ネットワーク障害でリクエストが届いたか不明な場合のリトライが安全かどうかを設計段階で確認した。来院記録の登録(POST)は冪等でないため、Idempotency-Keyヘッダーを導入してリトライ時の二重登録を防ぐ仕組みを入れた。

エラーレスポンスの詳細度については、EDC側のシステムが機械的にエラーを解釈してアラートを上げる仕組みがあったため、エラーコードを体系化して「どのフィールドが問題か」「どのビジネスルール違反か」を明確に返すようにした。エラーの詳細度が低いと、連携先が何が起きているのかを診断できなくなる。

「この本を読んでいれば最初からこう設計できた」と強く思った経験だ。原則を知っていれば、場当たり的な命名規則の迷いがなくなり、設計判断に根拠を持てるようになる。

まとめ

RESTの原則は「べき論」ではなく、Webが長年機能し続けてきた理由と密接に結びついた設計思想だ。

URLをリソースの識別子として使う、HTTPメソッドで操作を表現する、ステートレスに設計する——この3つだけでもきちんと守ると、APIの扱いやすさは大きく変わる。フロントエンドエンジニアがAPI設計に関わる機会が増えている今、RESTの原則を一度体系的に学び直しておくことは投資対効果が高いと感じている。