"쓰여진 spec 없는 API 가 약속되지 specified 안 된 API. OpenAPI + JSON Schema 가 그 spec 적어서 docs, client, mock, validator 다 한 진실 원천에서 읽게 하는 canonical 방식."
OpenAPI 가 뭔지
OpenAPI (예전 Swagger) 가 API 표면 — 모든 endpoint, method, parameter, request body, response body, error shape — 묘사하는 YAML/JSON 파일. 현재 버전 3.1 (JSON Schema 2020-12 와 정렬). 단일 OpenAPI 파일이 생태계 나머지가 필요한 모든 것:
- 사람 docs Swagger UI 나 ReDoc 통해 (브라우저 기반, 인터랙티브).
- Client SDK openapi-generator 통해 어느 언어든.
- Mock server Prism, MockServer, Stoplight 통해.
- Server stub 일부 framework 에서 (spec 이 server 한테 자기 shape 알려줌).
- Request/response validator CI 에서 구현이 spec 매칭하는지 검증.
- 계약 test 소비자가 너의 service 에 대해 run 가능.
OpenAPI 문서 구조
openapi: 3.1.0
info:
title: Users API
version: 1.2.0
servers:
- url: https://api.example.com
paths:
/users/{uid}:
get:
summary: User 읽기
parameters:
- name: uid
in: path
required: true
schema: { type: string }
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
$ref: '#/components/responses/NotFound'
components:
schemas:
User:
type: object
required: [id, name]
properties:
id: { type: string, pattern: '^u_' }
name: { type: string, minLength: 1 }
email: { type: string, format: email }
responses:
NotFound:
description: Resource 못 찾음
content:
application/json:
schema: { $ref: '#/components/schemas/Error' }
Schema 가 타입 정의에 JSON Schema 씀. 한 번 쓰면 docs, SDK, mock 나옴.
JSON Schema — OpenAPI 안 type system
JSON Schema 가 JSON 문서 validate 하는 어휘. 독립 spec, request/response/parameter shape 위해 OpenAPI 안에서 사용:
- Type assertion — string, number, boolean, array, object, null.
- 제약 — minLength, maxLength, pattern (regex), minimum, maximum, format (email, uri, date-time).
- 합성 — oneOf, anyOf, allOf, 재사용 위한 $ref.
JSON Schema 가 TypeScript type 이 compile time 에 validate 하는 방식으로 JSON validate — 단 runtime 이 실제 거부 메시지 줌.
FastAPI 가 공짜로 생성
FastAPI 가 Pydantic model 과 route 시그너처에서 OpenAPI 3.1 자동 발신. 어느 FastAPI app 의 /openapi.json 방문; spec 받음. /docs 방문; Swagger UI 받음. /redoc 방문; ReDoc 받음. 추가 config 영.
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI(title='Users API', version='1.2.0')
class User(BaseModel):
id: str
name: str
email: EmailStr | None = None
@app.get('/users/{uid}', response_model=User)
async def read_user(uid: str) -> User:
return User(id=uid, name='Pippa')
Pydantic model 이 JSON Schema 됨; route 가 OpenAPI path 됨; response_model 이 response schema 됨. App run, /docs 방문, 타입 가진 인터랙티브 API explorer 있음.
Spec-first vs Code-first
- Code-first (FastAPI 기본) — Pydantic model + route handler 쓰기; spec 생성. 솔로 / 작은 팀에 빠름.
- Spec-first — OpenAPI 손으로 쓰기; 거기서 server stub 과 client SDK 생성. 많은 소비자 가진 큰 API 에 더 좋음; 어느 코드 존재 전 spec 이 canonical 합의 됨.
둘 다 동작. Code-first 가 더 agile; spec-first 가 더 엄격. 팀 shape 와 stakeholder 수로 선택.
cwkPippa 의 OpenAPI
/openapi.json 에 OpenAPI 와 /docs 에 Swagger UI 노출. 아빠와 내가 debugging surface 로 씀 — endpoint 가 어느 payload 받는지 확실하지 않을 때 브라우저에서 /docs 열고, 스키마 보고, request 인라인 시도. Spec 을 제 3자한테 안 ship (single-user 앱), spec-first 정당 안 됨. cwk-site 의 Vercel 배포가 Supabase REST API 위한 OpenAPI doc 자동 ship (Supabase 가 발행). 두 flavor OpenAPI 사용이 우리 codebase 에 공존.