REST API 버전 관리
버전관리라는 것은 단순하게 사용자에게 보여주는 항목을 관리하는 것이 아닌 REST API 설계가 변경되거나 Application의 구조가 변경되었을 시에도 버전을 변경해야 할 수도 있습니다.
또한 사용자들이 어떤 버전을 사용해야 할지 가이드를 해야 하거나 회사, 팀마다 어떻게 Version 관리를 하는 방식은 매우 다를 수도 있습니다.
REST API의 새로운 버전을 오픈, 배포해도 고객들은 기존의 주 버전을 계속 사용하기를 원할수도 있고 새로운 API Version을 사용하길 원할 수도 있습니다.
즉, 기존 사용하던 Rest API를 계속해서 사용하게 해주기 위해 버전을 관리해주어야 합니다.
🏷️ 버전 관리 방법
✔️ Major Version 과 Minor Version
Major Version
이전 버전과 호환의 문제가 깨지는 즉, 클라이언트 측의 코드가 변경되어야 하는 하는 상황으로 봅니다.
✅ 변경되야 하는 상황
1. API가 삭제되거나 API URL이 변경되는 경우
2. API의 파라미터가 삭제되거나, 파라미터 명이 변경되는 경우
3. API의 동작이 변경되는 경우
4. 반환하던 에러코드가 변경되는 경우
위와 같은 케이스들은 전보 기존에 쓰던 API를 사용할 수가 없어 클라이언트 측의 코드도 변경되어야 하는 상황이며, 위와 같은 상황이 아니더라도 클라이언트 측에 어떠한 변화라도 있게 되는 경우에는 Major 버전을 올려줘야 합니다.
Minor Version
Major한 변경이 아닌 그 외의 작은 변경사항이 있는 경우에는 마이너 버전넘버를 변경하게 됩니다.
✅ 변경되야 하는 상황
1. 버그 픽스와 같이 오류로 인해 내부 코드가 바뀌는 경우
2. 추가되는 기능이 존재하나 클라이언트의 코드가 변경될 필요는 아닌 경우(Optional 파라미터 추가 등)
이렇듯 클라이언트 측의 코드가 변경되지 않아도 되는 상황에서 API의 코드가 수정되는 경우에는 Minor한 버전으로 보면 된다.
1. URI 버전 관리
@GetMapping("/v1/person")
public PersonV1 getFirstVersionOfPerson() {
return new PersonV1("Bob Charlie");
}
@GetMapping("/v2/person")
public PersonV2 getSecondVersionOfPerson() {
return new PersonV2(new Name("Bob", "Charlie"));
}
// ex) www.example.com/v1/person
REST API 버전을 명시하는 방법중 하나는 URI 경로에 버전을 명시하는 것으로 Facebook, Twitter 등에서 이 방법을 사용하고 있습니다. API의 내부적인 정보는 Majar-version.Minor-version.Release-version 형태로 사용됩니다.
이 방법은 URI을 사용하여 특정 버전의 API를 가리킵니다. 캐시 키(이 경우 URI)는 버전별로 변경되므로 클라이언트는 리소스를 쉽게 저장할 수 있습니다. 새로운 버전의 REST API가 출시되면 캐시 내의 새로운 엔트리로 인식됩니다.
장점 : 클라이언트는 쉽게 리소스를 저장할 수 있습니다.
단점 : 이 방법은 코드 베이스에 매우 큰 공간이 필요해집니다. 이 말의 의미는 새로운 버전이 생성된다는 것은 API 전체를 새로 분기하는 것을 의미합니다.
2. Request Parameter 버전 관리
@GetMapping(path = "/person", params = "version=1")
public PersonV1 getFirstVersionOfPersonRequestParameter() {
return new PersonV1("Bob Charlie");
}
@GetMapping(path = "/person", params = "version=2")
public PersonV2 getSecondVersionOfPersonRequestParameter() {
return new PersonV2(new Name("Bob", "Charlie"));
}
// ex) www.example.com/person?version=1
Request parameter에 버전을 명시하는 방법으로 구현 관점에서 API를 버전화하는 간단한 방법입니다.
장점 : API 버전을 쉽게 만들 수 있으며 최신 버전으로 기본 설정하기 쉽습니다.
단점 : 적절한 API 버전으로 요청을 라우팅할 때 쿼리 파라미터를 사용하는 것이 더 어렵습니다.
3. Header 버전 관리
@GetMapping(path = "/person/header", headers = "X-API-VERSION=1")
public PersonV1 getFirstVersionOfPersonRequestHeader() {
return new PersonV1("Bob Charlie");
}
@GetMapping(path = "/person/header", headers = "X-API-VERSION=2")
public PersonV2 getSecondVersionOfPersonRequestHeader() {
return new PersonV2(new Name("Bob", "Charlie"));
}
// postman나 Talend API 크롬 앱에서 header에 X-API-VERSION을 추가하여 version을 별도로 요청 가능
REST API는 Atribute로 포함된 버전 번호와 함께 커스텀 헤더를 제공하여 버전화할 수도 있습니다. 이 접근법과 이전 두 접근법의 가장 큰 차이점은 URI에 버전 정보를 복잡하게 만들지 않는다는 것입니다.
장점 : URI를 버전 정보로 복잡하게 만들지 않습니다.
단점 : Custom Header가 필요합니다.
4. MIME type 버전 관리
@GetMapping(path = "/person/accept", produces = "application/vnd.company.app-v1+json")
public PersonV1 getFirstVersionOfPersonAcceptHeader() {
return new PersonV1("Bob Charlie");
}
@GetMapping(path = "/person/accept", produces = "application/vnd.company.app-v2+json")
public PersonV2 getSecondVersionOfPersonAcceptHeader() {
return new PersonV2(new Name("Bob", "Charlie"));
}
이 방법을 사용하면 API 전체를 버전화하는 대신 단일 리소스 표현을 버전화할 수 있으므로 버전 관리를 보다 세밀하게 제어할 수 있습니다. 또한 새로운 버전을 만들 때 전체 애플리케이션을 분리할 필요가 없으므로 코드 베이스에 설치 공간이 줄어듭니다. 이 접근법의 또 다른 장점은 URI 경로를 통한 버전 관리를 통해 도입된 URI 라우팅 규칙을 구현할 필요가 없다는 것입니다.
장점: API 전체를 버전화하는 대신 단일 리소스 표현을 버전화할 수 있으므로 버전 관리를 보다 세밀하게 제어할 수 있습니다. 설치 공간을 줄일 수 있습니다. URI 라우팅 규칙을 구현할 필요가 없습니다.
단점: 미디어 타입의 HTTP 헤더가 필요하기 때문에 브라우저를 사용하여 API를 테스트하고 탐색하는 것이 더욱 어려워집니다.
🏷️ 버전 관리에 중요한 점
- URI 가 지저분 해지지 않도록 잘 관리해야 합니다.
- 잘못된 HTTP Header 사용에 주의해야 합니다.
- Cache로 인해 지정한 값이 제대로 반영되지 않을 수 있으므로 주의해야 합니다.
- 요청하는 API가 웹 브라우저에서 바로 동작해야 합니다.
- API 개발자 문서를 지원해야 합니다.
개인이 진행하는 프로젝트의 경우 각각 장단 점을 비교해서 선택하거나 요청 매개변수 버전 관리는 아마존, 헤더 버전 관리는 마이크로 소프트, 미디어 유형 버전 관리는 깃허브 등과 같이 회사가 사용하는 방식에 따라서 선택을 하면 됩니다.
📖 Reference
'코딩 공부 > web & Java' 카테고리의 다른 글
[Spring] 직렬화(Serialize) (1) | 2023.11.15 |
---|---|
[Spring] HATEOAS (1) | 2023.11.14 |
[Spring] 국제화 (0) | 2023.11.12 |
OpenAPI와 Swagger (1) | 2023.11.09 |
[Docker] Docker (0) | 2023.11.08 |