꿈소년의 개발 이야기

[Network][Web] REST API 버전 관리 본문

Software Engineering

[Network][Web] REST API 버전 관리

꿈소년 2021. 9. 24. 11:22
반응형

Abstract

클라우드 네이티브 애플리케이션 개발에 대해 마이크로 서비스가 핫 트렌드입니다.

마이크로 서비스의 이점 ?

  • 향상된 확장성
  • 회복 탄력적인 애플리케이션
  • 기술에 구애받지 않는 애플리케이션
  • 출시 시간 단축
  • CI/CD 지원을 통한 비즈니스 민첩성 향상

등등 다양한 이점이 있어서라고 합니다.

API 버전 관리는 언제?

마이크로 서비스 기반 아키텍처 MSA 의 핵심 구성 요소 중 하나는 'API design & contract' 임.

API 버저닝은 매우 중요하다.

클라이언트가 준비 될 때 언제든지, 기존 클라이언트가 기존 REST API 를 지속적으로 사용하게 해주고, 클라이언트 애플리케이션이 새로운 API 로 마이그레이션을 할 수 있게 한다.

버전 관리의 이점

버저닝은 API 변경 사항을 탐색하는데 도움을 준다.

  • Changes made to the request format by introducing mandatory parameters
    필수 파라미터가 추가됨에 따라 변경되는 요청 형식.
  • Changes made to the response data either due to format change or structure of the response message
    응답 메시지 형식 변경 또는 구조 변경으로 인한 응답 데이터 변경.
  • Deprecation of the API to provide the enhanced functionalities
    보다 향상된 기능 제공을 위한 기존 API 사용 중단.

API 버전화 방법

  1. URI Path(URI 경로) 를 통한 버전 지정
  2. Query Parameters(쿼리 매개변수) 를 통한 버전 지정
  3. Custom Headers(사용자 지정 헤더) 를 통한 버전 지정
  4. Content Negotiations (컨텐츠 협상) 을 통한 버전 지정

Version Through URI path

엔드포인트를 버저닝 하는데 가장 보편적인 방식입니다.

형식은 구애 받지 않습니다. 의미 있는 식별자로 사용할 수 있으므로 API 개발팀이 새로운 변경 사항을 원활하게 통합할 수 있습니다.

http://api.example.com/v1

Versioning Through Query Parameters

다음과 같이 쿼리 매개 변수로 버전을 사용하는 방식입니다.

간단하고 구현하기 쉽습니다. 명시적으로 지정하지 않으면 무조건 최신 API 버전을 기본값으로 만들 수 있습니다.

http://api.example.com/customers?version=v1

Versioning Through Custom Headers

Header 에 커스텀 헤더를 통해서 버전 관리를 하는 방식입니다.

이 방식은 URI 를 훼손하지 않고도 버전 관리를 하도록 해줍니다.

단점은 헤더를 처리하고 버전을 사용하기 위해서 헤더를 유지 보수해야 합니다.

@RestController
@RequestMapping("/")
public class ProductController {

      @Autowired
     private ProductRepository repository;

      @GetMapping(value= "products", headers = {"X-API-VERSION=v1"})
    public List<Product> findAll() {
           return repository.findAll();
     }

     @GetMapping(value= "products", headers = {"X-API-VERSION=v1"})
     public List<Product> findAllV2() {
           return repository.findAll();
     }
}

Versioning Through Content negotiations

클라이언트가 특별하게 'Accept Header' 가 있는 버전을 요청하도록 함으로서 버저닝하는 방식입니다.

특정 버전을 요청하지 않는 경우 default 구현을 제공하기 위해서 서비스를 구현해야 합니다.

Github 의 경우 이런 방식으로 구현되어 있습니다.

GET /customers/1234 HTTP/1.1 Accept: application/vnd.v1+json
@RestController
@RequestMapping("/")
public class ProductController {

     @Autowired
     private ProductRepository repository;

        // Find
        @GetMapping(value= "products", headers = {"Accept=application/vnd.v1+json"})
        List<Product> findAll() {
            return repository.findAll();
        }

        @GetMapping(value= "products", headers = {"Accept=application/vnd.v2+json"})
        List<Product> findAllV2() {
            return repository.findAll();
        }

}
  • v1 버전으로 요청한 경우 v1 응답을 받습니다.
curl -L -X GET 'http://localhost:8080/products' \ -H 'Accept: application/vnd.v1+json'
 [    
    {       
        "name": "IdeaPad Slim 5 (15, AMD)"  
    } 
]
  • v2 버전으로 요청한 경우 v2 응답을 받는다.
curl -L -X GET 'http://localhost:8080/products' \
-H 'Accept: application/vnd.v2+json'

[
    {
        "name": "IdeaPad Slim 5 (15, AMD)"
     }
]
  • Accept 헤더 없이 그냥 보낸 경우

그냥 v1 기본 값으로 버전 처리한다.

curl -L -X GET 'http://localhost:8080/products' 
 [    
    {       
        "name": "IdeaPad Slim 5 (15, AMD)"  
    } 
]

  • 406 Not Acceptable
curl -L -X GET 'http://localhost:8080/products' 
-H 'Accept: application/vnd.v3+json'

{
    "timestamp": "2021-09-13T14:30:12.263+0000",
    "status": 406,
    "error": "Not Acceptable",
    "message": "Could not find acceptable representation",
    "path": "/products"
}

Summary

API 기반 아키텍처가 진화하고 점점 더 많은 사람들이 채택하고 있는 만큼 API 버전에서는 API 변경으로 인한 중단을 최소화하고 이전 버전과의 호환성을 높이는 것이 중요하다. 위에서 언급한 각각의 버전 기술들은 각각의 장단점을 돕는다.

Refer.

https://dzone.com/articles/rest-api-versioning-strategies-1#