개요
초기 서비스를 개발하고, 운영을 하다 보면 적지 않게 여러 요구사항과 이슈수정 그리고 업데이트에 의해 API의 버전들이 자주 변경됨을 알 수 있다.
제일 간편한방법은 각 API에 버전을 prefix로 기입하는 방법 /api/v1 이 있겠으나 보다 더 보안적이고 API별로 관리할 수 있는 방법은 없을까? 란 궁금증이 생겼다.
또한 REST API에서 각 API들의 버전들을 관리하는 방법들에 대해서 습득한 이후, 추후 버전에 관련된 의사결정을 할때 각 방법들에 대해서 제대로 알고 있다면 추후 선택하는 과정에서 보다 원활하게 선택할 수 있지 않을까 하여 학습을 진행하게 되었다.
버전을 관리하는 방법
버전을 관리하는 방법은 총 4가지가 있다.
- URI를 통한 버전관리 → 사용 경험 O
- Request params를 통한 버전관리 → 사용경험 X
- Header을 통한 버전관리 → 사용경험 X
- Mime Type을 통한 버전관리 → 사용 경험 O
현재까지 실무를 진행하며 Request Param, Header를 통한 버전관리에 비례하여 URI를 통한 API 버전관리를 대체적으로 많이 사용했었고, 이전에 한번 Mime Type을 통한 버전관리가 있었는데 이렇게 2개 정도를 사용해 본 적이 있었다.
물론 API별 버전관리를 하기에 앞서 제일 우선적으로 정해야하는건 각 팀의 의사결정에 따른 선택을 우선적으로 따라야 할 것이다.
위 사항을 살펴보기 전 통상적으로 많이 사용되는 API의 버전 관리방법에 대해서 이야기해볼까 한다.
보통의 API는 Major과 Minor로 구분하여 상황에 맞춰 버전을 관리하게 된다.
Major
- 주요 변경사항을 나타낸다.
- 내부적으로 새로운 메이저버전은 새로운 API를 생성하는 것을 의미한다.
- 그 외 주요 핵심적인 요구사항에서 요청, 응답등 상태값이 변경되어야 하는 상황
Minor
- 이슈, 수정에 의해 내부 코드가 변경되는 경우 ( Bug Fix )
- 기존 핵심적인 요구사항 외 변경이 발생할 경우 ( ex. 내부 Validation 추가 등 … )
URI를 통한 버전관리
해당 방법은 통상적으로 처음 학습을 진행했을 때부터 현재까지 자주보이는 버전 관리방식이다.
해당 방법은 URI 라우팅을 사용해 특정 버전의 API를 가리킨다. 캐시 키는 버전에 따라 변경되기 때문에 클라이언트는 리소스를 쉽게 캐시 할 수 있다.
새 버전의 REST API가 생성될 경우 캐시는 새 항목으로 인식한다.
장점
- 클라이언트가 리소스를 쉽게 캐시 할 수 있다.
단점
- 해당 방법을 도입하게 될 경우 전체 API를 분기해야 하기에, 적절한 패키지 분리 등 관리 기법이 필요하다.
Params를 통한 버전관리
해당 방법은 Query Params를 활용해 버전을 관리하는 방법이다.
요청 시 다음과 같은 형태로 요청을 발송하게 된다.
<http://localhost:8080/example?version=2.0>
URI와 크게 다른 점은 없이 버전을 Query Parameter로 관리한다는 특징이 있다.
장점
- API의 버전을 관리하는 간단한 방법이며, 최신버전으로 기본설정하기 쉽다.
단점
- 쿼리 매개변수를 사용해 요청을 적절한 API 버전으로 라우팅 하기가 어렵다.
Header를 통한 버전관리
다음은 헤더를 통한 버전관리이다.
API 요청을 보낼 때 해당 헤더 항목에 버전을 포함한다는 특징을 가지고 있다.
요청 시 다음과 같이 발송이 이뤄지게 된다.
<http://localhost:8080/resolver/example>
X-API-VERSION : 2.0
이전 두 접근법과 비교했을 때 헤더 측으로 버전을 관리하도록 분리했기 때문에 URI 내 버전정보를 전체 다 포함하지 않아도 된다는 특징을 가지고 있다.
또한, 해당 기법을 통해 Resolver로 해당 헤더를 Catch 하여 각 버전에 맞는 메서드를 실행할 수 있도록 커스텀 진행도 가능하지 않을까도 생각했다. ( 물론 내부 코드 복잡도가 높아지겠지만.. )
해당 항목의 장단점은 다음과 같다.
장점
- URI를 버전 정보로 복잡하게 만들지 않아도 된다.
단점
- Custom Header가 필요하다.
MIME type Versioning
부끄러운 이야기지만, 이전에 해당 방법을 사용했을 땐 “아.. 이런 방법이 있구나”에서 멈췄었고 해당 방법의 이름은 이번에 학습을 진행하며 처음 알게 되었다.
해당 방법은 API를 버전 화하는 대신 단일 리소스 표현을 버전 화할 수 있으며 보다 버전관리를 세밀하게 진행할 수 있다는 이점을 가지고 있다.
요청방법은 다음과 같다.
<http://localhost:8080/version/example>
Accept : application/vnd.example-1.0.json
또한, 새로운 버전을 만들 때 전체 애플리케이션을 분리할 필요가 없기에 코드레벨에서의 공간이 줄어든다는 장점이 있다.
하지만, 위 방법들과 반대되는 단점을 꼽자면 아무래도 팀 내 모든 팀원들이 해당 방법에 대해 알고 있다면 모르겠지만 접근성 자체는 떨어진다는 점이라고 생각한다.
또한, 해당 요청을 하기 위해선 미디어 타입을 가진 헤더가 필요하기 때문에 Postman, Curl과 같은 툴을 사용해 테스트를 진행해야 한다.
장점
- API 전체를 버전 화하는 대신 단일 리소스 표현을 버전화 할 수 있다.
- 버전 관리를 보다 세밀하게 진행할 수 있다.
단점
- 미디어 타입의 HTTP 헤더가 필요하기 때문에 테스트가 어렵다.
마치며
개인적인 궁금증으로 시작해 다양한 버전관리 방법을 알고 추후 적용을 해야 하는 의사결정이 필요할 때 도움이 될까 하여 학습을 시작했지만 결국 모든 방법의 장단점이 있었고 현재의 나는 다음과 같은 결론을 내릴 것 같다.
MIME TYPE을 통한 방법 외적인 방법들을 고려해 본다.
각 코드 버전의 관리는 결국 하나의 팀뿐만이 아닌 해당 API들을 사용하는 클라이언트 개발자들과의 결정이 필요할 것이고 결국 이는 의사결정으로 풀 수 있는 요소 중 하나지 않을까란 생각이 들었다.
또한, MIME Type 구현을 진행하며 해당 관리를 Custom Annotation으로 분리하여 관리를 해보고자 진행했는데 진행하면 할수록 배보다 배꼽이 더 큰 느낌이 드는 느낌이 들었다.
결국 버전이 변경됨에 따라 내부 코드가 변경이 될 테고 각 버전에 따른 메서드가 진행이 되어야 할 텐데 큰 의미가 있을까란 생각이 들기도 했다.
진행했던 코드는 아래에 첨부해 두고자 한다.
https://github.com/JoeCP17/api-version-management
학습을 진행하며 Interceptor, WebMvcConfigurer 등 다양하게 학습을 진행할 수 있어서 나름 의미가 있었다고 생각한다.
학습을 진행하며 당시 내가 궁금했던 포인트와 학습관련된 내용을 함께 기록하고자 글을 작성한다.
해당 학습을 진행하며 좋은 소스를 제공받아 운영 중에 버전을 바꿀 수 있는 Feature Flag도 함께 공부해보려고 한다.
REF
'Project' 카테고리의 다른 글
프로젝트 회고 : Let's Parking! (5) | 2022.12.27 |
---|