"API 는 변해. 의도적으로 versioning 하거나 실수로 client 깨거나. 1일차에 전략 골라, 몇 년 동안 v2 안 ship 해도."
Versioning 이 해결하는 문제
API 는 결정 누적: 필드 이름, error format, status code 선택, 기본값. 일부 결정은 잘못된 것으로 판명. 일부 시장은 밑에서 변함. Production 이미 10,000 client 있는데 API 고치거나 확장하고 싶음. Versioning 은 "이 버전은 안정; 다음 버전은 다를 수 있어" 라고 publish 하는 계약.
요령: request 의 어디 에 version 살지 — URL path, header, media type, query parameter — 골라서 일관성 유지.
네 가지 전략 (각각 언제 맞나)
1. URL path versioning. https://api.example.com/v1/users vs /v2/users. Stripe, AWS, GitHub (현재), Twilio, 알아볼 만한 대부분 API.
- Pro: 로그와 curl 에 보임; cache-friendly; 어느 framework 에서나 routing 쉬움.
- Con: URI 를 version 에 coupling (purist REST 는 각 resource 가 canonical URI 하나 가져야 한다 주장).
- 판결: 대부분 API 의 기본 선택. 가르치기 쉽고, 운영 쉬움.
2. Custom header versioning. X-API-Version: 2. LinkedIn (역사적), 일부 enterprise API.
- Pro: version 간 URI 동일; REST purist 한텐 깔끔.
- Con: header log 안 하면 로그에 안 보임; CDN caching 에
Vary: X-API-Version필요; 발견 가능성 낮음. - 판결: 동작은 하는데 운영 세금 실제임.
3. Media-type versioning. Accept: application/vnd.example.v2+json. GitHub 가 v4 전에 썼음; 일부 hypermedia API.
- Pro: version 이 representation 의 일부, 가장 순수한 REST 해석.
- Con: Tooling (브라우저, OpenAPI editor, curl user) 가 이걸 어색하게 처리; Vary 필요; client 가 magic media type 문자열 알아야.
- 판결: 이론적으로 순수, 실전에선 흔치 않음.
4. Query parameter versioning. /users?version=2. 일부 quick-and-dirty API.
- Pro: Framework routing 안 바꾸고 동작.
- Con: URL identity 깸 (다른 version query 둘이 다른 resource 둘); caching 어려움; 게으른 냄새.
- 판결: 피해. URL path versioning 이 이것의 모든 걸 더 깔끔하게 줘.
Date-based versioning (Stripe 정제)
Stripe 는 path-style 인데 date 로: 경로는 /v1/charges, 추가로 per-request header Stripe-Version: 2024-09-30.acacia 가 API 동작 snapshot 선택. Client 가 통합한 version 에 고정되고 자기가 선택할 때만 upgrade. 각 이름 붙은 version 동작은 절대 안 변함.
이건 진짜 문제 해결: "version" 이 여러 shape 으로 옴 (새 필드, 제거된 필드, 변경된 기본값, 이름 바뀐 endpoint), 단일 정수 version ("v2") 가 변경 묶음 강요. Date-based version 은 아무도 안 깨고 지속적으로 release 가능.
Additive vs breaking — 시간 벌어주는 규칙
모든 변경이 additive 면 versioning 완전히 건너뛸 수 있어:
- Response 에 새 필드 추가 → 기존 client 무시. 안전.
- 새 optional query parameter 추가 → 기존 client 안 보냄. 안전.
- 새 endpoint 추가 → 기존 client 절대 안 부름. 안전.
- 새 status code 나 error case 추가 → 좋은 family-dispatch 가진 기존 client 가 처리. 안전.
Versioning 은 breaking 변경 위한 것:
- 필드 제거나 이름 변경. 그거 읽는 client 깸.
- 필드 type 이나 format 변경. 그거 parse 하는 client 깸.
- Validation 강화 (이전엔 받아들이던 payload 가 이제 422). Looseness 의존한 client 깸.
- Optional parameter 의 기본값 변경. 미묘하지만 실제.
대부분 production API 는 v2 필요하기 전 몇 년 동안 기능 추가. 기본은 additive; 새 동작이 진짜로 옛 거와 공존 못 할 때만 versioning 잡아.
Deprecation — 정중한 작별
옛 version 은퇴 필요하면 wire 통해 신호. 관련 header 둘:
Deprecation: Sun, 01 Jan 2026 00:00:00 GMT— "이 endpoint 나 version 이 이 날짜부터 공식 deprecated." Client 가 경고 로그.Sunset: Wed, 01 Jul 2026 00:00:00 GMT(RFC 8594) — "이 endpoint 가 이 날짜 후 응답 멈춤." Client 한테 데드라인.
이걸 명확한 changelog 와 migration 가이드와 쌍. Header 가 wire 신호; 문서가 사람 신호. 둘 다 필요.
cwkPippa 의 versioning 현실
/v1/ 등장하는 날. 그때까진 선제적 versioning 비용이 보호보다 큼.