ストーリー
高橋アーキテクトがER図を広げた。
リソースの粒度を考える
データベースとAPIリソースの違い
// データベースのテーブル構造
// users テーブル
// user_profiles テーブル
// user_addresses テーブル
// 悪い例: テーブル構造をそのまま公開
GET /api/v1/users/123
GET /api/v1/user-profiles/123
GET /api/v1/user-addresses/123
// → クライアントが3回のリクエストを送る必要がある
// 良い例: ユースケースに合わせたリソース設計
GET /api/v1/users/123
// レスポンス(内部で3テーブルをJOINして返す)
{
"data": {
"id": "usr_123",
"name": "田中太郎",
"email": "tanaka@example.com",
"profile": {
"bio": "エンジニアです",
"avatarUrl": "https://example.com/avatars/123.jpg"
},
"address": {
"prefecture": "東京都",
"city": "渋谷区"
}
}
}
リソース設計の3つのアプローチ
// 1. 粗粒度リソース(Coarse-grained)
// 1回のリクエストで多くの情報を返す
GET /api/v1/users/123 // プロフィール、注文履歴、お気に入りを含む
// メリット: リクエスト回数が少ない
// デメリット: 不要なデータも含まれる(over-fetching)
// 2. 細粒度リソース(Fine-grained)
GET /api/v1/users/123
GET /api/v1/users/123/profile
GET /api/v1/users/123/orders
GET /api/v1/users/123/favorites
// メリット: 必要なデータだけ取得できる
// デメリット: リクエスト回数が多い(under-fetching)
// 3. バランス型(推奨)
GET /api/v1/users/123 // 基本情報
GET /api/v1/users/123?include=profile // プロフィール含む
GET /api/v1/users/123/orders // 注文は別リソース
// include パラメータで関連データの取得を制御
URI設計パターン
コレクションとシングルトン
// コレクションリソース(複数形)
GET /api/v1/users // 一覧取得
POST /api/v1/users // 新規作成
// シングルトンリソース(特定の1つ)
GET /api/v1/users/123 // 1件取得
PUT /api/v1/users/123 // 更新
DELETE /api/v1/users/123 // 削除
// シングルトンリソース(ユニークなもの)
GET /api/v1/users/me // 現在のユーザー
GET /api/v1/settings // アプリケーション設定
サブリソース
// 親子関係のあるリソース
GET /api/v1/users/123/orders // ユーザー123の注文一覧
GET /api/v1/users/123/orders/456 // ユーザー123の注文456
POST /api/v1/users/123/orders // ユーザー123に注文を作成
// サブリソースのサブリソース(2階層目まで)
GET /api/v1/orders/456/items // 注文456の商品一覧
// それ以上深い場合はトップレベルに昇格
GET /api/v1/order-items/789 // 注文商品を直接参照
GET /api/v1/order-items?orderId=456 // フィルタで絞り込み
アクションリソース
// リソースに対する特殊な操作(CRUDに当てはまらない場合)
// 方式1: サブリソースとしてアクションを表現
POST /api/v1/orders/456/cancel // 注文をキャンセル
POST /api/v1/users/123/activate // ユーザーをアクティベート
POST /api/v1/emails/send // メール送信
// 方式2: 状態をリソースとして扱う(より RESTful)
PATCH /api/v1/orders/456
Body: { "status": "cancelled" }
PATCH /api/v1/users/123
Body: { "status": "active" }
実践:ECサイトのリソース設計
// ECサイトのリソースマップ
// ユーザー関連
GET /api/v1/users // ユーザー一覧
GET /api/v1/users/:id // ユーザー詳細
GET /api/v1/users/me // 自分の情報
PATCH /api/v1/users/me // 自分の情報更新
// 商品関連
GET /api/v1/products // 商品一覧
GET /api/v1/products/:id // 商品詳細
GET /api/v1/products/:id/reviews // 商品レビュー
GET /api/v1/categories // カテゴリ一覧
// カート関連
GET /api/v1/cart // カート取得
POST /api/v1/cart/items // 商品をカートに追加
PATCH /api/v1/cart/items/:id // カート内商品の数量変更
DELETE /api/v1/cart/items/:id // カートから商品を削除
// 注文関連
GET /api/v1/orders // 注文一覧
POST /api/v1/orders // 注文作成(カートから)
GET /api/v1/orders/:id // 注文詳細
POST /api/v1/orders/:id/cancel // 注文キャンセル
// 検索
GET /api/v1/search?q=keyword // 横断検索
URI設計のアンチパターン
// アンチパターン1: 動詞を含む
GET /api/v1/getAllProducts // Bad
GET /api/v1/products // Good
// アンチパターン2: ファイル拡張子
GET /api/v1/users/123.json // Bad
GET /api/v1/users/123 // Good(Accept ヘッダーで制御)
// アンチパターン3: 内部実装の露出
GET /api/v1/db/users/select // Bad(SQL操作を露出)
GET /api/v1/users // Good
// アンチパターン4: 不要な階層
GET /api/v1/system/management/users/list // Bad(冗長)
GET /api/v1/users // Good
// アンチパターン5: クエリパラメータで操作を指定
GET /api/v1/users?action=delete&id=123 // Bad
DELETE /api/v1/users/123 // Good
まとめ
| ポイント | 内容 |
|---|---|
| リソース粒度 | ユースケースに合わせて設計、テーブル構造をそのまま公開しない |
| URI構造 | コレクション、シングルトン、サブリソースの3パターン |
| ネスト深度 | 2階層まで、それ以上はトップレベルに昇格 |
| アクション | POST でサブリソースとして表現、または PATCH で状態変更 |
| アンチパターン | 動詞、拡張子、内部実装の露出を避ける |
チェックリスト
- データベーステーブルとAPIリソースの違いを理解した
- リソース粒度の3つのアプローチを把握した
- URI設計パターン(コレクション、サブリソース、アクション)を理解した
- URIアンチパターンを認識できるようになった
次のステップへ
リソース設計とURI設計を学びました。
次のセクションでは、HATEOASとリチャードソン成熟度モデルを学びます。 REST APIの「成熟度」を測る指標を理解し、より高品質なAPIを目指しましょう。
推定読了時間: 30分