✍️ 필사 모드: 2026 年 API スキーマ地図 — JSON Schema・OpenAPI 3.1・AsyncAPI・GraphQL・gRPC・Smithy・TypeSpec を一枚で
日本語プロローグ — スキーマがコードより先に来る時代
2026 年のバックエンド会議はだいたいこう始まる。「エンドポイントを書く前に、まずスキーマを見せてくれ」。
ハンドラを先に書いてその結果から OpenAPI を吐かせる時代があった。spec-from-code — コードが真実、スペックは副産物。楽だった。そして崩れた。二つのチームがお互いのレスポンス形状を推測しあって一ヶ月かかる結合バグを生み、クライアント SDK は常に一拍遅れ、社内 Wiki の「現状の API」ページは半分が嘘になっていた。
2026 年は逆になった。spec-first — スキーマを先に書き、そこから型・ドキュメント・サーバスタブ・クライアント SDK・テストフィクスチャ・AI ツール定義まで 生成 する。真実はスキーマファイルにある。
だから一度整理しておこう。同じ「API」でもプロトコルが違えば道具が違う。REST は OpenAPI 3.1、イベントは AsyncAPI 3.0、サービス間は Protobuf、フロントエンド向けは GraphQL、そしてそれらの 文法的基盤 が JSON Schema 2020-12。さらに AWS の Smithy、Microsoft の TypeSpec、契約テストの Pact — 名前は多いが役割は明確に分かれている。
本記事は 2026 年の API スキーマ地図だ。各形式の正体と強み、同じドメインモデルを四つの形式に翻訳した比較、AI ツールコールで JSON Schema が占めた位置、そして「うちのチームは何を選ぶべきか」に対する誠実な意思決定フレームまで。
1 章 · JSON Schema 2020-12 — すべての土台
まず一行で。JSON Schema は「JSON 値の形をさらに別の JSON で記述する」標準である。 「このフィールドは整数」「これは 1 から 120」「これは ISO 8601 の日付」 — そうした制約を宣言として書く。
draft 2020-12 が事実上の安定ベースラインだ。その後の作業は進行中だが、2026 年現在、互換性とツール対応がもっとも厚いバージョンは 2020-12 である。OpenAPI 3.1 がこの draft に 完全に 揃ったことで、以前に nullable や example の差異で頭が痛かった微妙な齟齬がほぼ消えた。
JSON Schema が 2026 年に重要になった理由は、三つの場所で同時に使われているからだ。
- REST API: OpenAPI 3.1 の
components.schemasの中身はそのまま JSON Schema 2020-12 である。 - AI ツールコール(function calling): OpenAI・Anthropic・Gemini のツール定義フォーマットがすべて JSON Schema のサブセットだ。モデルが
argumentsを JSON で埋めて返し、ホストは同じスキーマで検証する。 - 設定の検証: kubeconfig・CI ワークフロー・アプリの設定ファイルを検証するときに最もよく出会う標準。
JSON Schema は「フォーマット」ではなく 文法 である。一度学べば右の三つの場所で同じ文法を使える。2026 年のバックエンドエンジニアがもっとも頻繁に触る単一標準と言ってもよい。
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/user.json",
"type": "object",
"required": ["id", "email"],
"properties": {
"id": { "type": "string", "format": "uuid" },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0, "maximum": 130 },
"roles": {
"type": "array",
"items": { "type": "string", "enum": ["admin", "member", "guest"] },
"uniqueItems": true
}
},
"additionalProperties": false
}
この小さなファイル一つが、OpenAPI にも、AI ツール定義にも、単独のバリデータにも入る。再利用可能な単位こそが真実なのだ。
2 章 · OpenAPI 3.1 — REST 標準は決まり、そしてやっと始まった
OpenAPI 3.0 と 3.1 の本質的な差は一行だ。3.1 は JSON Schema 2020-12 に完全に整列した。 3.0 時代の nullable: true は消え、標準は "type": ["string", "null"] になった。example/examples の意味は整理された。$ref はもっと自由になった — JSON Schema のどこでも指せる。
2026 年の OpenAPI 3.1 は REST API スペックの事実上の標準 だ。Swagger 時代の残滓はほぼ洗い流され、新規プロジェクトはほぼすべて 3.1 から始まる。OpenAPI 3.2 の作業は進行中だが(フォーム・ヘッダ・複数コンテンツ応答のような小さな表面を整えている)、3.1 と 3.2 は 破壊的変更なし で進化する関係だ。今 3.1 で始めても安全である。
openapi: 3.1.0
info:
title: Orders API
version: 1.0.0
paths:
/users/{userId}/orders:
get:
summary: List orders for a user
parameters:
- name: userId
in: path
required: true
schema: { type: string, format: uuid }
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Order'
components:
schemas:
Order:
type: object
required: [id, userId, total]
properties:
id: { type: string, format: uuid }
userId:{ type: string, format: uuid }
total: { type: number, minimum: 0 }
status:
type: string
enum: [pending, paid, shipped, cancelled]
この一ファイルから 生成 されるもの: TypeScript/Go/Python のクライアント SDK、サーバスタブ、Postman/Bruno コレクション、インタラクティブドキュメント、モックサーバ、契約テストフィクスチャ、AI エージェントが呼べるツール定義。これが 2026 年のワークフローだ — 一つのスペックからすべての成果物。
Swagger UI は依然として動くが、2026 年の新しい標準は Stoplight Elements と Scalar だ。どちらも OpenAPI 3.1 をネイティブに扱い、ダークモード・検索・試行(try-it)・コードサンプルを Swagger UI より遥かに綺麗に見せる。Scalar は特に <script> 一行で完結する軽い埋め込みのおかげで一気に広まった。Swagger UI は「あってもよい」選択肢であり、もはやデフォルトではない。
3 章 · AsyncAPI 3.0 — イベントの OpenAPI
REST には OpenAPI がある。では Kafka トピック・MQTT チャンネル・WebSocket ストリーム・Server-Sent Events はどうするか。2026 年の答えは明快だ — AsyncAPI 3.0。
AsyncAPI 2.x 時代の最大の批判は「チャンネル = トピック = 動作の束」という曖昧さだった。publish と subscribe が同じチャンネル定義の中で絡んでいた。3.0 はこれを operations に分離した。チャンネルはメッセージが流れる道、operation は send/receive という行為 である。この分離だけで、Kafka のようなシステムのモデリングが格段に綺麗になった。
AsyncAPI 3.0 の中心語彙:
- channels — メッセージが流れる経路(トピック・キュー・チャンネル)。
- operations — そのチャンネルで起こる行為(send・receive)。明示的。
- messages — メッセージのペイロードスキーマ(JSON Schema をそのまま再利用)。
- servers — Kafka ブローカー・MQTT ブローカー・WebSocket エンドポイントなど、プロトコル別バインディング。
asyncapi: 3.0.0
info:
title: Orders Events
version: 1.0.0
servers:
kafka-prod:
host: kafka.prod.example.com:9092
protocol: kafka
channels:
orderCreated:
address: orders.created.v1
messages:
OrderCreated:
$ref: '#/components/messages/OrderCreated'
operations:
publishOrderCreated:
action: send
channel: { $ref: '#/channels/orderCreated' }
components:
messages:
OrderCreated:
payload:
type: object
required: [orderId, userId, createdAt]
properties:
orderId: { type: string, format: uuid }
userId: { type: string, format: uuid }
createdAt: { type: string, format: date-time }
total: { type: number, minimum: 0 }
AsyncAPI 3.0 が 2026 年に定着した理由は二つだ。第一に、イベント駆動システムはもはや「特殊ケース」ではない。ほぼすべてのマイクロサービス系会社は Kafka・NATS・MQTT のいずれかを使っている。第二に、AsyncAPI のエコシステムが OpenAPI の模倣を超えて 自前の道具 を持つようになった — Studio、generator(サーバスタブ・クライアント)、validator、カタログ。ユーザビリティのギャップはほぼ埋まった。
REST とイベントが同じシステムに混在するのが普通の 2026 年では、OpenAPI と AsyncAPI を 同じリポジトリに並べて 管理するのが標準パターンだ。どちらも JSON Schema を基盤にしているので、メッセージペイロードスキーマの共有も容易である。
4 章 · GraphQL SDL — フロントエンドとの講和条約
GraphQL は 2015 年に Facebook が発表し、2019 年に GraphQL Foundation に移管された。2026 年でも強い領域を保ち続けている。とくに 複数のクライアントが違う形のデータを必要とする場所 — BFF、モバイルアプリが何種類もあるコンテンツプラットフォーム、ダッシュボード。
GraphQL のスキーマは SDL(Schema Definition Language) という独自の DSL で書く。OpenAPI/AsyncAPI/JSON Schema と違って JSON ではない。
type User {
id: ID!
email: String!
age: Int
orders(status: OrderStatus, limit: Int = 20): [Order!]!
}
type Order {
id: ID!
total: Float!
status: OrderStatus!
createdAt: DateTime!
}
enum OrderStatus {
PENDING
PAID
SHIPPED
CANCELLED
}
type Query {
user(id: ID!): User
orders(userId: ID!, status: OrderStatus): [Order!]!
}
scalar DateTime
GraphQL の魅力は introspection — スキーマ自体が API からクエリ可能なことだ。クライアントツールはライブサーバに接続してスキーマを引き、コード生成で型安全なフックを作る。Apollo Studio、GraphiQL、GraphQL Code Generator、urql、Relay — 道具のエコシステムは厚い。
2026 年の GraphQL のトレンド:
- Federation v2 が定着した — 複数サービスの GraphQL を一つのスーパーグラフに合成する標準。
- Persisted queries がセキュリティと性能のデフォルトになった — クライアントは任意のクエリを送らず、ビルド時に登録されたクエリのハッシュだけを送る。
- REST との共存。「全部 GraphQL に書き換えよう」の波は去り、「フロントエンドがよく変わるところだけ GraphQL、バックエンド間は gRPC/REST」が普通のパターンになった。
弱点も誠実に見ておこう。キャッシュが面倒(URL が一本なので HTTP キャッシュが効きにくい)。N+1 は DataLoader のようなパターンで解決する必要がある。クエリコスト分析をしないと、クライアント一人がサーバを落とせる。そして すべて の場所に合うわけではない — CRUD 中心の単純な API なら、OpenAPI のほうがほぼ常にシンプルだ。
5 章 · gRPC と Protobuf — サービス間のデフォルト
2026 年でも、サービス間呼び出しといえば gRPC と Protobuf が依然としてデフォルトである。理由は単純だ — 小さい、速い、多言語、ストリーミングがファーストクラス。
Protobuf は バイナリ スキーマだ。.proto ファイルにメッセージとサービスを定義すると、protoc(もっと多くの場合は Buf)が言語ごとのコードを生成する。ワイヤ上では JSON より遥かに小さく(フィールド名が整数タグに圧縮される)、パースもずっと速い。
syntax = "proto3";
package shop.v1;
import "google/protobuf/timestamp.proto";
message User {
string id = 1;
string email = 2;
int32 age = 3;
repeated string roles = 4;
}
message Order {
string id = 1;
string user_id = 2;
double total = 3;
OrderStatus status = 4;
google.protobuf.Timestamp created_at = 5;
}
enum OrderStatus {
ORDER_STATUS_UNSPECIFIED = 0;
ORDER_STATUS_PENDING = 1;
ORDER_STATUS_PAID = 2;
ORDER_STATUS_SHIPPED = 3;
ORDER_STATUS_CANCELLED = 4;
}
service OrdersService {
rpc GetOrders(GetOrdersRequest) returns (GetOrdersResponse);
rpc StreamOrders(stream GetOrdersRequest) returns (stream Order);
}
message GetOrdersRequest { string user_id = 1; }
message GetOrdersResponse { repeated Order orders = 1; }
2026 年の Protobuf エコシステムの中心は事実上 Buf である。buf build・buf lint・buf breaking・buf generate — protoc のユーザビリティ問題をすべて解消した道具一式だ。Buf Schema Registry は protobuf スキーマの GitHub のような役割を担う — バージョン・リリース・依存関係を管理する。
gRPC を使うとき:
- サービス間 呼び出し — マイクロサービスの内部メッシュ。
- 双方向ストリーミング — チャット、ライブデータ、ゲームサーバ。
- 高性能 が本当に重要な場所 — 非常に高い RPS、大きなペイロード。
gRPC を使わないとき:
- ブラウザから直接 呼ぶ — gRPC-Web はあるが依然として面倒。REST/GraphQL のほうが向いている。
- 第三者公開 API — 外部開発者には敷居が高すぎる。
- 平文でデバッグしたいとき — ワイヤがバイナリなので curl で覗けない。
注目すべき流れ: Connect(Buf が作ったプロトコル)が登場し、同じ .proto から gRPC と REST/JSON を同時に公開できるようになった。内部メッシュは gRPC、外部クライアントは同じハンドラを JSON で — 一つのコードベースで二兎を追える。
6 章 · 同じモデルを四形式で — User-with-orders
抽象的に比較するのではなく、同じドメインを移してみよう。ユーザが注文の配列を持つ。
6.1 JSON Schema(単独)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"Order": {
"type": "object",
"required": ["id", "total", "status"],
"properties": {
"id": { "type": "string", "format": "uuid" },
"total": { "type": "number", "minimum": 0 },
"status": { "type": "string", "enum": ["pending","paid","shipped","cancelled"] }
}
}
},
"type": "object",
"required": ["id", "email", "orders"],
"properties": {
"id": { "type": "string", "format": "uuid" },
"email": { "type": "string", "format": "email" },
"orders":{ "type": "array", "items": { "$ref": "#/$defs/Order" } }
}
}
6.2 OpenAPI 3.1(REST)
paths:
/users/{id}:
get:
parameters:
- { name: id, in: path, required: true, schema: { type: string, format: uuid } }
responses:
'200':
content:
application/json:
schema: { $ref: '#/components/schemas/UserWithOrders' }
components:
schemas:
UserWithOrders:
type: object
required: [id, email, orders]
properties:
id: { type: string, format: uuid }
email: { type: string, format: email }
orders:
type: array
items: { $ref: '#/components/schemas/Order' }
Order:
type: object
required: [id, total, status]
properties:
id: { type: string, format: uuid }
total: { type: number, minimum: 0 }
status: { type: string, enum: [pending, paid, shipped, cancelled] }
6.3 GraphQL SDL
type User {
id: ID!
email: String!
orders: [Order!]!
}
type Order {
id: ID!
total: Float!
status: OrderStatus!
}
enum OrderStatus { PENDING PAID SHIPPED CANCELLED }
type Query {
user(id: ID!): User
}
6.4 Protobuf
message User {
string id = 1;
string email = 2;
repeated Order orders = 3;
}
message Order {
string id = 1;
double total = 2;
OrderStatus status = 3;
}
enum OrderStatus {
ORDER_STATUS_UNSPECIFIED = 0;
ORDER_STATUS_PENDING = 1;
ORDER_STATUS_PAID = 2;
ORDER_STATUS_SHIPPED = 3;
ORDER_STATUS_CANCELLED = 4;
}
同じモデル、四つの表現。情報量はほぼ同じだが、誰のために書くか が違う。JSON Schema は 共通文法、OpenAPI は HTTP 公開、GraphQL は クライアント親和、Protobuf は ワイヤ効率。ツールを選ぶことは データの形 ではなく 対話の相手 を決める作業だ。
7 章 · Smithy — AWS の API IDL
Smithy は AWS が作った API 定義言語だ。最初は AWS 内部で自社の SDK を自動生成するための道具だったが、2020 年代後半から外部に公開され、活発に進化している。
Smithy の哲学は「プロトコルに 不可知 なモデル」だ。.smithy ファイルでモデルを一度定義すれば、そこから 複数のプロトコル に投影できる — REST(JSON over HTTP)、AWS 固有プロトコル、gRPC。OpenAPI は 出力 として生成される。
$version: "2.0"
namespace shop
service Orders {
version: "2026-05-14"
operations: [GetUser]
}
@http(method: "GET", uri: "/users/{userId}")
operation GetUser {
input := {
@httpLabel
@required
userId: String
}
output := {
@required
id: String
@required
email: String
@required
orders: OrderList
}
}
list OrderList { member: Order }
structure Order {
@required
id: String
@required
total: Double
@required
status: OrderStatus
}
enum OrderStatus {
PENDING
PAID
SHIPPED
CANCELLED
}
Smithy の強み:
- トレイトシステム が OpenAPI より強力 — 認可、ページネーション、idempotency のような 横断関心事 を綺麗に表現できる。
- すべての AWS SDK(JavaScript・Python・Go・Rust など)が Smithy から生成されている — 産業的検証。
- 一つのモデルから複数の成果物 — OpenAPI、クライアント SDK、サーバスタブを単一ソースから。
弱み: エコシステムが OpenAPI より狭い。AWS の外での採用は徐々に増えているが、OpenAPI 3.1 の普遍性には及ばない。「複数言語向け SDK を作る」というシナリオでないなら、OpenAPI で十分なことが多い。
8 章 · TypeSpec — Microsoft の OpenAPI 執筆代替
OpenAPI 3.1 の YAML を手で書くのは — 正直 — 長く、反復が多く、タイポが起こりやすい。その痛みへの答えとして Microsoft が作ったのが TypeSpec(旧名 Cadl)だ。
TypeSpec は TypeScript ライクな コンパクトな DSL で API を記述し、そこから OpenAPI(または JSON Schema・Protobuf)を 生成 する。執筆性・再利用性・ツール対応で OpenAPI の素の YAML より一段上に位置する。
import "@typespec/http";
using TypeSpec.Http;
@service({ title: "Orders API" })
namespace ShopApi;
model Order {
id: string;
total: float64;
status: OrderStatus;
}
enum OrderStatus { Pending, Paid, Shipped, Cancelled }
model User {
id: string;
email: string;
orders: Order[];
}
@route("/users/{userId}")
interface Users {
@get op getUser(@path userId: string): User;
}
同じ情報量の OpenAPI YAML よりずっと短い。しかも コンパイル される — TypeSpec コンパイラが OpenAPI 3.1、JSON Schema 2020-12、Protobuf、クライアント SDK を同時に吐き出す。Azure の新サービスのほとんどが TypeSpec で書かれている。
TypeSpec を使うとき:
- API が大きく複雑 — 数十のエンドポイント、共通モデルと応答パターンが多い。
- 一つの定義から 複数の成果物 を欲しい — OpenAPI と Protobuf とクライアント。
- チームが TypeScript に慣れていて DSL が馴染む。
TypeSpec を使わないとき:
- API が小さい — OpenAPI YAML 一枚のほうがシンプルな場合がある。
- ツールチェーンを軽く保ちたい — TypeSpec は ビルドステップ を一つ増やす。
9 章 · Pact — 契約テスト、スキーマの第二の用途
ここまでの形式はすべて ドキュメント + コード生成 用だった。だがスキーマにはもう一つの強力な用途がある — 契約テスト(consumer-driven contract testing)。その代表が Pact だ。
状況: サービス A がサービス B を呼ぶ。B が応答の形を変えると A が壊れる。「結合テスト」は両方を立ち上げて呼ぶが — 遅くて壊れやすい。Pact は別のアプローチを取る。
消費者主導の契約。 A(消費者)が「私は B にこう要求し、こういう形の応答を期待する」を 契約ファイル に書く。この契約を Pact Broker にアップする。B(提供者)は CI で、自分のコードが その契約 を満たすか検証する。B が応答の形を変えて — A がそれに依存していたら — B の CI が即座に赤くなる。
// 消費者側のテスト
provider
.uponReceiving('a request for a user')
.withRequest({ method: 'GET', path: '/users/123' })
.willRespondWith({
status: 200,
body: { id: '123', email: 'a@b.com', orders: eachLike({ id: like('o1'), total: like(99.0) }) },
})
Pact は OpenAPI/AsyncAPI と 競合 するのではなく 補完 する。OpenAPI は「API はこうあるべき」という 定義 で、Pact は「この消費者が 実際に これに依存している」という 証拠 だ。両方を使うチームが増えた。
10 章 · AI ツールコール — JSON Schema の第二の春
2024 年から 2025 年にかけて LLM が ツールを呼ぶ ようになり、JSON Schema に第二の春が訪れた。OpenAI・Anthropic・Gemini のツール定義フォーマットは すべて JSON Schema のサブセットだ。モデルはそのスキーマに合わせて arguments を JSON で埋めて返し、ホストは同じスキーマで検証する。
同じ User-with-orders ドメインで「ユーザの注文一覧を取得」ツールを定義してみよう。
{
"name": "get_user_orders",
"description": "Return all orders for the given user",
"input_schema": {
"type": "object",
"required": ["user_id"],
"properties": {
"user_id": { "type": "string", "format": "uuid" },
"status": {
"type": "string",
"enum": ["pending","paid","shipped","cancelled"]
},
"limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 }
},
"additionalProperties": false
}
}
これが OpenAPI 内の components.schemas とほぼ同じであることに注目しよう。2026 年の綺麗なワークフローはこうなる:
- OpenAPI 3.1 で 真実の源泉 を置く。
- 同じスペックから サーバスタブとクライアント SDK を生成する。
- 同じスペックの
components.schemasを AI ツール定義 にマッピングする — 一つのハンドラが人とモデル両方に公開される。 - 同じスキーマ でツールコールの引数を検証する — モデルが間違えれば即座に拒否。
「API」と「AI エージェントのツール」が同じスキーマを共有することは 2026 年の日常的な現実だ。だから JSON Schema 2020-12 をしっかり理解することが、バックエンドエンジニアの 基礎スキル になった。
11 章 · spec-first か code-first か — 終わらない論争
OpenAPI/AsyncAPI 時代の大きな論争は二つの陣営に分かれる。
code-first: コード(デコレータ・型)を先に書き、そこからスペックを 生成 する。FastAPI、NestJS、tRPC が代表。利点は単一の真実 — コードがスペックだ。欠点はスペックが コードの影 になり、非技術ステークホルダーとの協議が遅くなり、言語の表現力に縛られること。
spec-first: スペックを先に書き、そこから サーバスタブとクライアント を生成する。OpenAPI YAML、TypeSpec、Smithy が代表。利点はプロトコルの 仕様 がコードより先に存在する — API デザイナ・QA・外部クライアントが同時に見られる。欠点は 真実が二箇所でずれる リスク — スペックとハンドラが乖離しうる。
2026 年のバランスポイント:
- 外部公開 API、複数クライアント(言語・チーム)がある API → spec-first がほぼ常に有利。
- 内部の単一サービス、素早いプロトタイピング、フルスタック単一チーム → code-first が速い。
- ハイブリッド も可: code-first で始め、スペックが安定したら spec-first に 固める 流れ。
ツール差も狭まった。TypeSpec や Smithy のような 高水準 spec-first ツール は執筆の摩擦を大きく減らし、FastAPI のような 代表的 code-first ツール は逆にスペック整合性検査を強化した。陣営論争より「この API の 寿命 と クライアント数」を見るほうが誠実だ。
12 章 · ツールチェーン — 2026 年の標準スタック
| 領域 | 標準に近いツール |
|---|---|
| OpenAPI ドキュメント UI | Scalar、Stoplight Elements(Swagger UI はレガシー) |
| OpenAPI エディタ | Stoplight Studio、Insomnia、Postman |
| クライアントコード生成 | openapi-typescript、oapi-codegen、openapi-generator |
| モックサーバ | Prism(Stoplight)、Mockoon |
| 契約テスト | Pact(Pact Broker、PactFlow) |
| Protobuf ツールチェーン | Buf(lint、breaking-change、BSR)、protoc(低レベル) |
| Protobuf → REST | Connect(Buf)、gRPC-Gateway |
| AsyncAPI エディタ | AsyncAPI Studio |
| AsyncAPI コード生成 | AsyncAPI Generator |
| GraphQL ツール | Apollo Studio、GraphiQL、GraphQL Code Generator、Hasura、Relay |
| TypeSpec | tsp CLI、VS Code 拡張 |
| Smithy | smithy build、IntelliJ プラグイン |
Swagger UI を デフォルト にする時代は終わった。Stoplight Elements と Scalar の両方が OpenAPI 3.1 を綺麗に扱い、ダークモード・検索・コードサンプル・テーマがずっと優れている。新規プロジェクトでは Scalar の埋め込みスニペット一行でドキュメントページが完結する。
13 章 · 意思決定フレーム — うちのチームは何を使うべきか
同じ「API」でも 対話相手 が違えば答えが変わる。
Q1: 対話相手は誰か?
├─ 外部開発者(公開 API) → OpenAPI 3.1 + Scalar/Stoplight
├─ 社内フロントエンド(多様な形) → GraphQL (Apollo Federation)
├─ 内部サービス間 → gRPC + Protobuf (Buf)
├─ イベント(Kafka・MQTT・WebSocket) → AsyncAPI 3.0
└─ AI エージェントのツール → JSON Schema 2020-12 (OpenAPI から再利用)
Q2: API の寿命は?
├─ 短期プロトタイプ → code-first (FastAPI など) で素早く
└─ 長期・外部公開 → spec-first (OpenAPI/TypeSpec/Smithy) で堅く
Q3: 一つの定義から複数の成果物が欲しいか?
├─ はい (REST + gRPC + クライアント SDK) → TypeSpec または Smithy
└─ いいえ → OpenAPI 単独で十分
Q4: クライアントが壊れるのをどれだけ恐れるか?
├─ 非常に → Pact で契約テスト追加
└─ 適度に → スペック + コード生成で十分
さらに、2026 年に 推奨しない 組み合わせ:
- 新規プロジェクトを OpenAPI 2.0(Swagger 2) で始める — 十年前の規格。必ず 3.1 を。
- gRPC をブラウザに直接 公開 — gRPC-Web/Connect を経由するか、別途 BFF を立てる。
protocを直接 呼ぶ — Buf がほぼすべての面で優位。- Swagger UI を新標準 にすること — 2026 年なら Scalar または Stoplight Elements。
- GraphQL の任意クエリ を外部にそのまま — persisted queries でホワイトリスト化を。
14 章 · マイグレーション — よくある三つの経路
A. OpenAPI 3.0 → 3.1
最も一般的なマイグレーションだ。互換性が非常に高く、ほとんどが 機械的 に終わる:
nullable: true→"type": ["string", "null"](またはanyOfでnull)。example→examples(スカラ一つならそのままでもよい)。- ツール固有のベンダー拡張(
x-キー)を確認。 - CI に OpenAPI 3.1 バリデータを追加。
B. 単一 OpenAPI → OpenAPI と AsyncAPI の分離
REST とイベントが一つのファイルに混在していたコードベースで、AsyncAPI にイベントを 分離 する:
- Kafka トピックとメッセージを抽出して AsyncAPI 3.0 ファイルに移す。
- メッセージペイロードスキーマは 共有 JSON Schema ファイル に切り出し、両側が
$refで指す。 - 一つのリポジトリに
openapi.yaml・asyncapi.yaml・schemas/を並べる。
C. 手書き OpenAPI → TypeSpec/Smithy への引き上げ
API が大きくなり反復が増えたとき:
- 既存の OpenAPI を TypeSpec/Smithy に インポート(公式コンバータが存在する)。
- 共通モデルとトレイト(認可・ページネーション・idempotency)を 横断的 に抽出。
- TypeSpec/Smithy を真実の源泉にし、OpenAPI は 生成物 に格下げ。
三経路ともに ビッグバン ではなく 漸進的 だ。2026 年のよくある失敗は「一度に全部書き換える」で、ほぼ常に失敗する。一領域(例: 一サービス、一トピック)を移してパターンを固めてから広げる。
15 章 · 信頼性 — スペックが実際に 守られる ようにする
スキーマが真実になるためには 守られる 必要がある。2026 年のよくあるガードレール:
- CI で OpenAPI/AsyncAPI を lint — Spectral、Redocly が標準。スタイル・禁止パターン・必須フィールドを検査。
- 破壊的変更の検出 — Buf の
buf breaking、OpenAPI はoasdiff。スペックを壊す PR は即赤。 - サーバの応答を 実際に スペックと突き合わせる — ライブトラフィックの一部をスペック検証器に流す(Optic、prism --validate など)。
- 契約テスト(Pact) — 消費者が 実際に依存している 形だけを捕まえる。
- AI ツールコールの引数検証 — モデルが間違えれば即座に拒否してモデルに再生成を要求。
この五つすべてが必要なわけではないが 一つは 必要だ。「スペックがある」と「スペックが守られる」は別の仕事である。
エピローグ — スキーマが真実
2026 年のバックエンドを一行で。API の単位はエンドポイントではなく、スキーマだ。
正しいスキーマ一枚から — ドキュメント・クライアント・サーバスタブ・テストフィクスチャ・AI ツール定義が すべて 生まれる。良いスキーマは、外部開発者には「今何があるか」を見せ、内部チームには「何が壊れてはいけないか」を伝え、AI エージェントには「どう呼べばよいか」を教える。
道具は多い — JSON Schema、OpenAPI 3.1、AsyncAPI 3.0、GraphQL、Protobuf、Smithy、TypeSpec、Pact。覚える名前が増えたのではなく、役割 が分化したのだ。一つの道具がすべての状況に勝つことはない。良いバックエンドエンジニアは 対話相手 に応じて道具を選ぶ。
14 項目チェックリスト
- 新規プロジェクトの OpenAPI は 3.1(2.0・3.0 ではなく)。
- 同じリポジトリに REST(OpenAPI)とイベント(AsyncAPI)が並ぶ。
- メッセージペイロードスキーマは 共有 JSON Schema に切り出して両側が
$ref。 - Swagger UI ではなく Scalar または Stoplight Elements を使う。
- CI に OpenAPI/AsyncAPI の lint(Spectral など)がある。
- 破壊的変更検出が CI にある(
buf breaking、oasdiff)。 - クライアント SDK はスペックから自動生成される。
- サーバスタブと型もスペックから生成される(手書き禁止)。
- Protobuf ツールチェーンは Buf —
protocを直接使わない。 - gRPC をブラウザに直接公開しない(Connect/gRPC-Web/BFF を介する)。
- AI ツール定義が 同じ JSON Schema コンポーネント を再利用している。
- AI ツールコールの引数を 実行前 にスキーマで検証する。
- 主要な結合には Pact(または同等の契約テスト)がある。
- GraphQL は 任意クエリ ではなく persisted queries でホワイトリスト化される。
アンチパターン 10 選
- コードとスペックを 両方手で 保とうとする — 必ずずれる。
- すべての場所に GraphQL — CRUD には OpenAPI のほうがシンプル。
- すべての場所に gRPC — ブラウザや外部開発者には摩擦が大きい。
- OpenAPI があるのに 検証されていない 状態 — それは Wiki ページであってスペックではない。
- イベントを OpenAPI に無理やり入れる — AsyncAPI 3.0 が答えだ。
- 今 Swagger 2 から始める — 十年前の規格。
protocを手で呼ぶ — Buf がほぼすべての面で優位。- SDK を多言語で出すわけでもないのに Smithy を強行 — エコシステムのコスパが悪い。
- AI ツール定義を OpenAPI と 別に 維持 — 同じコンポーネントを再利用するのが正解。
- すべての API を一度に spec-first に書き換えるビッグバン — 漸進的でないと失敗する。
次回予告
候補: Connect プロトコル深掘り — Buf が作る gRPC + REST の融合、AsyncAPI 3.0 で社内イベントカタログを作る、AI ツールコールスキーマの設計 — JSON Schema をモデル親和にする。
「エンドポイントではなくスキーマ。2026 年の良い API は手でコードを書くのではなく、スキーマから 落ちてくる ものだ。」
— 2026 年 API スキーマ地図、了。
参考 / References
- JSON Schema — draft 2020-12 specification
- JSON Schema — Getting Started
- OpenAPI Specification 3.1.0
- OpenAPI Initiative
- OpenAPI 3.2 work-in-progress
- AsyncAPI 3.0 specification
- AsyncAPI Initiative
- AsyncAPI 3.0 release notes
- GraphQL spec — October 2021
- GraphQL Foundation
- Apollo Federation v2 docs
- Protocol Buffers — google/protobuf
- gRPC project home
- Buf — Protobuf toolchain
- Buf Schema Registry (BSR)
- Connect protocol — Buf
- Smithy — AWS API IDL
- Smithy GitHub — smithy-lang/smithy
- TypeSpec — Microsoft
- TypeSpec GitHub — microsoft/typespec
- Pact docs
- PactFlow
- Stoplight Elements
- Scalar — API docs
- Redocly
- Spectral — OpenAPI/AsyncAPI linter
- oasdiff — OpenAPI diff
- OpenAI — function calling
- Anthropic — tool use
- Gemini — function calling
- openapi-typescript
- openapi-generator
현재 단락 (1/498)
2026 年のバックエンド会議はだいたいこう始まる。「エンドポイントを書く前に、まずスキーマを見せてくれ」。