관련 이슈: #44
| 방식 | 판단 |
|---|---|
경로 (/api/v1/facilities) |
채택하지 않음 |
헤더 (X-API-Version: 1) |
채택 |
경로 방식을 쓰지 않는 이유:
- 프런트가 부르는 모든 경로와
SecurityConfig의 인가 규칙이 버전 없는 경로로 짜여 있다. 경로에 버전을 넣으면 인가 규칙을 두 벌로 유지해야 하고, 한쪽만 고치면 그대로 구멍이 된다. - 버전이 갈리는 건 보통 일부 API 뿐이다. 헤더 방식은 바뀐 API 만 새 버전 처리를 두면 된다.
예전 BaseController 의 @RequestMapping("/api/v1") 은 하위 컨트롤러가 전부 덮어써서 어떤 경로에도
적용된 적이 없다. 오해만 낳아 지웠다.
| 요청 | 처리 | 응답 헤더 |
|---|---|---|
| 헤더 없음 | 현재 버전(1) | X-API-Version: 1 |
X-API-Version: 1 또는 v1 |
1 | X-API-Version: 1 |
지원하지 않는 값 (2, abc …) |
400 API_VERSION_UNSUPPORTED |
X-API-Version: 1 |
- 헤더가 없으면 현재 버전이다. 지금 클라이언트는 아무것도 바꾸지 않아도 된다.
- 모르는 버전을 400 으로 거절하는 이유: 다른 버전을 기대한 클라이언트에게 조용히 현재 버전을 주면 필드가 어긋나도 알아채지 못한다. 이 프로젝트에서 실제로 여러 번 겪은 실패 방식이다.
- 구현:
core/web/ApiVersionFilter. CORS 허용·노출 헤더에 포함돼 브라우저에서도 읽을 수 있다. - Swagger 의 모든 API 에 선택 헤더로 표시된다.
필드 삭제·이름 변경·타입 변경·필수값 추가가 여기에 해당한다. 필드 추가는 호환 변경이다.
ApiVersionFilter.SUPPORTED에 새 버전을 추가한다 (CURRENT는 아직 올리지 않는다).- 바뀌는 API 에서 요청 속성
ApiVersionFilter.REQUEST_ATTRIBUTE로 버전을 보고 응답을 가른다. - 프런트가 새 버전 헤더를 보내도록 배포한다.
- 옛 버전 응답에
Deprecation·Sunset헤더를 붙여 종료일을 알린다. - 종료일이 지나면 옛 버전을
SUPPORTED에서 빼고CURRENT를 올린다.
가능하면 1~5 대신 새 필드를 추가하고 옛 필드를 유지하는 호환 변경을 먼저 검토한다.
(예: 정책 검색 응답의 totalCount 는 totalElements 를 추가한 뒤에도 남겨 두었다.)