API Versioning하기

jinny
None
Published in
6 min readSep 17, 2019

안녕하세요. 휴먼스케이프에서 개발을하고 있는 jinny입니다.

오늘은 마이크로소프트의 REST API Guidelines의 API versioning 방법을 소개하고 Django 프로젝트 버저닝을 알아봅니다.

Version Number

마이크로소프트 REST API 가이드라인에서는 버전 넘버를 Major.Minor(v1.1)로 관리하도록 가이드합니다. 그러나 선택적으로 Minor 넘버를 제외하고 Major 넘버만 사용할 수 있습니다.

When to Version

Major Version

이전 버전과 하위호환을 깨는 큰 변화가 생겼을 경우 메이저 버전 넘버를 업그레이드합니다. 예를 들어 다음과 같은 경우들이 있습니다.

  • API가 삭제되거나 API URL이 변경된 경우
  • API 파라미터가 삭제되거나, 파라미터명이 변경된 경우
  • API의 동작이 변경된 경우
  • 반환하던 에러 코드가 변경된 경우

나열된 상황들의 공통점은, 기존에 쓰던 하위버전 API를 계속 사용할 수 없게되어 클라이언트 코드를 변경해야 한다는 점입니다. 이러한 상황이라면 나열된 경우 외에도 반드시 메이저 버전 넘버를 올려야 합니다.

그 외의 작은 변경사항들이 있을 때는 마이너 버전넘버를 변경합니다.

Minor Version

메이저 버전을 업그레이드하는 경우는 마이크로소프트 외에 다른 API 가이드라인도 대부분 이와 동일합니다. 그러나 마이너 버전의 업그레이드 정책은 보다 다양합니다.

예컨대 이베이 API Documentaion에서는 버전넘버를 세 파트로 구분(v1.3.8)하고 있습니다. 첫번째 자리가 변경될 때와 달리 2,3번째 자리의 변경은 하위호환성을 유지합니다. 3번째 자리의 변경은 버그픽스와 같은 경미한 업그레이드를 의미합니다. 2번째 자리의 변경은 클라이언트 코드를 반드시 변경할 필요는 없지만, 새로 추가된 기능을 이용하려면 선택적으로 코드를 변경해야 함을 의미합니다. 예를 들어 optional한 요청 파라미터가 추가되거나, 새로운 response field가 추가되는 경우입니다.

Versioning Format

버전 넘버를 명시하는 방식으로는 2가지를 제시합니다. 첫번째는 URL path에 버전 넘버를 포함하는 것이고, 두번째는 요청의 쿼리 파라미터로 버전 넘버를 전달하는 것입니다.

Versioning in Django REST Framework

장고에서 버저닝은 다음과 같이 구현할 수 있습니다. 버전넘버를 담는 argument를 url에 포함하여 뷰로 넘기는 방식입니다. 뷰에서는 version값에 따라 다른 동작을 할 수 있습니다.

  • urls.py
urlpatterns = [
url(
r'^(?P<version>(v1|v2))/bookings/$',
bookings_list,
name='bookings-list'
),
url(
r'^(?P<version>(v1|v2))/bookings/(?P<pk>[0-9]+)/$',
bookings_detail,
name='bookings-detail'
)
]
  • 버저닝 클래스 상속

버저닝 클래스를 상속해서 커스터마이징할 수 있습니다.

from rest_framework.versioning import URLPathVersioning
from rest_framework.views import APIView

class ExampleVersioning(URLPathVersioning):
default_version = ...
allowed_versions = ...
version_param = ...
class ExampleView(APIVIew):
versioning_class = ExampleVersioning

NamespaceVersioning

또는 네임스페이스로 여러 버전을 관리할 수 있습니다.

  • bookings/urls.py
urlpatterns = [
url(r'^$', bookings_list, name='bookings-list'),
url(r'^(?P<pk>[0-9]+)/$', bookings_detail, name='bookings-detail')
]
  • urls.py
# urlpatterns = [
url(r'^v1/bookings/', include('bookings.urls', namespace='v1')),
url(r'^v2/bookings/', include('bookings.urls', namespace='v2'))
]

아쉬운 점

위와 같은 예시처럼, DRF의 버저닝 기능은 bookings/urls.py의 urlpatterns를 공통적으로 사용하되, 버전에 따라 url에 연결되는 뷰의 동작을 구분하는 것에 초점을 두고 있습니다.

반면 뷰의 동작은 동일하지만 API URL이 변경되거나, 기존 API가 삭제되어, 버전에 따라 여러 urlspattern이 생기는 경우는 별도의 가이드가 없습니다. bookings/ 안에 여러 urls.py를 만들어 글로벌한 urls.py에서 각각 include하는 등 알아서 버전별 urls.py를 관리해야 합니다.

감사합니다.

Get to know us better!
Join our official channels below.

Telegram(EN) : t.me/Humanscape
KakaoTalk(KR) : open.kakao.com/o/gqbUQEM
Website : humanscape.io
Medium : medium.com/humanscape-ico
Facebook : www.facebook.com/humanscape
Twitter : twitter.com/Humanscape_io
Reddit : https://www.reddit.com/r/Humanscape_official
Bitcointalk announcement : https://bit.ly/2rVsP4T
Email : support@humanscape.io

--

--

jinny
None
Writer for

Studied CSE / Interested in ethics of AI and technological policy for AI / Love ducks and pandas