웹 서비스 REST API 버전 관리에 대한 알려진 방법이나 모범 사례가 있습니까?
AWS는 엔드 포인트의 URL을 기준으로 버전 관리를 수행하는 것으로 나타났습니다 . 이것이 유일한 방법입니까, 아니면 같은 목표를 달성 할 수있는 다른 방법이 있습니까? 여러 가지 방법이 있다면 각 방법의 장점은 무엇입니까?
웹 서비스 REST API 버전 관리에 대한 알려진 방법이나 모범 사례가 있습니까?
AWS는 엔드 포인트의 URL을 기준으로 버전 관리를 수행하는 것으로 나타났습니다 . 이것이 유일한 방법입니까, 아니면 같은 목표를 달성 할 수있는 다른 방법이 있습니까? 여러 가지 방법이 있다면 각 방법의 장점은 무엇입니까?
답변:
이것은 좋고 까다로운 질문입니다. URI 디자인 주제는 동시에 REST API의 가장 두드러진 부분 이므로 해당 API 사용자에 대한 잠재적 장기 약속 입니다.
응용 프로그램의 진화와 API의 수명 이 줄어들고 API는 프로그래밍 언어와 같이 복잡해 보이는 제품의 진화와 비슷하기 때문에 URI 디자인 에는 자연스러운 제약 이 없어야합니다. 시간이 지남에 따라 . 애플리케이션 및 API 수명이 길수록 애플리케이션 및 API 사용자에 대한 헌신이 커집니다.
반면에, 삶의 또 다른 사실은 API를 통해 소비 될 모든 자원과 그들의 측면을 예측하기 어렵다는 것입니다. 운 좋게도 Apocalypse 까지 사용될 전체 API를 디자인 할 필요는 없습니다 . 모든 자원 엔드 포인트 및 모든 자원 및 자원 인스턴스의 주소 지정 체계를 올바르게 정의하면 충분합니다.
시간이 지남에 따라 각 특정 리소스에 새로운 리소스와 새로운 속성을 추가해야 할 수도 있지만, 리소스 주소 지정 체계가 공개되어 최종적으로 API 사용자가 특정 리소스에 액세스하기 위해 따르는 방법은 변경되지 않아야합니다.
이 방법은 HTTP 동사 시맨틱 (예 : PUT은 항상 업데이트 / 교체해야 함) 및 이전 API 버전에서 지원되는 HTTP 상태 코드 (인간 개입없이 작업 한 API 클라이언트가 계속 작동 할 수 있도록 계속 작동해야 함)에 적용됩니다. 그런 식으로).
또한 API 버전을 URI에 포함하면 시간이 지남에 따라 변경되는 리소스 주소 / URI를 가짐으로써 애플리케이션 상태 엔진 (Roy T. Fieldings PhD 논문에 명시되어 있음) 으로서 하이퍼 미디어 개념이 중단되므로 API가 API 사용자가 의존 할 수 있는 자원 URI는 영구 링크이어야 함을 의미하므로 버전을 자원 URI에 오랫동안 유지해서는 안됩니다 .
물론, 기본 URI에 API 버전을 포함 할 수 있지만 새 API 버전에서 작동 하는 API 클라이언트 디버깅과 같이 합리적이고 제한된 용도로만 사용할 수 있습니다. 이러한 버전이 지정된 API는 시간 제한이 있으며 제한된 API 사용자 그룹 (예 : 비공개 베타 버전)에서만 사용할 수 있어야합니다. 그렇지 않으면, 당신은 당신이하지 말아야 자신을 저지른 다.
만료 날짜가있는 API 버전의 유지 관리에 대한 몇 가지 생각. 웹 서비스 (Java, .NET, PHP, Perl, Rails 등)를 구현하는 데 일반적으로 사용되는 모든 프로그래밍 플랫폼 / 언어를 통해 웹 서비스 엔드 포인트를 기본 URI에 쉽게 바인딩 할 수 있습니다. 이런 방식 으로 파일 / 클래스 / 메소드 모음 을 서로 다른 API 버전간에 쉽게 수집하고 보관할 수 있습니다 .
API 사용자 POV의 경우 이처럼 분명하지만 제한된 시간 동안 만 (예 : 개발 중) 특정 API 버전으로 작업하고 바인딩하는 것이 더 쉽습니다.
API 관리자의 POV에서 파일에 대해 가장 작은 단위 (소스 코드) 버전 관리로 주로 작업하는 소스 제어 시스템을 사용하여 서로 다른 API 버전을 병렬로 유지하는 것이 더 쉽습니다.
그러나 URI에 API 버전이 명확하게 표시되면주의해야 할 점이 있습니다. URI 히스토리에서 API 히스토리가 표시 / 부모 되기 때문에 시간 이 지남 에 따라 REST 지침에 위배되는 변경이 발생하기 때문에이 방법에 반대 할 수도 있습니다 . 동의한다!
이 합리적인 이의 제기를 해결하는 방법은 버전이없는 API 기본 URI에서 최신 API 버전을 구현하는 것입니다. 이 경우 API 클라이언트 개발자는 다음 중 하나를 선택할 수 있습니다.
최신 버전에 대비하여 개발하십시오 ( 잘못 설계된 API 클라이언트를 손상시킬 수있는 최종 API 변경으로부터 애플리케이션을 보호하기 위해 애플리케이션을 유지하기 위해 스스로 노력 ).
제한된 시간 동안 만 특정 버전의 API에 바인딩 (명확 해짐)
예를 들어, API v3.0이 최신 API 버전 인 경우 다음 두 개는 별명이어야합니다 (즉, 모든 API 요청과 동일하게 작동 함).
http : // shonzilla / api / customers / 1234 http : // shonzilla / api /v3.0 / customers / 1234 http : // shonzilla / api / v3 / customers / 1234
또한 사용 중인 API 버전이 더 이상 사용되지 않거나 더 이상 지원되지 않는 경우 여전히 이전 API 를 가리 키려고하는 API 클라이언트 에 최신 이전 API 버전을 사용하도록 알려야합니다 . 따라서 다음과 같이 사용되지 않는 URI에 액세스하십시오.
http : // shonzilla / api /v2.2 / customers / 1234 http : // shonzilla / api /v2.0 / customers / 1234 http : // shonzilla / api / v2 / customers / 1234 http : // shonzilla / api /v1.1 / customers / 1234 http : // shonzilla / api / v1 / customers / 1234
적절한 버전의 리소스 URI로 리디렉션되는 HTTP 헤더 와 함께 사용되는 리디렉션을 나타내는 30x HTTP 상태 코드 중 하나를 반환해야합니다 Location
.
http : // shonzilla / api / customers / 1234
API 버전 관리 시나리오에 적합한 리디렉션 HTTP 상태 코드가 두 개 이상 있습니다.
301 요청 된 URI가있는 자원이 다른 URI (API 버전 정보를 포함하지 않는 자원 인스턴스 영구 링크 여야 함)로 영구적으로 이동했음을 나타 내기 위해 영구적으로 이동했습니다. 이 상태 코드는 사용되지 않거나 지원되지 않는 API 버전을 나타내는 데 사용되어 버전이 지정된 리소스 URI가 리소스 permalink로 대체되었음을 API 클라이언트에 알립니다 .
302 요청한 리소스가 일시적으로 다른 위치에 있지만 요청 된 URI가 계속 지원 될 수 있음을 나타냅니다. 이 상태 코드는 버전이없는 URI를 일시적으로 사용할 수없고 리디렉션 주소를 사용하여 요청을 반복해야하는 경우 (예 : APi 버전이 포함 된 URI를 가리키는 경우) 클라이언트에게 계속 사용하도록 요청하려고 할 때 유용합니다. 퍼머 링크).
다른 시나리오는 HTTP 1.1 사양의 리디렉션 3xx 장 에서 찾을 수 있습니다
410 Gone
리디렉션이 새 위치가 호환되지 않을 때 리디렉션 할 수 있기 때문에 더 이상 지원되지 않고 더 이상 지원되지 않는 API가 반환해야한다고 말하고 싶습니다 . API가 단순히 폐기되었지만 여전히 존재 Warning
하는 경우 응답 의 HTTP 헤더가 옵션 일 수 있습니다.
URL에는 버전이 포함되지 않아야합니다. 버전은 요청한 리소스의 "아이디어"와 관련이 없습니다. URL을 원하는 개념의 경로로 생각해야합니다. 항목을 반환하려는 방식이 아닙니다. 버전은 객체의 개념이 아니라 객체의 표현을 나타냅니다. 다른 포스터가 말했듯이 요청 헤더에 형식 (버전 포함)을 지정해야합니다.
버전이있는 URL에 대한 전체 HTTP 요청을 보면 다음과 같습니다.
(BAD WAY TO DO IT):
http://company.com/api/v3.0/customer/123
====>
GET v3.0/customer/123 HTTP/1.1
Accept: application/xml
<====
HTTP/1.1 200 OK
Content-Type: application/xml
<customer version="3.0">
<name>Neil Armstrong</name>
</customer>
헤더에는 요청한 표현이 포함 된 행이 포함됩니다 ( "Accept : application / xml"). 그것이 버전이 있어야하는 곳입니다. 모두가 당신이 다른 형식으로 같은 것을 원할 수도 있고 고객이 원하는 것을 요청할 수 있어야한다는 사실을 좋아하는 것 같습니다. 위의 예에서 클라이언트가 요구되는 어떠한 하지 정말 원하는 것을의 진정한 표현 - 자원의 XML 표현입니다. 이론적으로 서버는 요청이 XML 인 한 요청과 완전히 관련이없는 것을 반환 할 수 있으며 그것이 잘못되었다는 것을 파싱해야합니다.
더 좋은 방법은 다음과 같습니다.
(GOOD WAY TO DO IT)
http://company.com/api/customer/123
===>
GET /customer/123 HTTP/1.1
Accept: application/vnd.company.myapp.customer-v3+xml
<===
HTTP/1.1 200 OK
Content-Type: application/vnd.company.myapp-v3+xml
<customer>
<name>Neil Armstrong</name>
</customer>
또한 클라이언트가 XML이 너무 장황하다고 생각하고 이제 JSON을 원한다고 가정 해 봅시다. 다른 예에서는 동일한 고객에 대한 새 URL이 있어야하므로 다음과 같이 끝납니다.
(BAD)
http://company.com/api/JSONv3.0/customers/123
or
http://company.com/api/v3.0/customers/123?format="JSON"
(또는 비슷한 것). 실제로 모든 HTTP 요청에는 원하는 형식이 포함됩니다.
(GOOD WAY TO DO IT)
===>
GET /customer/123 HTTP/1.1
Accept: application/vnd.company.myapp.customer-v3+json
<===
HTTP/1.1 200 OK
Content-Type: application/vnd.company.myapp-v3+json
{"customer":
{"name":"Neil Armstrong"}
}
이 방법을 사용하면 훨씬 더 자유롭게 디자인 할 수 있으며 실제로 REST의 원래 아이디어를 준수 할 수 있습니다. 클라이언트를 방해하지 않고 버전을 변경하거나 API가 변경됨에 따라 클라이언트를 점진적으로 변경할 수 있습니다. 표현 지원을 중단하기로 선택하면 HTTP 상태 코드 또는 사용자 정의 코드로 요청에 응답 할 수 있습니다. 클라이언트는 또한 응답이 올바른 형식인지 확인하고 XML을 검증 할 수 있습니다.
다른 많은 장점이 있으며 여기 내 블로그에서 그 중 일부를 설명합니다. http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html
URL에 버전을 배치하는 방법이 나쁜지 보여주는 마지막 예입니다. 객체 내부에 정보가 필요하고 다양한 객체의 버전을 지정했다고 가정합니다 (고객은 v3.0, 주문은 v2.0, shipto 객체는 v4.2). 클라이언트에 제공해야하는 불쾌한 URL은 다음과 같습니다.
(Another reason why version in the URL sucks)
http://company.com/api/v3.0/customer/123/v2.0/orders/4321/
-x
가에 의해 사용되지 않는 것으로 RFC6648 .
URL에 버전을 넣는 것이 실용적이고 유용하다는 것을 알았습니다. 사용중인 내용을 한 눈에 쉽게 알 수 있습니다. 허용되는 답변에서 알 수 있듯이 사용 편의성, 더 짧거나 더 깨끗한 URL 등을 위해 / foo를 / foo / (최신 버전)에 별칭으로 사용합니다.
이전 버전과의 호환성을 영원히 유지하는 것은 종종 비용이 많이 들고 어렵습니다. 더 이상 사용되지 않음, 여기에 제안 된 리디렉션, 문서 및 기타 메커니즘에 대한 고급 정보를 제공하는 것이 좋습니다.
리소스 표현을 버전 화하는 것이 REST 접근법을 따르는 것이 더 낫다는 것에 동의하지만 ... 사용자 정의 MIME 유형 (또는 버전 매개 변수를 추가하는 MIME 유형)의 큰 문제 중 하나는 HTML 및 자바 스크립트.
예를 들어, 리소스를 만들기 위해 IMO가 HTML5 양식으로 다음 헤더를 사용하여 POST 할 수 없습니다.
Accept: application/vnd.company.myapp-v3+json
Content-Type: application/vnd.company.myapp-v3+json
에서 HTML5 때문입니다 enctype
속성은 평소보다 다른 것을 따라서, 열거입니다 application/x-www-formurlencoded
, multipart/form-data
그리고 text/plain
유효하지 않습니다.
... HTML4의 모든 브라우저에서 지원되는지 확실하지 않습니다 (더 느슨한 encytpe 속성을 가지고 있지만 MIME 유형이 전달되었는지 여부에 대한 브라우저 구현 문제임)
이 때문에 버전에 가장 적합한 방법은 URI를 통한 것이라고 생각하지만 '올바른'방법이 아니라는 것을 인정합니다.
REST API에서 버전 관리를 수행 할 수있는 몇 가지 위치가 있습니다.
언급 한 바와 같이, URI에서. 방향 전환 등을 잘 사용하면 다루기 쉽고 심미적으로도 즐거울 수 있습니다.
Accepts : 헤더에서 버전은 파일 형식입니다. 'mp3'대 'mp4'와 같습니다. 이것은 또한 작동하지만 IMO는 조금 덜 잘 작동합니다 ...
자원 자체에서. 많은 파일 형식에는 일반적으로 헤더에 버전 번호가 포함되어 있습니다. 따라서 지원되지 않는 (최신) 버전이 지정되어 있으면 이전 소프트웨어는 펀트 할 수있는 반면 기존 소프트웨어는 파일 형식의 모든 기존 버전을 이해하여 최신 소프트웨어가 '작동'할 수 있습니다. REST API의 맥락에서 이는 URI를 변경할 필요가 없으며 사용자가 처리 한 특정 버전의 데이터에 대한 응답 만 의미합니다.
세 가지 접근 방식을 모두 사용해야하는 이유를 알 수 있습니다.
REST API 버전 관리는 다른 API 버전 관리와 유사합니다. 사소한 변경이 이루어질 수 있으며 주요 변경 사항에는 완전히 새로운 API가 필요할 수 있습니다. 가장 쉬운 방법은 매번 처음부터 시작하는 것입니다. URL에 버전을 넣는 것이 가장 합리적입니다. 클라이언트의 삶을 편하게하려면 더 이상 사용되지 않는 호환성 (영구적 리디렉션), 여러 버전의 리소스 등을 사용하여 이전 버전과의 호환성을 유지하려고합니다.이 방법은보다 까다 롭고 더 많은 노력이 필요합니다. 그러나 "쿨 URI는 변경되지 않습니다"에서 REST가 권장하는 사항이기도합니다.
결국 다른 API 디자인과 같습니다. 고객 편의를 위해 노력하십시오. API에 시맨틱 버전 관리를 채택하면 클라이언트가 새 버전과의 하위 호환성을 명확하게 알 수 있습니다.