Spring Boot

API versioning (API 버전 관리)

HEY__ 2024. 7. 1. 22:17
728x90

이 글은 공부를 하면서 알게 된 내용들을 기록하는 글 입니다. 오류나 고쳐야 할 사항들이 있다면 지적 부탁드립니다!

✅ API versioning의 필요성

팀 프로젝트를 Local에서 개발할 때에는 `BE`-`FE` 팀원들끼리 즉각적인 피드백을 진행하다보니, API에 버그가 발생하거나 구조를 변경해도 바로바로 적용했었다.

AWS에 올려 서비스 운영을 시작한 직후에도 FE 팀과 이야기를 해서 API 변경에 대해 동시에 작업을 진행했기 때문에, API 버전 관리의 필요성을 느끼지 못했었다.

 

1차 개발 및 배포 이후, `성능 테스트` 및 `리팩토링`을 진행하는 과정에서 `기존에 사용되고 있던 API는 유지`하면서, `새로운 API를 개발`해야 하는 상황이 발생했다.

 

이럴 때 필요한 것이 API versioning(버전 관리)이다.

URI, Header와 같은 곳에 `v1`, `v2`와 같이 API에 버전을 명시하여 API 버전 관리를 할 수 있다.

 


1️⃣ URI path

URI path에 API의 버전 넘버를 명시하여 관리하는 방법이다.

# version 1
GET http://{host}/v1/example

# version 2
GET http://{host}/v2/example
@GetMapping(value = "/api/v1/{id}")
public String testV1(@PathVariable int id){...}
 
@GetMapping(value = "/api/v2/{id}")
public String testV2(@PathVariable int id){...}

URI에 API version 정보가 포함되어 있다.

  • 장점
    가장 쉽고 단순하게 버전을 관리할 수 있다
  • 단점
    Controller에 메서드를 새롭게 추가하거나, Controller 자체를 분기하는 등의 작업이 필요하여 소스코드 관리 측면에서 고려를 해야 한다는 단점이 있다.
    (커스텀 Annotation을 설정함으로서 보완이 가능하다. 밑에서 자세히 알아보도록 하자)
  • 일반 브라우저에서 `실행 가능`
  • 예시: Naver, Facebook, Twitter

 


2️⃣ Query String

# version 1
GET http://{host}/example?version=1

# version 2
GET http://{host}/example?version=2
@GetMapping(value = "/api/{id}/", param = "version = 1")
public String testApiV1(@PathVariable int id){...}
 
@GetMapping(value = "/api/{id}/", param = "version = 2")
public String testApiV2(@PathVariable int id){...}

Query string에 API 버전정보 파라미터(version) 값 설정

  • 장점
    1) 구현이 간단하다.
    2) 버전이 업데이트 되었을 때 클라이언트에서 업데이트된 버전 정보를 쉽게 요청할 수 있고, API 요청 시 파라미터가 누락되어도 `Default value`를 정의해두어 최신 버전을 사용하도록 유도할 수 있다.
  • 단점
    클라이언트 측에서 적절한 version parameter를 고려해야 한다.
  • 일반 브라우저에서 `실행 가능`
  • 예시: Amazon

3️⃣  Custom Header (사용자 정의 헤더)

GET /example HTTP/1.1
    Host: {host}
    Content-Type: application/json
    X-API-Version: 1
@GetMapping(value = "/api/{id}", headers = "X-API-VERSION=1")
public String testApiV1(@PathVariable int id){...}
 
@GetMapping(value = "/api/{id}", headers = "X-API-VERSION=2")
public String testApiV2(@PathVariable int id){...}

Header에 커스텀한 값을 설정하여 API 버전 설정

  • `Request Header`에 커스텀한 값을 추가해서 버전을 관리하는 방식이다.
    커스텀 header를 추가하는 방식이기 때문에 header의 이름이 정해져 있진 않지만, 대체로 `X-API-VERSION`을 사용한다.
  • 장점
    URI에 버전 정보가 없어도 되기 때문에 URI를 깔끔하게 관리할 수 있다.
    대신 일반 브라우저에서 무분별한 접근을 통제할 수 있다.
  • 단점
    일반 브라우저에서 `실행 불가`
    `gateway` 또는 `reverse proxy`를 사용하고 있다면, Header에 대한 제한이 없는지 확인해봐야 한다.
  • 예시: Microsoft

4️⃣  MIME Type을 이용하는 방법; Content-Negotiation || Accept header

🧐 MIME Type이란?

`Multipurpose Internet Mail Extension`의 약자로, 일종의 인코딩 방식을 이야기한다.

음악과 같은 바이너리 파일은 ASCII만으로 전송이 불가능하기 때문에 이를 텍스트로 변환한 것을 인코딩한 것을 말한다.

 

# Request 예시
GET /example HTTP/1.1
    Host: {host}
    Accept: application/vnd.example.v1+json
    Content-Type: application/vnd.example.v1+json
@GetMapping(value = "/versions", produces = "application/vnd.genius.apiv1+json")
public String testApiV1() {
    return "API V1";
}

@GetMapping(value = "/versions", produces = "application/vnd.genius.apiv2+json")
public ResponseEntity<List<String>> testApiV2() {
    return "API V2";
}

Accept 헤더에 version에 대한 값 명시

  • 클라이언트가 HTTP Response의 `Accept`의 값을 커스텀하게 넣어주어 버전을 관리하는 방법
    `Accept`에는 클라이언트가 어떤 데이터 타입을 받을 것인지 명시한다.
  • Spring의 경우 `@RequestMapping`의 `produces` 옵션을 통해 `Accept` 값을 설정한다.
  • `vnd.example`의 의미
    `vnd`는 vendor로 해당 API의 공급업체를 뜻한다. `vnd.example`는 보통 `vnd.{company-name}`이 들어간다.
    예를 들어 `github`사에서 제공하는 API인 경우에는 `vnd.github`가 될 것이다.
  • 장점
    1) custom header, request parameter 없이도 버전 관리가 가능하다.
    2) HTTP Response의 Content-Type을 통해 어떤 버전의 API인지 확인이 가능하다.
  • 단점
    일반 브라우저에서 `실행 불가`
  • 예시: GitHub

🧐 vnd.example의 의미가 무엇일까?

 


✅  참고 자료 & 링크

 

 

 

 

 

728x90