— CRUDの先へ:境界・セキュリティ・レスポンス標準 —
はじめに:面接で見えた“設計の壁”が、現場の速度と品質を決める
候補者面接をしていると、特定技術の知識や理論の準備はしっかりしているのに、「設計」や「アーキテクチャ思考」になると途端に浅くなるケースが多い——このギャップは、実はそのまま現場の爆速納品と品質担保の差になります。
この記事は、実装テクニック集というよりAPI設計の“考える順番”を揃えるための土台です。手を動かす前の設計が揃うほど、システム開発/アプリ開発のスピードは“破綻せずに”上がります。
1. APIの基本:APIは“機械同士の会話の約束”
API(Application Programming Interface)は、2つのシステムが「お互いに理解できる形で」やり取りするための窓口です。外部の利用者(他システム)は、裏側の実装を知らなくても、定められた方法で機能を利用できます。
例えるならレストランのメニュー。メニュー(API)を見て注文し、料理(結果)を受け取れるけれど、厨房の手順(実装)は知らなくていい。…そしてメニューが日替わりで気分変更されると、客(利用者)は離れます。APIも同じです。

2. APIは何のため?:安全・制御・予測可能な統合
APIの主目的は、システム同士を「安全に」「制御可能に」「予測可能に」統合することです。良いAPIは次を実現します。
- 異なるシステムが独立して開発・運用できる(変更の影響範囲を閉じ込める)
- システム間が会話できる(連携・自動化が進む)
- 既存利用者を壊さずにプラットフォームを成長させられる(互換性と拡張性)
代表的な連携例:
- フロントエンド ↔ バックエンド
- マイクロサービス間通信
- 社内システム → 社外公開API
- 自社アプリ ↔ パートナーアプリ
だからこそAPIは、スケーラブルで安全、速く、分かりやすく、保守しやすい必要があります。

3. 構造:CRUDの集合から“境界(Boundary)”へ
面接でも現場でもつまずきやすいのが、「この状況なら、どんなAPIを作る?」という問いです。多くの人がDBテーブルごとのCRUDエンドポイントを先に作り始めます。成立することもありますが、いつも正解とは限りません。
境界(Boundary)で考えると、設計が一段上がる
- ❌「UserにCRUDを作る」
- ✅「利用者がユーザー関連データとどう関わるべきか? その境界をどう切るか?」
この発想は、爆速納品を狙うほど効きます。境界が曖昧なCRUD集合は、後から変更要求が来た瞬間に“全部に影響が波及”し、品質担保が崩れやすいからです。
API構造の狙い(設計目標)
- HTTPの都合とビジネスロジックを分離する
- サーバーを起動せずにユースケースをテストできるようにする
- 依存関係と結合度を下げる(変更に強くする)
- 保守・バージョニング・セキュリティ・監視がしやすい形にする
4. 基本の3層:まずはこれで十分強い
多くのシステムで堅い土台になるのが3層です。
- API/Transport層:ルーティング、入力検証、認証認可、HTTPエラーハンドリング、レスポンス整形
- Application層:ユースケース(例:注文作成、プロフィール取得、支払い方法更新)を実行
- Domain層:エンティティ/集約と、HTTPやDBに依存しない中核ビジネスロジック
これが揃うと、サーバーを起動せずにユースケースをテストでき、変更の影響範囲も見えやすい。結果、納期が短くても(=爆速納品の圧が高くても)品質担保しやすい構造になります。
5. ディレクトリ設計:型(controllers/services…)ではなく機能単位で
よくある失敗は、controllers/services/repositories など“ファイル種別”で固めること。代わりに users/orders/billing のように“機能(ドメイン)単位”で固めると、依存のねじれが減り、変更が追いやすくなります。
モノリスの例(推奨構成)
src/api
/routes (map endpoints)
/middlewares (authentication, tracing, rate limiting)
/controllers (translate HTTP requests into use cases)
/schemas (request and response validation)
src/modules
/users
/domain
/application
/infra
/orders (same structure as users)
/billing (same structure as users)
src/shared (logging, configuration, base errors, utilities)
src/infra (database clients, messaging, external providers)
src/main.ts (application bootstrap and wiring)
マイクロサービスでも考え方は同じ(サービスごとに繰り返す)
services/users-api
/api
/routes
/middlewares
...
/modules
/users
/domain
/application
...
/roles
/domain
...
/shared
...
6. 構造チェックリスト(面接でも現場でも効く)
このチェックで「No」が増えるほど、システム開発/アプリ開発は“速く出すほど壊れやすい”状態になります。
- ✅ サーバーを起動せずにユースケースをテストできるか?
- ✅ フレームワーク変更でDomain層を触らずに済むか?
- ✅ エンドポイントは“手順のオーケストレーション”に徹し、業務ルールを持っていないか?
- ✅ 機能ごとに自己完結し、まとまっているか?
- ✅ users が orders を勝手に import するなど、不自然な依存が無いか?

