Mar 5, 2026
OpenAPI × API First開発ガイド2026|スキーマ駆動・コード生成・モック・テスト API First開発とは
API First開発は、実装の前にAPI仕様を定義する アプローチです。OpenAPI(旧Swagger)仕様書をSingle Source of Truthとし、そこからサーバー/クライアントのコード、ドキュメント、テストを自動生成します。
従来の開発 vs API First
従来(Code First):
サーバー実装 → API仕様を後付けで作成 → フロントエンドが待ち
API First:
API仕様を定義 → サーバー/クライアント並行開発 → モックで即テスト
メリット
メリット 説明 並行開発 フロント/バックが同時に開発できる 型安全 スキーマからコード生成で型の不一致なし ドキュメント 仕様書がそのままドキュメント モック 実装前にAPIをテスト可能 契約テスト 仕様と実装の乖離を自動検出
OpenAPI仕様の書き方
基本構造
# openapi.yaml
openapi : 3.1.0
info :
title : My API
version : 1.0.0
description : ユーザー管理API
servers :
- url : http://localhost:8080/api/v1
description : ローカル開発
- url : https://api.example.com/v1
description : 本番環境
paths :
/users :
get :
summary : ユーザー一覧取得
operationId : listUsers
tags : [ Users ]
parameters :
- name : page
in : query
schema :
type : integer
default : 1
minimum : 1
- name : per_page
in : query
schema :
type : integer
default : 20
minimum : 1
maximum : 100
- name : search
in : query
schema :
type : string
maxLength : 100
responses :
'200' :
description : ユーザー一覧
content :
application/json :
schema :
$ref : '#/components/schemas/PaginatedUsers'
post :
summary : ユーザー作成
operationId : createUser
tags : [ Users ]
requestBody :
required : true
content :
application/json :
schema :
$ref : '#/components/schemas/CreateUserRequest'
responses :
'201' :
description : 作成成功
content :
application/json :
schema :
$ref : '#/components/schemas/User'
'409' :
description : メールアドレスが重複
content :
application/json :
schema :
$ref : '#/components/schemas/Error'
/users/{id} :
get :
summary : ユーザー詳細取得
operationId : getUser
tags : [ Users ]
parameters :
- name : id
in : path
required : true
schema :
type : integer
responses :
'200' :
description : ユーザー詳細
content :
application/json :
schema :
$ref : '#/components/schemas/User'
'404' :
$ref : '#/components/responses/NotFound'
components :
schemas :
User :
type : object
required : [ id , name , email , createdAt ]
properties :
id :
type : integer
example : 1
name :
type : string
example : 田中太郎
email :
type : string
format : email
example : tanaka@example.com
age :
type : integer
nullable : true
minimum : 0
maximum : 150
createdAt :
type : string
format : date-time
CreateUserRequest :
type : object
required : [ name , email , password ]
properties :
name :
type : string
minLength : 2
maxLength : 50
email :
type : string
format : email
password :
type : string
minLength : 8
maxLength : 100
age :
type : integer
minimum : 0
maximum : 150
PaginatedUsers :
type : object
required : [ items , total , page , perPage ]
properties :
items :
type : array
items :
$ref : '#/components/schemas/User'
total :
type : integer
page :
type : integer
perPage :
type : integer
Error :
type : object
required : [ message ]
properties :
message :
type : string
errors :
type : object
additionalProperties :
type : string
responses :
NotFound :
description : リソースが見つかりません
content :
application/json :
schema :
$ref : '#/components/schemas/Error'
securitySchemes :
bearerAuth :
type : http
scheme : bearer
bearerFormat : JWT
security :
- bearerAuth : []
コード自動生成
TypeScriptクライアント生成(openapi-typescript)
npx openapi-typescript openapi.yaml -o src/api/types.ts
// 生成された型を使用
import type { paths, components } from './api/types' ;
import createClient from 'openapi-fetch' ;
const client = createClient < paths >({
baseUrl: 'http://localhost:8080/api/v1' ,
});
// 完全に型安全なAPI呼び出し
const { data , error } = await client. GET ( '/users' , {
params: {
query: { page: 1 , per_page: 20 },
},
});
// data は PaginatedUsers 型
if (data) {
data.items. forEach ( user => {
console. log (user.name); // 型安全
});
}
// POST
const { data : newUser } = await client. POST ( '/users' , {
body: {
name: '田中太郎' ,
email: 'tanaka@example.com' ,
password: 'password123' ,
},
});
Zodスキーマ生成
npx openapi-zod-client openapi.yaml -o src/api/zodSchemas.ts
// 生成されたZodスキーマでバリデーション
import { CreateUserRequestSchema } from './api/zodSchemas' ;
const result = CreateUserRequestSchema. safeParse (formData);
if ( ! result.success) {
console. log (result.error.issues);
}
Pythonクライアント生成
pip install openapi-python-client
openapi-python-client generate --path openapi.yaml
モックサーバー(Prism)
# Prismのインストール
npm install -g @stoplight/prism-cli
# モックサーバー起動
prism mock openapi.yaml
# → http://localhost:4010 でモックAPIが使える
# リクエスト例
curl http://localhost:4010/users
# → OpenAPIのexampleに基づいたレスポンスが返る
curl -X POST http://localhost:4010/users \
-H "Content-Type: application/json" \
-d '{"name":"test","email":"test@example.com","password":"password123"}'
# → 201レスポンス
# バリデーション
curl -X POST http://localhost:4010/users \
-H "Content-Type: application/json" \
-d '{"name":"t"}'
# → 422エラー(minLength違反)
Prismのプロキシモード
# 実際のAPIに対してリクエスト/レスポンスをOpenAPIに対して検証
prism proxy openapi.yaml http://localhost:8080
リンティング(Spectral)
npm install -g @stoplight/spectral-cli
# .spectral.yaml
extends :
- spectral:oas
rules :
# カスタムルール
operation-description :
severity : warn
given : "$.paths[*][*]"
then :
field : description
function : truthy
# operationIdは必須
operation-operationId :
severity : error
# 日本語でsummaryを書く
operation-summary-length :
severity : warn
given : "$.paths[*][*].summary"
then :
function : length
functionOptions :
min : 5
max : 50
spectral lint openapi.yaml
# 出力例
# /users:get.description - Operation should have a description (operation-description)
# ✖ 1 problem (0 errors, 1 warning)
契約テスト
Schemathesisによる自動テスト
pip install schemathesis
# OpenAPIスキーマに基づいてファジングテスト
schemathesis run http://localhost:8080/openapi.json \
--checks all \
--base-url http://localhost:8080
# 見つかる問題の例:
# - 5xxエラーを返すエッジケース
# - スキーマと異なるレスポンス
# - 想定外の入力での挙動
Prismでの契約テスト
// テストでPrismを使って仕様との一致を検証
import { createClientFromPrism } from './test-helpers' ;
test ( 'GET /users のレスポンスがスキーマに一致する' , async () => {
const response = await fetch ( 'http://localhost:8080/api/v1/users' );
const data = await response. json ();
// Zodスキーマで検証
const result = PaginatedUsersSchema. safeParse (data);
expect (result.success). toBe ( true );
});
CI/CDとの統合
# .github/workflows/api-check.yml
name : API Schema Check
on :
pull_request :
paths :
- 'openapi.yaml'
- 'src/api/**'
jobs :
lint :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- name : OpenAPIリンティング
run : npx @stoplight/spectral-cli lint openapi.yaml
breaking-changes :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
with :
fetch-depth : 0
- name : 破壊的変更の検出
run : |
npx oasdiff breaking \
<(git show main:openapi.yaml) \
openapi.yaml
generate :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- run : npm ci
- name : 型生成
run : npx openapi-typescript openapi.yaml -o src/api/types.ts
- name : 差分確認
run : git diff --exit-code src/api/types.ts
まとめ
API Firstの開発フロー
1. OpenAPIでAPI仕様を定義
2. Spectralでリンティング
3. Prismでモックサーバー起動
4. フロント: openapi-fetchで型安全にAPI呼び出し
5. バック: スキーマに合わせて実装
6. CI: 契約テスト + 破壊的変更検出
ツール 用途 openapi-typescript TypeScript型生成 openapi-fetch 型安全HTTPクライアント Prism モックサーバー/プロキシ Spectral リンティング oasdiff 破壊的変更検出 Schemathesis ファジングテスト
API Firstは初期コストがかかりますが、チーム開発のスピードと品質を大幅に向上させます。特にフロント/バック分業のプロジェクトでは、その効果は絶大です。
関連記事
サーバー選びで迷ったら — 国内トップシェアを比較しよう
XServer・さくらのレンタルサーバー・XServerVPS。用途と予算に合わせた最適なプランを見つけよう。高速・安定・手厚いサポートで初心者からプロまで選ばれています。