LESSON 30分

ストーリー

高橋アーキテクト
RESTの基本原則は分かったね。次はもう少し深く掘り下げよう

高橋アーキテクトがER図を広げた。

高橋アーキテクト
API設計の第一歩は、リソースを正しく識別することだ。データベースのテーブル設計に似ているが、同じではない
あなた
テーブルとリソースは違うんですか?
高橋アーキテクト
違う。テーブルは”データの保存方法”、リソースは”外部に公開するインターフェース”だ。内部構造をそのまま公開するのは、設計ミスの始まりだ

リソースの粒度を考える

データベースと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分