# 공개 웹 API는 어떻게 버전 관리하나요?

> Clean Markdown view of GeekNews topic #30026. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=30026](https://news.hada.io/topic?id=30026)
- GeekNews Markdown: [https://news.hada.io/topic/30026.md](https://news.hada.io/topic/30026.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-05-31T01:00:58+09:00
- Updated: 2026-05-31T01:00:58+09:00
- Original source: [lobste.rs](https://lobste.rs/s/g9u6b7/how_do_you_version_public_web_apis)
- Points: 1
- Comments: 1

## Topic Body

- 공개 웹 API가 **Product API** 같은 이름과 `/api/v1` 경로를 함께 쓰면, API 자체의 시맨틱 버전과 구조가 어긋날 수 있음
- `/v1/` 경로와 `major.minor.patch`를 병행하면 **라우트**와 API 계약이 섞이고, 시맨틱 버전의 첫 숫자가 URL에 고정됨
- 호환성을 깨는 변경에는 새 경로와 **리버스 프록시** 라우트가 필요해져, 계약 정보가 URL과 버전 번호로 분산될 수 있음
- 후속 API를 동시에 만들면 기존 API는 사실상 `v1`에 묶이고, 이후 호환성 깨짐 변경에서 이름과 경로의 의미가 애매해짐
- 공개 웹 API 버전 관리에서 반복적으로 거슬리는 방식과 더 나은 **설계 원칙**을 찾으려는 문제의식임

## Comments



### Comment 58626

- Author: neo
- Created: 2026-05-31T01:00:59+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/g9u6b7/how_do_you_version_public_web_apis) 
- URL에 `/v1/`을 두는 건 사실 큰 장점 중 하나임. 엔드포인트를 끄기 전까지는 사용자에게 **API를 깨지 않도록 강제**하기 때문

- [**Evolving HTTP APIs**](https://mnot.net/blog/2012/api-evolution)와 같은 저자의 다른 글들이 유용한 조언을 줌

- 기본적으로 각 라우트에 `/v1/`, `/v2/`처럼 붙여 **호환성 깨짐 변경**을 표시함. 여러 호스트에서 동작하는 표준을 정의하려는 게 아닌 공개 운영 API라면 완전한 의미적 버전 관리(semantic versioning)를 할 이유가 별로 없음  
  의미적 버전 관리는 다른 개발자가 변경 로그를 20분씩 읽지 않고도 의존성을 자신 있게 올릴 수 있게 하려고 존재하는데, 운영 중인 API에서는 사람들이 새 마이너 버전이나 버그 수정 버전을 언제 가져올지 선택할 수 없음  
  무엇이 호환성 깨짐 변경인지는 **문서화된 동작**을 바꾸거나, 문서화된 동작에 의존하는 기존 클라이언트를 깨뜨리는 경우로 봄. 문서화되지 않은 동작 변경까지 깨짐으로 보는 곳도 있지만, 거기엔 위험이 많음

- Google에서는 이렇게 함: [AIP-185: API Versioning](https://google.aip.dev/185), [AIP-180: Bacwards compatibility](https://google.aip.dev/180)  
  이 설계 문서들은 Google의 업무 방식에 꽤 특화되어 있다고 느끼지만, API를 설계할 때 참고해 왔고 그 안의 몇몇 아이디어는 매우 유용했음

- 일반적으로 모든 API는 **호환성 깨짐 변경**을 최대한 줄이려 노력해야 한다고 봄. 예를 들어 속성 이름을 바꾸고 싶다면 기존 속성을 없애기보다 새 이름을 중복으로 추가하는 편이 낫다고 생각함  
  다만 [the people at Buttondown do it](https://buttondown.com/blog/api-versioning) 방식도 깔끔함. API 버전 간 마이그레이션을 정의해서, 소비자는 헤더로 자기 API 버전을 고정할 수 있고 제공자는 계속 변경을 진행할 수 있게 함
  - 출력 속성에는 속성을 중복하는 방식이 꽤 잘 먹혔음. 하지만 입력에서는 클라이언트가 두 속성을 서로 다른 값으로 보내는 경우를 처리해야 함  
    “새 이름이 항상 우선”이라는 답이 떠오르지만, 클라이언트가 읽기-수정-쓰기 순서를 수행하면서 서버가 만든 객체의 수정본을 다시 보내는 경우엔 무너질 수 있음. 클라이언트가 예전 속성만 갱신하고 새 속성은 무시한 채 그대로 되돌려 보낼 수 있기 때문
  - API 제공자가 설명한 것처럼 API 버전 간 **마이그레이션**을 제공하는 건 좋아 보이지만, [using an HTTP request header for versioning can cause problems](https://mnot.net/blog/2012/header_versioning)
  - 그 링크는 **데이터 형태**를 다루는 방법을 아주 잘 설명함. 다만 그건 일부일 뿐이고, 동작 자체가 바뀔 때는 어떻게 하는지 궁금함  
    그런 변환을 동작 할당에도 쓸 수 있을 것 같지만, 놓친 게 아니라면 그 부분은 다루지 않았음

- 이상적으로는 버전을 경로에 포함하고, 새 버전은 추가적인 성격을 갖게 만들어야 함. 그러면 예전 버전 API가 필요한 입출력 변환을 거쳐 요청을 더 새 API 버전으로 **재라우팅**할 수 있음  
  몇 년 뒤 어떤 오래된 버전도 아무도 쓰지 않게 되면 제거할 수 있고, `/v1/` 경로는 오류가 됨

- 예전에 `Accept` 헤더를 통한 **콘텐츠 협상**으로 API 버전 관리를 하는 방식을 조금 읽어 봤음. 그런 방식으로 API 버전 관리를 해 본 사람이 있다면 경험이 궁금함  
  내 경험상 리소스별 버전 관리나 전역 버전 관리가 가장 직관적인 방식에 가까웠음. 폐기에는 `Deprecation` HTTP 응답 헤더([RFC 9745](https://datatracker.ietf.org/doc/rfc9745/))를 쓰고, 결국 오래된 엔드포인트에는 `410 Gone` 같은 응답을 반환하는 조합이 클라이언트가 새 버전으로 옮겨가게 하는 합리적인 방법으로 보임  
  추가로, 누군가 **진화 가능한 API**를 만들어 봤는지도 정말 궁금함. 예전 버전 요청을 내부에서 새 API 버전 요청으로 번역해 주다가, 클라이언트가 이전하거나 일정 시간이 지나면 실제로 예전 버전을 제거하는 방식 말임
