사내에서는 URI에 경로를 포함하는 방법으로 개발이 되어있었는데 팀원분과 REST API 버전 관련하여 말하다 보니REST API 특성상 URI에는 자원을 표기하는 것이지 버전을 표기한다는 점에서 어색함이 들어서 시작이 되어
정리가 필요해 보여서 정리를 하고자 한다.
REST API 버전을 표기하는 방법으로는 대표적으로 4가지가 있다.
1. URI 경로에 표기하는 방법
GET /api/v1/call
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class HelloController {
private final NewVersionService newVersionService;
private final OldVersionService oldVersionService;
@GetMapping("v1/version")
public String version() {
return oldVersionService.findName();
}
@GetMapping("v2/version")
public String version2() {
return newVersionService.findName();
}
}
2. Reqeust Parameter로 표기하는 방법
GET /api/call?version=v1
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class ParamVersionController {
private final NewVersionService newVersionService;
private final OldVersionService oldVersionService;
@GetMapping("/version")
public String api(@RequestParam String version){
if (version.equals("V2")) {
return newVersionService.findName();
}
return oldVersionService.findName();
}
}
3. 커스텀한 Request Header 값으로 분기
GET /api/call
X-API-VERSION: V1
@GetMapping(path = "header", headers = {"X-API-VERSION=V1"})
public String v1() {
return oldVersionService.findName();
}
@GetMapping(path = "header", headers = {"X-API-VERSION=V2"})
public String v2() {
return newVersionService.findName();
}
4. MIME 타입으로 분기하는 방법
GET /api/call
Accept: application/vnd.benggrae.com.v1+json #vnd는 벤더를 의미
public class BengMimeType {
public static final String V1_JSON = "application/vnd.benggrae.com.v1+json";
public static final String V2_JSON = "application/vnd.benggrae.com.v2+json";
}
@GetMapping(path = "name", produces = BengMimeType.V1_JSON)
public String v1() {
return oldVersionService.findName();
}
@GetMapping(path = "name", produces = BengMimeType.V2_JSON)
public String v2() {
return newVersionService.findName();
}
그래서? 무엇을 써야 하는 걸까?
정리를 진행하면서 타 블로그 들을 몇 가지 읽어 보았고 각 대표 회사(트위터, 아마존, GitHub, 마이크로스프트)들의 REST API 도큐먼트들타 블로그들에서는 각 회사별로 표준이 있는 듯 보였으나 실재로는 그렇지 않았다. 대부분의 회사가 혼용해서 사용하고 있었다.
특히 마이크로소프트는 경로에 포함방식과 헤더값에 명시하는 방법 혼용해서 사용하고 있었으며 깃허브에서는 3번 4번 방식을 같이 사용하고 있었다.
개인적으로는 REST의 규칙을 준수하여 3. 커스텀한 Request Header 값으로 분기와 4. MIME 타입으로 분기하는 방법이 명확해 보이나.
클라이언트에 따라서 header값을 추가하지 못하는 상황이 발생할 수 있다고 생각이 되어 트레이드오프에 따라 정하기 나름이라고 정리하기로 했다.
참조.
정리한 상세 소스 레포지토리 (https://github.com/benggrae/study-repository/tree/main/rest-api-version-managed/rest-version
트위터 (https://developer.twitter.com/en/docs/twitter-api/v1/tweets/curate-a-collection/api-reference/get-collections-entries)
아마존 (https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid.html)
GITHUB (https://docs.github.com/ko/rest/packages?apiVersion=2022-11-28)
GitHub - benggrae/study-repository: 스터디용 레포지토리를 관리한다.
스터디용 레포지토리를 관리한다. Contribute to benggrae/study-repository development by creating an account on GitHub.
github.com
GET collections/entries
GET collections/entries Retrieve the identified Collection, presented as a list of the Tweets curated within. The response structure of this method differs significantly from timelines you may be used to working with elsewhere in the Twitter API. To naviga
developer.twitter.com
Api - Amazon API Gateway
Thanks for letting us know this page needs work. We're sorry we let you down. If you've got a moment, please tell us how we can make the documentation better.
docs.aws.amazon.com
패키지 - GitHub Docs
Status: 200 { "id": 40201, "name": "octo-name", "package_type": "rubygems", "owner": { "login": "octocat", "id": 209477, "node_id": "MDQ6VXNlcjIwOTQ3Nw==", "avatar_url": "https://avatars.githubusercontent.com/u/209477?v=4", "gravatar_id": "", "url": "https
docs.github.com