API 계약 품질: Versioning·HATEOAS·OpenAPI
API를 계약으로 보고 버저닝·HATEOAS·OpenAPI·에러 모델을 통해 변경 비용을 통제하는 실무 기준
요약 (5–7줄)
API는 엔드포인트 모음이 아니라 조직·팀·클라이언트 간 계약이다.
버저닝은 기술 문제가 아니라 변경 비용을 언제, 누구에게 전가할지의 결정이다.
HATEOAS는 REST 성숙도 레벨 3이지만, 실무 채택률이 낮은 이유가 분명하다.
OpenAPI는 문서가 아니라 계약 검증·테스트·SDK 생성의 단일 입력물이다.
에러 처리와 Validation은 내부 품질이 아니라 사용자 커뮤니케이션 설계다.
이 편의 핵심은 “API 변경을 사건(event)으로 다루는 태도”다.
1. 정의
API 설계 품질이란
- 변경이 발생했을 때
- 누가, 언제, 얼마나 고통을 받는지를
의도적으로 통제하는 능력이다.
좋은 API는 기능이 많은 API가 아니라
변경이 예측 가능한 API다.
2. 직관
API를 코드로 보면 컨트롤러다.
API를 계약으로 보면 약속 위반 시 비용이 발생하는 문서다.
버저닝, 스키마, 에러 포맷은 모두
“이 약속을 어떻게 지킬 것인가”에 대한 장치다.
3. 작동원리: API를 계약으로 운영한다는 것
1) 요청/응답 스키마가 계약의 본문
2) 버전은 계약의 개정판
3) 에러는 계약 위반 시의 공식 통보
4) OpenAPI는 계약의 기계 판독본
이 관점이 없으면 API는 변경 이력 없는 임시 인터페이스가 된다.
4. API Versioning 전략 3종 비교
4.1 URI 버저닝 (/v1/orders)
- 장점: 명확, 캐시/라우팅 단순
- 단점: URL 증식, 리소스 동일성 훼손
- 적합: 다중 외부 클라이언트, B2B
4.2 헤더 버저닝 (X-API-Version)
- 장점: URL 안정
- 단점: 가시성 낮음, 디버깅 비용
- 적합: 내부 API, 통제된 환경
4.3 미디어 타입 버저닝 (application/vnd.company.v1+json)
- 장점: REST 이론상 정합
- 단점: 학습 비용, 실무 복잡
- 적합: 표준화 조직, 강한 계약 문화
선택 기준
- 외부 노출/다중 클라이언트 → URI
- 내부/단일 소비자 → 헤더
- 장기 표준 계약 → 미디어 타입
5. 버전 관리가 필요한 트리거 조건
- 클라이언트 수가 2종 이상
- 배포 주기가 서로 다름
- 필드 삭제/의미 변경 발생
- B2B 계약 포함
“아직 v1이면 괜찮다”는 판단은
미래 변경 비용을 부채로 쌓는 결정이다.
6. HATEOAS: 왜 안 쓰고, 왜 여전히 가치가 있는가
6.1 레벨 3 REST로서의 의미
- 상태 전이 링크를 응답에 포함
- 클라이언트는 URL을 하드코딩하지 않음
6.2 실무에서 안 쓰는 이유
- 프론트엔드가 이미 흐름을 알고 있음
- 응답 복잡도 증가
- 테스트/문서 비용 상승
6.3 그럼에도 남는 가치
- 리소스 상태 전이 모델링 사고
- 워크플로우 중심 API 설계
- 내부 도메인 이해도 향상
실무에서는 사고 도구로만 채택하는 경우가 대부분이다.
7. OpenAPI의 진짜 역할
OpenAPI는 문서가 아니다.
- 계약: 요청/응답 스키마의 단일 기준
- 검증: 요청 Validation 자동화
- 테스트: 계약 기반 테스트 생성
- 배포: 클라이언트 SDK 생성
OpenAPI가 최신이 아니라면
실제 계약은 이미 붕괴된 상태다.
8. 에러 처리 = 사용자 커뮤니케이션 설계
ControllerAdvice/Validation의 목적은
“예외를 잡는 것”이 아니라 의미를 전달하는 것이다.
- HTTP 상태 코드: 실패의 범주
- 에러 코드: 기계 판독
- 메시지: 인간 판독
이 3가지를 섞어 쓰면
API는 즉시 신뢰를 잃는다.
9. 트레이드오프
- 장점: 변경 관리, 예측 가능성, 신뢰
- 비용: 초기 설계 시간, 문서/테스트 유지
API 품질은 초기엔 느리게, 장기엔 빠르게 만든다.
10. 최소 예시
10.1 Toy 예시: v1 → v2 깨지는 변경
1) 필드 삭제: totalPrice 제거
- 대응: v1 유지, v2에서만 제거 (브레이킹)
2) 필드 의미 변경: status 값 재정의
- 대응: 새 필드 추가, 기존 유지 (호환)
핵심: 의미 변경은 삭제보다 더 위험하다.
10.2 실무 예시: 다중 클라이언트
- 웹: 주 1회 배포
- 모바일: 월 1회 배포
- B2B: 분기 단위 계약
전략:
- URI 버저닝
- 최소 2개 버전 병행
- 폐기 일정 사전 고지
11. 실무 함정 → 해결 패턴
| 함정 | 결과 | 해결 패턴 |
|---|---|---|
| 무버전 API | 묵시적 브레이킹 | 명시적 버전 |
| 에러 포맷 불일치 | 클라이언트 혼란 | 표준 에러 모델 |
| 문서 수동 관리 | 계약 붕괴 | OpenAPI 단일화 |
12. 오해/실수 3개 + 교정
1) “v1은 자유롭게 바꿔도 된다” → 가장 위험
2) “HATEOAS는 쓸모없다” → 사고 도구로 유효
3) “OpenAPI는 문서” → 계약 원본
13. 판단 기준
사용해야 할 때
- 외부/다중 클라이언트 API
- B2B 계약 존재
- 장기 운영 서비스
쓰지 말아야 할 때
- 단기 실험용 API
- 단일 내부 소비자
- 변경 폐기 예정 서비스
14. 재학습 체크리스트 (10–14)
- 이 API의 소비자는 누구인가?
- 배포 주기는 서로 다른가?
- 브레이킹 변경 기준이 정의돼 있는가?
- 버전 폐기 정책이 있는가?
- 에러 포맷은 일관적인가?
- Validation 실패 메시지는 명확한가?
- OpenAPI가 단일 진실원인가?
- SDK 생성이 가능한가?
- 문서와 구현이 동기화돼 있는가?
- 의미 변경을 새 필드로 처리하는가?
- HATEOAS적 사고를 적용했는가?
- 계약 변경 시 공지 경로가 있는가?
