API 문서 생성기
기존 라우트 핸들러 코드에서 API 문서를 추출합니다. 소스 코드를 읽고, 스키마를 추론하며, OpenAPI 명세, TypeScript 타입, 실행 가능한 curl 예제를 생성합니다. 이는 설계 의도가 아닌 실제 구현을 기반으로 합니다.
활성화 트리거
다음과 같은 요청 시 활성화: "API 문서 생성", "코드에서 OpenAPI", "엔드포인트 문서화", "API 레퍼런스", "swagger 생성", "엔드포인트 문서", "API 타입 생성", "API용 curl 예제"
다음과 같은 경우에는 사용하지 마세요: 처음부터 API 설계 --> api-architect | 소스 코드 없이 OpenAPI 작성 --> openapi-spec-writer | API 테스팅 --> test-automation-expert
핵심 기능
- Express, Next.js App Router, Next.js Pages API 라우트, Fastify, Hono 핸들러에서 라우트 정의 추출
- TypeScript 타입, Zod 스키마 또는 런타임 유효성 검사에서 요청/응답 스키마 추론
- 정확한 경로 매개변수, 쿼리 문자열 및 요청 본문이 포함된 OpenAPI 3.0/3.1 명세 생성
- 실제 API 계약과 일치하는 TypeScript 타입 정의 생성
- 모든 엔드포인트에 대해 실제 샘플 데이터를 사용한 curl 예제 생성
- 미들웨어 체인 추적을 통한 인증 요구 사항 문서화
- 속도 제한 구성 식별 및 엔드포인트별 제한 문서화
- 핸들러의 throw/return 패턴 분석을 통한 오류 응답 분류
- 문서화되지 않은 엔드포인트 탐지 (존재하지만 JSDoc이나 스키마가 없는 라우트)
프레임워크 감지
무엇이든 생성하기 전에 프레임워크를 식별하십시오. 추출 전략은 크게 다릅니다.
Express / Express 유사
신호: app.get(), router.post(), express.Router()
라우트 소스: app._router.stack 또는 명시적 라우터 파일
미들웨어 체인: 인증 감지를 위해 app.use() 순서가 중요함
라우트 등록 패턴을 찾으십시오:
router.get('/users/:id', authenticate, getUser)-- 핸들러 앞의 미들웨어는 인증 필요를 의미app.use('/api/v1', rateLimiter({ max: 100 }), apiRouter)-- 하위 트리에 적용된 속도 제한기
Next.js App Router
신호: GET, POST, PUT, DELETE, PATCH를 내보내는 route.ts 파일
라우트 소스: app/api/ 디렉토리의 파일 시스템 규칙
미들웨어 체인: 디렉토리 경계에 있는 middleware.ts
경로 매개변수는 폴더 이름에서 가져옵니다: app/api/users/[id]/route.ts --> /api/users/{id}
Next.js Pages API 라우트
신호: default export handler가 있는 pages/api/**/*.ts 파일
라우트 소스: 파일 시스템 규칙
메서드 라우팅: 핸들러 내부의 req.method switch
Fastify
신호: fastify.get(), fastify.route(), 라우트 옵션의 schema 속성
라우트 소스: fastify.register()를 사용한 플러그인 등록
스키마: Fastify 라우트는 종종 자체 JSON 스키마를 선언합니다 -- 추출하여 변환
Fastify는 라우트가 자주 자체 스키마를 선언하기 때문에 문서화하기 가장 쉬운 프레임워크입니다. 추론하기 전에 기존 schema.body, schema.response, schema.querystring을 우선 추출하십시오.
Hono
신호: app.get(), app.post(), Hono(), zValidator()
라우트 소스: Hono 인스턴스에 대한 메서드 체이닝
유효성 검사: zValidator 미들웨어를 통한 zod 기반
zValidator와 함께 Hono는 Zod 스키마를 직접 제공합니다. Zod --> JSON Schema --> OpenAPI 스키마로 변환하십시오.
추출 프로세스
1단계: 라우트 발견
라우트 등록을 위해 프로젝트를 스캔하십시오. 단일 진입점에 의존하지 마십시오 -- 프레임워크는 종종 라우트를 여러 파일에 분산시킵니다.
# Express: 라우터 파일 찾기
grep -rl "express.Router\|app.get\|app.post\|router\." src/ --include="*.ts" --include="*.js"
# Next.js App Router: 라우트 핸들러 찾기
find src/app/api -name "route.ts" -o -name "route.js"
# Next.js Pages: API 라우트 찾기
find src/pages/api -name "*.ts" -o -name "*.js"
# Fastify: 라우트 등록 찾기
grep -rl "fastify\.\(get\|post\|put\|delete\|route\)" src/ --include="*.ts"
# Hono: 라우트 정의 찾기
grep -rl "app\.\(get\|post\|put\|delete\|patch\)" src/ --include="*.ts"
2단계: 스키마 추출
각 라우트에 대해 요청 및 응답 형태를 식별하십시오.
스키마 소스 우선 순위:
- 명시적 Zod/Joi/Yup 유효성 검사 스키마 (가장 높은 신뢰도)
- 요청/응답에 대한 TypeScript 타입 어노테이션
- JSON 스키마 선언 (Fastify)
- JSDoc @param / @returns 어노테이션
- 응답 구축에서 런타임 추론 (가장 낮은 신뢰도 -- 근사치로 표시)
런타임 추론(옵션 5)을 사용하는 경우, 항상 OpenAPI 출력에서 스키마를 x-inferred: true로 표시하여 소비자가 불완전할 수 있음을 알 수 있게 하십시오.
3단계: 인증 추적
각 라우트에 대한 미들웨어 체인을 따라 인증 요구 사항을 결정하십시오:
- 인증 미들웨어 없음:
security: [](공개)로 표시 - Bearer 토큰 미들웨어:
security: [{ bearerAuth: [] }]로 표시 - API 키 미들웨어:
security: [{ apiKeyAuth: [] }]로 표시 - 세션/쿠키 인증:
security: [{ cookieAuth: [] }]로 표시 - 여러 인증 옵션: 보안 배열에 모든 것을 대안으로 나열
4단계: 오류 분류
각 핸들러를 읽고 모든 오류 응답을 나열하십시오:
res.status(400).json(...)또는throw new BadRequestError(...)--> 400 응답 스키마res.status(401)--> 401 (명시적 throw가 없더라도 인증 미들웨어가 있는 경우 포함)res.status(404)--> 404res.status(409)--> 409 (충돌, 생성 작업에서 흔함)res.status(422)--> 422 (유효성 검사 실패)res.status(429)--> 429 (속도 제한, 속도 제한기 미들웨어가 감지된 경우 포함)res.status(500)--> 500 (가능성으로 항상 포함)
5단계: 출력 생성
세 가지 결과물을 생성하십시오:
- OpenAPI 명세 (JSON이 아닌 YAML -- 더 읽기 쉽고 diff하기 쉬움)
- TypeScript 타입 (모든 요청/응답 타입이 포함된 독립 실행형
.d.ts파일) - curl 예제 (엔드포인트당 하나, 헤더와 샘플 페이로드 포함)
의사 결정 포인트
코드베이스에 유효성 검사 스키마가 없는 경우
핸들러가 Zod/Joi 유효성 검사 없이 원시 req.body를 수락하는 경우, 사용법에서 타입을 추론해야 합니다. 다음을 찾으십시오:
- 속성 접근 패턴:
req.body.name,req.body.email-->{ name: string, email: string } - 구조 분해:
const { name, email } = req.body--> 동일한 추론 - 데이터베이스 삽입 호출:
db.users.create({ name: body.name })-- 가능한 경우 DB 스키마와 교차 참조
정보 수준에서 경고와 함께 전체 명세를 표시하십시오: x-schemas-inferred: true
라우트가 동적 경로 세그먼트를 사용하는 경우
- Express:
:id--> OpenAPI{id} - Next.js:
[id]--> OpenAPI{id} - Next.js catch-all:
[...slug]--> OpenAPI{slug}(배열 동작에 대한 참고 사항 포함) - Fastify:
:id--> OpenAPI{id} - Hono:
:id--> OpenAPI{id}
응답 형태가 상태 코드에 따라 다른 경우
각 상태 코드를 자체 스키마로 문서화하십시오. 200과 201이 다른 경우 하나의 스키마로 병합하지 마십시오. 일반적인 패턴:
responses:
'200':
description: 사용자 찾음
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: 사용자를 찾을 수 없음
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
속도 제한이 엔드포인트마다 다른 경우
OpenAPI 확장을 사용하여 속도 제한을 문서화하십시오:
x-rate-limit:
requests: 100
window: 60s
scope: per-api-key
속도 제한기가 전역(앱 수준에서 한 번 적용)인 경우, 최상위 info 섹션에 문서화하십시오. 라우트별인 경우 각 작업에 문서화하십시오.
TypeScript 타입 생성
OpenAPI 명세와 정확히 일치하는 타입을 생성하십시오. 코드베이스에서 사용하는 경우 ID에 브랜드 타입을 사용하십시오.
// OpenAPI 명세에서 생성됨 -- 수동으로 편집하지 마십시오
export interface CreateUserRequest {
name: string;
email: string;
role?: 'admin' | 'member' | 'viewer';
}
export interface CreateUserResponse {
id: string;
name: string;
email: string;
role: 'admin' | 'member' | 'viewer';
createdAt: string; // ISO 8601
}
export interface ErrorResponse {
error: {
code: string;
message: string;
details?: Array<{
field: string;
issue: string;
}>;
};
}
export interface PaginatedResponse<T> {
data: T[];
meta: {
page: number;
perPage: number;
total: number;
hasMore: boolean;
};
}
Curl 예제 생성
엔드포인트당 하나의 curl을 생성하십시오. 현실적이지만 명백히 가짜 데이터를 사용하십시오.
# GET /api/users/:id -- 단일 사용자 가져오기
curl -X GET https://api.example.com/api/users/usr_abc123 \
-H "Authorization: Bearer sk_test_..." \
-H "Accept: application/json"
# POST /api/users -- 새 사용자 생성
curl -X POST https://api.example.com/api/users \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Ada Lovelace",
"email": "[email protected]",
"role": "member"
}'
# GET /api/users -- 페이지네이션으로 사용자 목록 조회
curl -X GET "https://api.example.com/api/users?page=1&perPage=20&role=admin" \
-H "Authorization: Bearer sk_test_..." \
-H "Accept: application/json"
curl 예제 규칙:
- 항상 전체 URL 포함 (
https://api.example.com을 기본값으로 사용) - 모든 필수 헤더 포함
- 요청 본문에
-d와 함께 형식화된 JSON 사용 - 쿼리 매개변수가 포함된 URL은 따옴표로 묶음
- GET에도 HTTP 메서드를 명시적으로 표시
- 인증 토큰에
sk_test_...사용 (명백히 가짜) - "string" 또는 "test"가 아닌 현실적인 필드 값 사용
안티 패턴
1. 이상적인 API 문서화
증상: 명세가 아직 코드에 존재하지 않는 엔드포인트를 설명함 수정: 코드가 실제로 구현한 것만 문서화하십시오. 계획된 엔드포인트가 주석이나 명세 파일에 있지만 핸들러에 없는 경우 제외하십시오.
2. 미들웨어 부작용 무시
증상: 문서는 엔드포인트가 공개라고 표시하지만 실제로는 상위 미들웨어를 통해 인증이 필요함
수정: 앱 루트에서 핸들러까지 전체 미들웨어 체인을 추적하십시오. 라우트 정의 위에 router.use(auth)가 있으면 해당 아래의 모든 라우트는 인증이 필요합니다.
3. 요청 본문 형태 가정
증상: 유효성 검사가 없어서 req.body를 any 또는 object로 문서화
수정: 사용법(속성 접근, 구조 분해, 데이터베이스 호출)에서 추론하십시오. x-inferred: true로 표시하십시오. Zod 유효성 검사 추가를 권장하십시오.
4. 평면적인 오류 문서화
증상: 모든 엔드포인트가 세부 정보 없이 동일한 일반 "400 Bad Request"를 나열함 수정: 각 핸들러의 오류 경로를 읽으십시오. 반환된 특정 오류 코드와 메시지를 문서화하십시오. 다른 유효성 검사 실패는 다른 예제 응답을 보여야 합니다.
5. 오래된 생성 문서
증상: 명세가 한 번 생성된 후 코드가 변경되어도 업데이트되지 않음
수정: 잘 알려진 경로(docs/openapi.yaml)에 생성하십시오. 재생성하고 커밋된 명세와 diff하는 CI 검사를 추가하십시오. 차이가 나면 빌드를 실패 처리하십시오.
6. 페이지네이션 문서 누락
증상: 목록 엔드포인트가 페이지네이션에 대한 쿼리 매개변수 스키마 없이 문서화됨
수정: 핸들러가 page, limit, cursor, offset 또는 유사한 매개변수를 지원하는 경우 기본값과 최대값을 사용하여 문서화하십시오.
7. 문서화되지 않은 파일 업로드
증상: multipart/form-data 엔드포인트가 JSON으로 문서화됨
수정: multer, formidable, busboy 또는 프레임워크 네이티브 파일 처리를 감지하십시오. 적절한 바이너리 스키마와 함께 multipart/form-data 콘텐츠 유형을 사용하십시오.
품질 체크리스트
[ ] 코드베이스의 모든 라우트 핸들러에 해당 OpenAPI 작업이 있음
[ ] 경로 매개변수가 코드와 명세 간에 일치함 (:id와 {userId} 불일치 없음)
[ ] 요청 본문 스키마가 모든 필수 및 선택적 필드를 포함함
[ ] 응답 스키마가 실제 JSON 구조와 일치함 (핸들러 반환 값을 읽어 확인)
[ ] 인증 요구 사항이 미들웨어 체인 분석과 일치함
[ ] 속도 제한 정보가 속도 제한 미들웨어가 존재하는 곳에 문서화됨
[ ] 오류 응답이 핸들러의 실제 throw/return 문에서 분류됨
[ ] curl 예제가 실행 중인 인스턴스에 대해 성공적으로 실행됨
[ ] TypeScript 타입이 오류 없이 컴파일됨
[ ] 문서화되지 않은 x-inferred 스키마가 없음 (각 플래그 지정된 항목에 적절한 유효성 검사를 위한 TODO가 있음)
[ ] 페이지네이션 매개변수가 기본값과 최대값으로 문서화됨
[ ] 파일 업로드 엔드포인트가 multipart/form-data 콘텐츠 유형을 사용함
[ ] OpenAPI 명세가 spectral 또는 swagger-cli lint로 검증됨
[ ] 생성된 명세가 CI diffing을 위해 알려진 경로에 커밋됨
출력 아티팩트
docs/openapi.yaml-- 완전한 OpenAPI 3.0/3.1 명세docs/api-types.d.ts-- 모든 요청/응답 형태에 대한 TypeScript 타입 정의docs/api-examples.sh-- 모든 엔드포인트에 대한 실행 가능한 curl 예제docs/api-coverage.md-- 문서화된 vs 문서화되지 않은 라우트를 보여주는 보고서
검증
# 생성된 OpenAPI 명세 린트
npx @stoplight/spectral-cli lint docs/openapi.yaml
# 명세 구조 검증
npx swagger-cli validate docs/openapi.yaml
# TypeScript 클라이언트 생성하여 타입 컴파일 확인
npx openapi-typescript docs/openapi.yaml -o /tmp/api-check.d.ts
tsc --noEmit /tmp/api-check.d.ts
# 마지막으로 커밋된 명세와 차이 비교 (CI 검사)
diff <(cat docs/openapi.yaml) <(npx tsx scripts/generate-api-docs.ts --stdout) && echo "명세가 최신 상태입니다" || echo "명세가 오래되었습니다"
적용 범위: OpenAPI 생성 | TypeScript 타입 추출 | Curl 예제 생성 | 인증 문서화 | 속도 제한 문서화 | 오류 코드 분류
함께 사용: api-architect (먼저 설계, 나중에 문서화) | openapi-spec-writer (수동 작성) | test-automation-expert (생성된 명세에 대한 계약 테스트)