API는 웹 개발시 사실상 필수적으로 들어가는 요소이고 서버와 클라이언트를 이어주는 중요한 다리 역할을 한다. 그런데 이렇게 중요한 API가 변경되는 순간 만약 클라이언트가 해당 사실을 알지 못하고 기존의 API로 요청을 보내 404 에러를 만난다면 얼마나 당황스러울까?
팀 프로젝트를 개발할 당시에는 실제로 서비스되는 게 아니었고 프론트엔드 팀원들과 즉각적인 피드백을 하다보니 API url의 변경이나 내부 파라미터 등의 변경이 있어도 즉시 수정 후 재배포하는 과정만 반복했다. 그래서 API의 버전을 관리한다는 생각은 전혀 못했던 것 같다.
그런데 프로젝트가 끝나고 리마인드 및 리팩토링을 진행하면서 실제 서비스를 런칭해 운영하다보면 각각의 사용자가 이용하는 서비스의 환경 및 버전이 다를 수 있다는 생각이 들었고 그렇게 되면 변경된 API뿐 아니라 변경 전의 API 또한 있어야하는 것이 아닌가 라는 생각이 머리를 스쳤다.
그래서 찾아본 결과 API Versioning이라는 개념이 있었다.
API 버전은 Majo와 Minor로 구분해 상황에 따라 버전을 관리한다.
이전 버전과 더 이상 호환되지 않는 경우, 클라이언트측의 코드가 변경되어야 하는 경우
위의 경우들 외에도 기존 API를 사용하던 클라이언트 측의 코드가 변경되어야하는 모든 경우에 Major 버전을 올려주어야 한다.
Major의 변경이 아닌 작은 변경사항이 있는 경우 Minor 버전을 올려야한다.
이처럼 클라이언트 측의 코드가 변경되지 않아도 되는 경우에 Minor Version을 올린다.
API 버전 관리 방법은 여러 가지가 존재하는데 케이스마다 상황에 맞는 관리 방법을 선택해 관리하는 것이 좋다. 다만 관리방법을 선택했다면 이를 문서화해 제공하는 것이 좋다.
API 버전넘버는 보통 세 파트로 나뉜다. (v.1.2.3)
첫 번째 숫자는 Major버전, 두 번째, 세 번째는 Minor 버전이다.
주로 두 번째는 기능 추가, 세 번째는 버그픽스 등을 의미한다.
그렇다면 방법은 어떤 것들이 있을까
API URI path에 버전 넘버를 명시해 관리하는 방법이 있다.
다만 이 경우에는 Minor 버전 넘버는 관리하기 어려울 수 있다.
@GetMapping(value = "test/v1/{id}/")
public String restTestApiV1(@PathVariable int id){...}
@GetMapping(value = "test/v1/{id}/")
public String restTestApiV2(@PathVariable int id){...}
기존 메서드의 @Mapping의 값을 변경해주는 방식이다.
@GetMapping(value = "test/{id}/", param = "version = 1")
public String restTestApiV1(@PathVariable int id){...}
@GetMapping(value = "test/{id}/", param = "version = 2")
public String restTestApiV2(@PathVariable int id){...}
헤더에 키, 값을 추가해 관리하는 방식이다.
@GetMapping(value = "test/{id}/", headers = "X-API-VERSION = 1")
public String restTestApiV1(@PathVariable int id){...}
@GetMapping(value = "test/{id}/", headers = "X-API-VERSION = 2")
public String restTestApiV2(@PathVariable int id){...}
클라이언트에서 요청시 Header에 X-API-VERSION
값을 설정해 요청하면 된다.
Header 안의 Accept에 버전을 담아 요청하는 방식이다.
Accept는 복수의 형식 지정이 가능하다. 웹 서버는 Content-Type Header를 사용하여 응답 본문에 있는 데이터의 형식을 확인할 수 있다.
// v1
GET /users
Host: api.test.com
Accept: application/vnd.test.v1+json
// v2
GET /uesrs
Host: api.test.com
Accept: application/vnd.test.v2+json