7. セキュリティ:入力は“悪意がある”前提で設計する
API設計で最重要級の論点がセキュリティです。考え方はシンプル。
- 入力は無害と証明されるまで悪意がある
- クライアントは平気で嘘をつく
3本柱:Validation / Authentication / Authorization
7.1 Validation:何を検証する?
検証対象:
- Path parameters:ID、slug など
- Query parameters:ページング、フィルタ、ソート
- Request body:ペイロード本体
- Headers:Content-Type、Authorization など
検証の実務ルール:
- ブラックリストではなくホワイトリスト(期待する形を定義)
- 型と範囲(最大/最小、文字数、enum制約など)
- 正規化(trim、大小文字、フォーマット統一)
- 曖昧さの扱い(null vs undefined、文字列の数値 vs 整数など)
7.2 Authentication:「誰が呼んでいる?」に答える
「全部 trusted だよね」で始めた瞬間に事故ります。JWTは定番回答ですが、状況に応じて選ぶのが設計です。
- APIキー:サーバー間の単純な連携に有効(ローテーション、権限制限、監査が必須)
- JWT:有効期限、ローテーション、スコープ設計ができれば強い
- OAuth2 / OIDC:SSOやサードパーティ利用者が絡むプラットフォームでは第一候補
- mTLS:管理された環境のサービス間通信で強力
トークン認証で最低限守ること:
- 短命トークン(expiration)を基本にする
- 必要ならリフレッシュ機構を用意する
- トークン全文をログに残さない
- 常にHTTPS
- 401/403を正しく返す(“なんとなく200”は地雷)
7.3 Authorization:「何をして良い?」を決める
認可はバグ予防でもあり、悪用防止でもあります。代表モデル:
- RBAC(ロール):Admin / Manager / User など
- Scopes / Permissions:orders:read / orders:write など
- ABAC(属性):地域、プラン、所有権など属性に基づくルール
認可のベストプラクティス(2つだけ覚える):
- エンドポイント単位ではなく“リソース単位”で認可する
- クライアントが送る所有者IDを信用しない(所有権はサーバー側で検証)
追加のセキュリティコントロール:
- レート制限/スロットリング
- CORS(許可するオリジンを絞る)
- ログ(スタックトレースや機微情報を出しすぎない)
8. レスポンス設計:利用者が迷わない“標準”を作る
レスポンス設計を揃えると、利用者(別チームや外部)が楽になり、結果として問い合わせが減ります。これは運用コストにも効くので、爆速納品の組織ほど“標準化”が武器になります。
8.1 正しいHTTPステータスを返す
200 OKなのに中身がエラー、みたいなAPIは本当に多いです。ステータスとボディの意味が一致していないと、利用者は毎回“当て推量”を強いられます。
避けるべき例:HTTP 200 OK なのに中身がエラー
{
"id": 1234,
"body": { "error": "no users found" },
"status": "not_found"
}
代表的なステータスコード:
| Status | Meaning |
|---|---|
| 200 OK | 処理成功 |
| 201 Created | リソース作成成功 |
| 204 No Content | 成功(ボディなし) |
| 400 Bad Request | リクエストが不正 |
| 401 Unauthorized | 未認証 |
| 403 Forbidden | 認証済みだが権限なし |
| 404 Not Found | リソースが見つからない |
| 409 Conflict | 状態と衝突(重複など) |
| 429 Too Many Requests | レート制限超過 |
| 500+ | サーバー側エラー |
8.2 レスポンスの“エンベロープ”を統一する
エンドポイントごとにレスポンス構造がバラバラだと、利用側の実装が複雑になり、保守もつらくなります。できるだけ一貫した形(標準エンベロープ)を保ちましょう。
避けるべき例:エンベロープが不一致
// Bad: inconsistent envelopes
// Endpoint: /user/123/orders/123
{ "id": "123", "status": "paid", "total": 150 }
// Endpoint: /order/123
{
"data": { "id": "123", "status": "paid", "total": 150 },
"meta": { "requestId": "456" }
}
8.3 レスポンス側のValidation(“返すもの”も仕様)
- 曖昧なエラー(例:Validation error)ではなく、具体的な理由を返す(例:Invalid email format)
- 一覧は明示的ページング(limit/offset または cursor)
- 空配列はエラーではない
- 必要ならバージョニング(/v1/users, /v2/users)
9. まとめ:設計力は“順番”で伸びる
API設計で大事なのは、流行りの技術よりも次の順番です。
- 1. 境界で考える
- 2. 層で分離する
- 3. セキュリティを前提にする
- 4. 標準で迷いを減らす
この順番が揃うと、スケーラビリティも保守性も自然についてきます。つまり、システム開発/アプリ開発で爆速納品を狙っても、設計が原因で品質担保が崩れる確率を下げられます。
10. 演習:面接でよく出す設計課題(あなたならどう切る?)
次の要件を満たすREST APIを設計してみてください。
- ユーザーCRUDとアカウント管理を扱う
- 1つのアカウントは複数ユーザーを持つ
- ロールは admin / manager / trainer / trainee
- それぞれでスコープ/権限が異なる
構造(境界と層)、セキュリティ(検証/認証/認可)、レスポンス標準まで含めて設計できたら、“シニアっぽい”思考に一歩近づきます。
Q&A:よくある勘違いを一気に潰す(爆速納品の敵は“曖昧さ”)
Q1. CRUDをテーブルごとに作れば十分?
A. 成立することもありますが、常に正解ではありません。まず境界(利用者がどう関わるか)で設計すると、変更に強くなります。
Q2. JWTを入れればセキュリティはOK?
A. JWTは選択肢の一つ。APIキー、OAuth2/OIDC、mTLSなど状況に応じて選び、短命トークン・HTTPS・ログ配慮・401/403運用までセットで考えるのが設計です。
Q3. 200 OKでエラー返すとフロントが楽じゃない?
A. その“楽”は、後で必ず利息付きで返ってきます。ステータスは正しく返すべきです。
必要なら、次のステップとして「標準レスポンスエンベロープ案(成功/失敗/ページング)」を、あなたのプロダクト(BFF有無、公開API有無、認可モデル)に合わせて“そのまま採用できる雛形”で作れます。
