REST API design 面接の質問
REST API設計のインタビューでは、スケーラブルで保守可能、ユーザーフレンドリーなWeb APIを構築する能力が評価されます。これらのインタビューは、バックエンド、フルスタック、プラットフォームエンジニアリングの役割、特にシニアレベルで一般的です。面接官は、RESTの原則、リソースモデリング、エラーハンドリング、ページネーション、バージョニング、セキュリティに関する理解を評価します。概念的な議論と実践的なコーディングチャレンジの両方に直面します。
REST API design 面接で問われる内容
RESTfulな原則と制約
ステートレス性、統一インターフェース、リソース識別、HTTPメソッド(GET、POST、PUT、DELETE、PATCH)とステータスコードの適切な使用方法の理解。
リソースモデリングと命名
ネストされたリソースの直感的なURIパターン、複数形の名詞、フィルタリング、ソート、エンドポイントでの動詞の回避。
ページネーション、フィルタリングとバージョニング
カーソルベース vs オフセットページネーションの実装、フィルタリング/ソートの戦略、URL vs ヘッダーバージョニングのアプローチ。
エラーハンドリングとセキュリティ
一貫したエラーレスポンス構造の設計、HTTPステータスコードの適切な使用、認証、レート制限、入力検証などの一般的なセキュリティプラクティス。
REST API design 面接の質問例
- ニュース記事システムのREST APIを設計してください。記事、コメント、タグのリソースとエンドポイントをどのようにモデル化しますか?良い回答が押さえる点
- リソースの明確な階層化
- コメントは記事に依存するサブリソース
- タグは多対多の関係を表現
- エンドポイントは一貫性と直感性を重視
- クエリパラメータでフィルタリングやソートを提供
サンプル回答を見る
ニュース記事システムのREST APIでは、リソースを記事、コメント、タグとしてモデル化します。記事はコアリソースで、`/articles` エンドポイントでCRUD操作を提供します。コメントは記事に依存するサブリソースとして `/articles/:id/comments` で表現し、タグは独立したリソース `/tags` として管理し、記事とタグの多対多関係は `/articles/:id/tags` で扱います。これにより、関連データの取得が直感的になり、APIの一貫性が高まります。ただし、タグの関連付けには中間テーブルが必要で、更新時のトランザクション管理が複雑になる可能性があります。クエリパラメータ(例:`?include=comments,tags`)を使って関連リソースを一緒に返すことで、N+1問題を回避しつつ柔軟性を提供します。また、フィルタリングやソート、ページネーションもクエリパラメータでサポートし、大規模データに対応します。
- ユーザーCRUD APIが与えられた場合、ソフトデリートを実装し、アクティブなユーザーと削除されたユーザーの両方を取得するにはどうすればよいですか?良い回答が押さえる点
- deleted_at カラムの追加
- デフォルトでアクティブなユーザーのみ取得
- 削除済みを含めるためのクエリパラメータ
- 論理削除のメリット: データ復元、監査
- 物理削除と論理削除のトレードオフ
サンプル回答を見る
ソフトデリートを実装するには、ユーザーテーブルに `deleted_at` カラム(NULL可能なタイムスタンプ)を追加します。アクティブなユーザーのみを返す場合、`SELECT * FROM users WHERE deleted_at IS NULL` とします。削除済みユーザーを含めるには、クエリパラメータ `?include_deleted=true` をAPIに追加し、条件を `deleted_at IS NOT NULL` に変えます。両方を取得する場合は制限なしで全件取得します。この設計の利点は、データの復元が容易で、監査ログとして利用できることです。ただし、クエリごとに `deleted_at` 条件を追加する必要があり、パフォーマンス上のオーバーヘッドが生じます。また、ユニーク制約がある場合、論理削除されたレコードが一意性を妨げるため、複合ユニーク制約に `deleted_at` を含めるなどの対策が必要です。物理削除に比べてストレージ消費が増えるため、長期的なデータ管理戦略を考慮すべきです。
- 大量のツイートコレクションのページネーションをどのように設計しますか?オフセットベースとカーソルベースのページネーションを比較し、一つ選んでください。良い回答が押さえる点
- オフセットページネーション: 単純だが不安定
- カーソルベース: 安定、大規模向け
- ソーシャルメディアではカーソルベースが一般的
- 実装の複雑さとパフォーマンスのトレードオフ
- 推奨: カーソルベースを選択
サンプル回答を見る
大量のツイートコレクションでは、カーソルベースのページネーションを推奨します。オフセットベースは実装が単純ですが、データ挿入/削除によりページがずれる可能性があり、大規模データではOFFSETのスキャンコストが高くなります。一方、カーソルベースは一意の順序キー(例:ツイートIDや作成日時)を使用し、そのキー以降のデータを効率的に取得するため、安定性が高く、大量データでもパフォーマンスが良いです。特にリアルタイム性が重要なソーシャルメディアでは、カーソルベースが標準です。ただし、実装がやや複雑で、クライアントはカーソル値を保持する必要があります。レスポンスには `next_cursor` フィールドを含め、クライアントはそれを次のリクエストに使用します。オフセットベースは小規模または静的なデータセットに適していますが、スケーラビリティを考慮するとカーソルベースが優れています。
- クライアントが特定のフィールドを要求(スパースフィールドセット)し、関連リソース(例:投稿と著者詳細)を含めることができるAPIを設計してください。良い回答が押さえる点
- sparse fieldsets: ?fields[resource]=field1,field2
- includes: ?include=relatedResource
- 複数リソースのネストをサポート
- パフォーマンス最適化のためのサーバー側実装
- JSON API 仕様の採用も検討
サンプル回答を見る
クライアントが特定のフィールドを要求できるようにするには、`fields` クエリパラメータを使用します。例:`?fields[articles]=title,body` で、レスポンスの記事オブジェクトに title と body のみを含めます。関連リソースを含めるには、`include` パラメータを使用します。例:`?include=author,comments` で、記事と共に著者詳細やコメントを返します。この設計により、クライアントは必要なデータだけを取得でき、ネットワーク転送量を削減できます。サーバー側では、これらのパラメータを解析し、データベースクエリを最適化して、不要なカラムやJOINを避ける必要があります。注意点として、フィールド指定はセキュリティ上、許可リストで制限すべきで、`include` の深いネストはパフォーマンスに影響するため、最大深度を設定します。JSON API 仕様を参考にすると、標準化された方法を提供できます。
- REST APIのバージョニングはどのように行いますか?URIバージョニングとカスタムリクエストヘッダーバージョニングの長所と短所を説明してください。良い回答が押さえる点
- URIバージョニング: 明確でシンプル
- カスタムヘッダーバージョニング: URIをクリーンに保つ
- URIはキャッシュに優しい
- ヘッダーはオプションで柔軟性がある
- トレードオフ: 管理の複雑さとクライアントの負担
サンプル回答を見る
REST APIのバージョニングには主にURIバージョニング(例:`/v1/users`)とカスタムリクエストヘッダー(例:`Accept: version=1`)の2つの方法があります。URIバージョニングの長所は、URLが明確で、クライアントが容易にバージョンを指定できる点です。また、異なるバージョンのレスポンスが異なるURLになるため、HTTPキャッシュが機能しやすいです。短所は、URLが長くなり、リソース設計がバージョンに依存してしまうことです。カスタムヘッダーバージョニングは、URIをクリーンに保ち、バージョン情報をヘッダーに隠せます。しかし、クライアントがヘッダーを正しく設定する必要があり、ブラウザのキャッシュが効きにくい、また開発ツールでの視認性が低いという欠点があります。全体的に、多くの公開APIではURIバージョニングが採用され、特に初期バージョンでの混乱を避けやすいです。一方、内部APIや進化が速いサービスではヘッダー方式が適している場合もあります。重要なのは、一度選択したら一貫性を保つことです。
- AuthorizationヘッダーからAPIキーを検証し、欠落または無効な場合に401を返すシンプルなExpress.jsミドルウェアを書いてください。良い回答が押さえる点
- Authorization ヘッダーの存在確認
- Bearer スキームとAPIキーの抽出
- キーの検証(例:環境変数との比較)
- 無効または欠落時は401を返す
- ミドルウェアの順序に注意
サンプル回答を見る
Express.jsミドルウェアは、リクエストの `Authorization` ヘッダーをチェックし、APIキーを検証します。ヘッダーが存在しない、または `Bearer <token>` 形式でない場合は、`401 Unauthorized` を返します。キーの検証は、簡単な例として環境変数 `API_KEY` と比較します。実際の運用ではデータベースやキャッシュと照合します。注意点として、ミドルウェアはルートに適用する前に、認証不要なエンドポイント(例:ログイン)を除外する必要があります。また、エラーレスポンスには `WWW-Authenticate` ヘッダーを含めるとクライアントが適切に動作できます。
参考コードjavascript // APIキー認証ミドルウェア const apiKeyAuth = (req, res, next) => { const authHeader = req.headers.authorization; if (!authHeader) { return res.status(401).json({ error: 'Missing Authorization header' }); } const parts = authHeader.split(' '); if (parts.length !== 2 || parts[0] !== 'Bearer') { return res.status(401).json({ error: 'Invalid Authorization format. Expected: Bearer <API_KEY>' }); } const apiKey = parts[1]; // 検証: 環境変数と比較(実際はDBなどで検証) if (apiKey !== process.env.API_KEY) { return res.status(401).json({ error: 'Invalid API key' }); } next(); }; // 使用例 app.use('/api', apiKeyAuth); - 支払いAPIのエラーレスポンス構造を設計し、バリデーションエラー、残高不足、サーバーエラーの例を含めてください。良い回答が押さえる点
- 統一されたエラーレスポンス構造
- エラーコード、メッセージ、詳細を含む
- HTTPステータスコードの適切な使用
- バリデーションエラー: 400 Bad Request
- 残高不足: 402 Payment Required
- サーバーエラー: 500 Internal Server Error
サンプル回答を見る
支払いAPIのエラーレスポンスは、統一されたJSON構造を持つべきです。トップレベルに `error` オブジェクトを含め、その中に `code`(機械可読な文字列)、`message`(人間可読な説明)、`details`(追加情報)を含めるとよいでしょう。例えば、バリデーションエラー(`code: 'VALIDATION_ERROR'`)では、`details` にフィールド単位のエラーを配列で含めます。残高不足(`code: 'INSUFFICIENT_BALANCE'`)では、現在の残高や不足額を `details` に含めます。サーバーエラー(`code: 'INTERNAL_ERROR'`)では、詳細を最小限にし、ログ用のIDを提供することもあります。HTTPステータスコードは、バリデーションエラーに400、残高不足に402(支払いが必要)、サーバーエラーに500を使用します。ただし、402はあまり一般的ではないため、代わりに400や409を使う企業もあります。一貫性が重要です。
- パブリックAPIにレート制限を実装するにはどうすればよいですか?アルゴリズムと、制限をクライアントに伝える方法を説明してください。良い回答が押さえる点
- レート制限アルゴリズム: トークンバケット、リーキーバケット、固定ウィンドウ、スライディングウィンドウ
- 実装にはRedisなどの高速ストレージが適切
- 制限超過時は429 Too Many Requestsを返す
- レート制限情報をレスポンスヘッダーで通知
- クライアントはRetry-Afterヘッダーを利用
サンプル回答を見る
パブリックAPIのレート制限では、トークンバケットアルゴリズムがよく使われます。トークンバケットは、バケットにトークンを一定レートで補充し、リクエストごとにトークンを消費する方式です。実装はRedisなどのインメモリストアで行い、各クライアント(IPやAPIキー単位)にバケットを割り当てます。制限を超えた場合、HTTP 429 Too Many Requestsを返し、レスポンスヘッダーに `X-RateLimit-Limit`(制限数)、`X-RateLimit-Remaining`(残りリクエスト数)、`X-RateLimit-Reset`(リセット時間)を含めてクライアントに情報を提供します。また、`Retry-After` ヘッダーで再試行までの秒数を伝えます。これにより、クライアントは過剰なリクエストを避けることができます。他のアルゴリズムとして、固定ウィンドウ(実装が単純だが境界で急増に対応しにくい)やスライディングウィンドウ(より正確だが複雑)もあります。要件に応じて選択します。
準備方法
- まずリソースとその関係を特定し、適切なHTTPメソッドでエンドポイントにマッピングすることから始めましょう。
- 好みの言語(Node.js/Express、Python/Flaskなど)で簡単なAPIをモックし、CRUD操作とエラーハンドリングを練習しましょう。
- HATEOAS、PUT/DELETEのべき等性、安全/べき等なメソッドなどの一般的なAPI設計パターンを学びましょう。
- トレードオフについて議論できるように準備しましょう:特定のページネーションアプローチやバージョニング戦略を選ぶ理由など。
- ホワイトボードでの練習:リソースの命名、ステータスコード、エラー形式に関する設計決定を明確に説明しましょう。
よくある質問
REST API設計で最もよくある間違いは何ですか?
エンドポイントに動詞を使うこと(例:/users/getUser の代わりに GET /users/:id)。また、エラーに適切なHTTPステータスコードを使わないこと。
常にHATEOASを使うべきですか?
HATEOASは完全なREST遵守のための制約ですが、実際のマイクロサービスではシンプルさのために省略されることがよくあります。明確なリソースリンクに焦点を当てましょう。
部分更新はどのように扱いますか?
PATCHメソッドをJSON PatchまたはMerge Patch形式で使用します。部分更新の場合は、リクエストボディに変更するフィールドのみを含めます。
APIのバージョニングに最適な方法は?
URIバージョニング(例:/v1/users)は明示的でキャッシュしやすいですが、ヘッダーバージョニングはURLをクリーンに保ちます。チームの好みに基づいて選択しましょう。
REST API設計インタビューをどのように練習すればよいですか?
ホワイトボードやPostmanなどのツールを使って模擬インタビューを行い、トレードオフと考え方を説明することに集中しましょう。
REST API design の質問をAIで練習、瞬時にフィードバック
履歴書をアップロードして、パーソナライズされた模擬面接を受け、改善点を確認 — 無料で始められます。