API 스펙을 쓰는 팀은 많습니다. 하지만 스펙이 실제 운영의 기준이 되는 팀은 생각보다 적습니다. 문서 사이트에는 status: string이라고 적혀 있는데 실제 응답은 숫자를 주고, SDK는 3개월 전 스펙에서 생성되어 있고, 게이트웨이 정책은 또 별도 YAML로 관리됩니다. 이 상태에서 API 변경이 들어오면 리뷰어는 문서, 코드, 테스트, 클라이언트 영향, 배포 정책을 따로 확인해야 합니다. 결국 계약은 있는데 계약이 의사결정을 막아주지 못합니다.
요즘 흐름에서 중요한 건 “OpenAPI를 쓰자” 수준이 아닙니다. API 계약을 제품 운영의 Source of Truth로 놓고, 그 계약에서 mock, SDK, compatibility test, gateway policy, change review가 파생되게 만드는 것입니다. 저는 이 방향이 REST API 설계, API Versioning, Consumer Driven Contract Testing이 플랫폼 엔지니어링 쪽으로 확장된 흐름이라고 봅니다.
이 글에서 얻는 것
- Contract-first API가 단순 문서 작성 방식이 아니라 변경 관리와 릴리스 안정성의 문제라는 점을 이해할 수 있습니다.
- OpenAPI, TypeSpec, protobuf 같은 계약을 어떤 산출물과 연결해야 실무 효과가 나는지 기준을 잡을 수 있습니다.
- API 변경 승인에서 볼 숫자와 조건, 그리고 과도한 형식주의를 피하는 방법을 정리할 수 있습니다.
핵심 개념/이슈
1) 문제는 스펙 부재보다 spec drift다
많은 조직이 API 스펙을 만들고도 실패합니다. 이유는 스펙이 없어서가 아니라 스펙과 실제 구현이 계속 벌어지기 때문입니다.
대표적인 drift는 아래처럼 생깁니다.
- 응답 필드가 코드에서는 추가됐지만 스펙에는 없다.
- nullable 여부가 문서와 다르다.
- 에러 코드가 실제 운영에서만 늘어난다.
- pagination, filtering, sorting 규칙이 endpoint마다 다르다.
- SDK는 예전 스펙으로 생성되어 클라이언트가 런타임 에러를 맞는다.
이런 drift가 쌓이면 계약은 신뢰를 잃습니다. 개발자는 문서를 보지 않고 실제 응답을 찍어보게 되고, 클라이언트는 방어 코드를 늘립니다. 결국 contract-first가 아니라 traffic-first reverse engineering으로 돌아갑니다.
시작 기준은 단순합니다. 핵심 API Top 20에 대해 매일 또는 PR마다 actual_response_sample과 declared_schema를 비교하고, drift를 24시간 안에 잡아야 합니다. drift 감지 시간이 일주일을 넘으면 스펙은 운영 도구가 아니라 장식에 가깝습니다.
2) Contract-first는 “먼저 쓰기"보다 “파생 산출물 일치"가 중요하다
contract-first라는 말을 너무 문자 그대로 받아들이면, 구현 전에 긴 YAML을 쓰는 프로세스만 생깁니다. 하지만 실무 효과는 작성 순서보다 하나의 계약에서 여러 산출물이 일관되게 나온다는 데 있습니다.
좋은 계약은 최소 아래를 만들어야 합니다.
- mock server 또는 fixture
- server-side validation 또는 handler stub
- client SDK와 type definition
- compatibility test
- documentation
- gateway policy 일부(rate limit, auth scope, request size limit)
- changelog와 migration note
즉 스펙은 사람이 읽는 문서이면서 동시에 CI와 런타임이 읽는 입력이어야 합니다. 이 관점은 Tool Contract Test와도 닮아 있습니다. 도구든 API든, 계약이 실행 경로에 연결되지 않으면 변경을 막지 못합니다.
3) breaking change 판정은 감이 아니라 규칙이어야 한다
API 변경 리뷰에서 가장 자주 흐려지는 질문은 “이게 breaking인가?“입니다. 실무에서는 아래 규칙부터 자동화하는 편이 좋습니다.
breaking으로 보는 변경:
- 필수 응답 필드 삭제 또는 타입 변경
- nullable → non-nullable 변경
- enum 값 삭제 또는 의미 변경
- request required field 추가
- 에러 응답 포맷 변경
- pagination cursor 의미 변경
- 인증 scope 강화
대부분 안전한 변경:
- optional 응답 필드 추가
- enum 값 추가(단, 클라이언트가 unknown enum을 처리할 때)
- 새 endpoint 추가
- 문서 설명 보강
숫자 기준도 필요합니다. 예를 들어 breaking_change_block_rate를 95% 이상으로 두고, breaking change가 필요하면 consumer_impact_report와 migration_window가 없을 때 merge를 막습니다. 외부 공개 API라면 최소 30~90일 deprecation window를 두는 편이 현실적입니다. 내부 API라도 핵심 consumer가 3개 이상이면 “그냥 같이 고치면 되지"가 아니라 버전 전략을 세워야 합니다.
4) API 계약은 gateway와 observability까지 내려와야 한다
문서와 SDK까지만 연결하면 절반입니다. 실제 운영에서는 게이트웨이와 관측성까지 계약을 읽어야 합니다.
예를 들어 계약에 아래 속성이 있어야 합니다.
- endpoint별 auth scope
- request body size limit
- rate limit tier
- timeout class
- idempotency requirement
- PII field marker
- deprecation status
이 정보가 있으면 gateway policy, 로그 마스킹, 알람 라벨, 비용 분류를 같은 기준으로 만들 수 있습니다. 반대로 이 정보를 각 시스템에 따로 적으면 시간이 지나며 어긋납니다. 보안과 운영 정책은 OWASP 체크리스트와 구조적 로깅 기준과 연결해야 합니다.
5) AI 코딩 시대에는 API 계약의 가치가 더 커진다
AI 도구가 endpoint나 SDK 코드를 빠르게 생성할수록, 명확한 계약의 가치가 커집니다. 모델은 주변 코드 패턴을 보고 그럴듯한 요청/응답을 만들 수 있지만, 실제 제품에서 허용되는 auth scope, 에러 포맷, pagination 규칙, deprecation 정책을 자동으로 알지는 못합니다.
계약이 잘 되어 있으면 AI 도구도 더 안전하게 쓸 수 있습니다.
- 새 endpoint 생성 시 기본 policy와 에러 포맷을 강제할 수 있다.
- SDK 재생성으로 수동 타입 불일치를 줄일 수 있다.
- contract test가 AI 생성 변경의 회귀를 잡는다.
- 리뷰어는 전체 코드를 다 읽기보다 계약 diff와 영향 범위를 먼저 본다.
이 흐름은 Test Evidence Pipeline과도 이어집니다. AI가 코드를 많이 만들수록, 사람은 산출물 자체보다 계약과 증거를 기준으로 검토해야 합니다.
실무 적용
1) API Top 20부터 시작한다
처음부터 모든 endpoint를 contract-first로 바꾸면 보통 실패합니다. 우선순위는 아래가 좋습니다.
- 외부 파트너나 모바일 앱이 쓰는 API
- 결제, 주문, 인증처럼 변경 비용이 큰 API
- consumer가 3개 이상인 내부 API
- 장애 시 고객 영향이 큰 조회 API
- 신규 개발이 잦은 도메인 API
이 Top 20에 대해 먼저 계약, 실제 응답 샘플, SDK 생성, compatibility test를 붙입니다. 전체 커버리지보다 중요한 건 중요 API의 drift를 줄이는 것입니다.
2) 최소 CI gate를 만든다
초기 gate는 복잡할 필요가 없습니다.
- 스펙 문법 검사
- 스펙 diff에서 breaking change 탐지
- handler 또는 fixture와 schema 검증
- SDK 생성 결과가 clean인지 확인
- 주요 consumer contract test 실행
추천 기준:
spec_lint_pass_rate: 100%schema_drift_detection_time: 24시간 이하sdk_generation_lead_time: 10분 이하breaking_change_without_approval: 0건undocumented_error_response_rate: 5% 이하
여기서 핵심은 gate가 너무 느려지지 않는 것입니다. API 스펙 변경 때마다 40분 CI가 돌면 개발자는 우회로를 찾습니다. 초기에는 Top 20 API의 핵심 검증을 10분 안에 끝내는 쪽이 낫습니다.
3) 계약 diff를 리뷰의 첫 화면으로 둔다
API 변경 PR에서 가장 먼저 봐야 하는 것은 코드 diff가 아니라 계약 diff입니다.
리뷰어 질문은 이렇게 바뀌어야 합니다.
- request/response shape가 바뀌었는가?
- nullable, enum, error code가 바뀌었는가?
- consumer 영향 범위가 계산됐는가?
- SDK와 문서가 같은 커밋에서 갱신됐는가?
- gateway policy나 auth scope 변화가 있는가?
- rollback 또는 deprecation 계획이 있는가?
이 순서가 잡히면 코드 리뷰가 훨씬 가벼워집니다. 구현 세부는 테스트와 코드에서 보고, 호환성 리스크는 계약 diff에서 먼저 거르는 구조가 됩니다.
트레이드오프/주의점
Contract-first는 만능이 아닙니다. 잘못 도입하면 개발 속도만 늦추는 형식주의가 됩니다.
주의할 점은 네 가지입니다.
- 스펙이 너무 추상적이면 구현과 분리된다
- 실제 fixture와 validation이 없으면 문서만 예뻐집니다.
- 모든 endpoint에 같은 엄격도를 적용하면 피로도가 커진다
- 내부 실험 API와 외부 결제 API의 gate는 달라야 합니다.
- 생성 코드에 과신하면 디버깅 능력이 떨어진다
- SDK 생성은 반복을 줄이는 도구이지, API 설계 판단을 대신하지 않습니다.
- 버전 전략 없이 breaking 차단만 하면 변화가 막힌다
- deprecation window, dual-write/dual-read, migration guide가 같이 필요합니다.
의사결정 기준은 간단합니다. consumer가 적고 빠르게 바뀌는 내부 실험 API는 lightweight spec만 둬도 됩니다. 반대로 외부 앱, 파트너, 결제/정산/인증처럼 변경 비용이 큰 API는 엄격한 contract gate를 두는 편이 맞습니다. 속도보다 호환성이 비싼 영역을 먼저 고르는 것이 핵심입니다.
체크리스트 또는 연습
도입 체크리스트
- 핵심 API Top 20이 정의되어 있다.
- 각 API의 contract owner가 있다.
- 실제 응답 샘플과 선언 스키마를 비교한다.
- breaking change 규칙이 자동화되어 있다.
- SDK, mock, 문서가 같은 계약에서 생성된다.
- gateway policy와 auth scope가 계약과 연결되어 있다.
- consumer impact report 없이 breaking change가 merge되지 않는다.
- deprecation window와 migration note 템플릿이 있다.
연습
운영 중인 API 하나를 골라 아래를 확인해 보세요.
- 문서의 response schema와 실제 production response가 같은가?
- enum 값이 추가되면 기존 클라이언트가 unknown 값을 처리할 수 있는가?
- request required field를 하나 추가하면 어떤 consumer가 깨지는지 10분 안에 알 수 있는가?
- SDK는 언제, 어떤 스펙에서 생성되었는가?
- gateway의 auth/rate limit 정책은 스펙과 같은 저장소에서 추적되는가?
이 질문에 세 개 이상 답하기 어렵다면, 지금 필요한 것은 더 예쁜 문서 사이트가 아니라 계약을 운영 경로에 연결하는 작업입니다.
결론
Contract-first API의 핵심은 “스펙을 먼저 쓰자"가 아닙니다. 핵심은 하나의 계약이 여러 운영 산출물의 기준점이 되게 만드는 것입니다. 문서, mock, SDK, 테스트, gateway policy, 변경 승인 기준이 서로 다른 곳에서 관리되면 API는 시간이 지날수록 불신의 대상이 됩니다.
반대로 계약이 실제 CI와 런타임에 연결되면 API 변경은 훨씬 다루기 쉬워집니다. 리뷰어는 계약 diff를 먼저 보고, consumer 영향이 자동으로 계산되고, SDK와 문서는 같은 변경에서 갱신됩니다. 이 정도가 되어야 API 스펙은 문서가 아니라 제품 운영의 Source of Truth라고 부를 수 있습니다.
💬 댓글