예상되는 변경을 계획하는 REST 엔드 포인트에 권장되는 패턴은 무엇입니까?


25

변화에 대한 전망을 가지고 외부 애플리케이션을위한 API를 설계하는 것은 쉽지 않지만, 조금만 생각하면 나중에 인생을 더 쉽게 만들 수 있습니다. 이전 버전 처리기를 그대로 두어 이전 버전과의 호환성을 유지하면서 향후 변경 사항을 지원할 계획을 세우려고합니다.

이 기사의 주요 관심사는 주어진 제품 / 회사에 대해 정의 된 모든 엔드 포인트에 대해 어떤 패턴을 따라야 하는가입니다.

기본 체계

의 기본 URL 템플릿을 감안할 때 https://rest.product.com/모든 서비스 /api/auth와 같은 기타 비 기반 엔드 포인트와 함께 존재하도록 고안했습니다 /doc. 따라서 다음과 같이 기본 엔드 포인트를 설정할 수 있습니다.

https://rest.product.com/api/...
https://rest.product.com/auth/login
https://rest.product.com/auth/logout
https://rest.product.com/doc/...

서비스 엔드 포인트

이제 엔드 포인트 자체를 위해. 우려에 대해 POST, GET, DELETE이 문서의 주요 목적하지 않고 이러한 작업 자신의 관심사입니다.

엔드 포인트는 네임 스페이스와 작업으로 분류 될 수 있습니다. 각 조치는 리턴 유형 또는 필수 매개 변수의 근본적인 변경을 지원하는 방식으로 제시되어야합니다.

등록 된 사용자가 메시지를 보낼 수있는 가상 채팅 서비스를 사용하면 다음과 같은 엔드 포인트가있을 수 있습니다.

https://rest.product.com/api/messages/list/{user}
https://rest.product.com/api/messages/send

이제 향후 API 변경에 대한 버전 지원을 추가하여 중단 될 수 있습니다. 이후 /api/또는 이후에 버전 서명을 추가 할 수 있습니다 /messages/. send엔드 포인트가 주어지면 v1에 대해 다음을 가질 수 있습니다.

https://rest.product.com/api/v1/messages/send
https://rest.product.com/api/messages/v1/send

첫 번째 질문은 버전 식별자의 권장 장소는 무엇입니까?

컨트롤러 코드 관리

이제 이전 버전을 지원해야하므로 시간이 지남에 따라 더 이상 사용되지 않을 수있는 각각의 새 버전에 대한 코드를 처리해야합니다. Java로 엔드 포인트를 작성한다고 가정하면 패키지를 통해이를 관리 할 수 ​​있습니다.

package com.product.messages.v1;
public interface MessageController {
    void send();
    Message[] list();
}

이는 모든 코드가 네임 스페이스를 통해 분리되어 변경 사항이 변경되면 서비스 엔드 포인트의 새 사본이됨을 의미합니다. 이것의 단점은 모든 코드를 복사해야하며 버그 수정을 새로운 버전과 이전 버전에 적용하기를 원할 때마다 각 사본마다 적용 / 테스트해야한다는 것입니다.

다른 방법은 각 엔드 포인트에 대한 핸들러를 작성하는 것입니다.

package com.product.messages;
public class MessageServiceImpl {
    public void send(String version) {
        getMessageSender(version).send();
    }
    // Assume we have a List of senders in order of newest to oldest.
    private MessageSender getMessageSender(String version) {
        for (MessageSender s : senders) {
            if (s.supportsVersion(version)) {
                return s;
            }
        }
    }
}

이제는 각 엔드 포인트 자체에 대한 버전 관리를 분리하고 대부분의 경우 한 번만 적용하면되는 버그 수정 포트 호환 문제를 해결할 수 있지만,이를 지원하려면 각 개별 엔드 포인트에 대해 약간 더 많은 작업을 수행해야합니다.

따라서 "이전 버전을 지원하기 위해 REST 서비스 코드를 디자인하는 가장 좋은 방법은 무엇입니까?"라는 두 번째 질문이 있습니다.

답변:


13

따라서 "이전 버전을 지원하기 위해 REST 서비스 코드를 디자인하는 가장 좋은 방법은 무엇입니까?"라는 두 번째 질문이 있습니다.

매우 신중하게 설계된 직교 API는 이전 버전과 호환되지 않는 방식으로 변경할 필요가 없으므로 실제로 가장 좋은 방법은 향후 버전을 사용하지 않는 것입니다.

물론, 당신은 아마 첫 번째 시도를 얻지 못할 것입니다. 그래서:

  • 계획하고있는 것처럼 API의 버전을 지정하고 (개별 메소드가 아닌 버전이 지정된 API 임) API에 대해 많은 소음을 발생시킵니다. 파트너가 API가 변경 될 수 있으며 응용 프로그램이 최신 버전을 사용하고 있는지 확인해야하는지 확인하십시오. 최신 버전이 출시되면 사용자에게 업그레이드하도록 조언합니다. 2 개의 이전 버전을 지원하는 것은 어렵고 5 개를 지원하는 것은 불가능합니다.
  • 모든 "릴리스"마다 API 버전을 업데이트하도록 촉구하십시오. 새로운 기능은 일반적으로 기존 클라이언트를 중단하지 않고 현재 버전으로 롤업 할 수 있습니다. 그들은 새로운 기능입니다. 마지막으로 원하는 것은 클라이언트가 버전 번호 를 무시 하는 것입니다. 어쨌든 대부분 이전 버전과 호환되기 때문입니다. 기존 API를 중단하지 않고 전진 할 수없는 경우에만 API 버전을 업데이트하십시오.
  • 새 버전을 만들 때가되면 첫 번째 클라이언트는 이전 버전과 호환되는 이전 버전이어야합니다. "유지 보수 API"자체는 현재 API에서 구현되어야합니다. 이런 식으로 당신은 몇 가지 완전한 구현을 유지하기 위해 갈망하지 않습니다. 현재 버전과 이전 버전에 대한 몇 가지 "쉘"만 있습니다. 이전 버전의 호환 가능한 클라이언트에 대해 사용되지 않는 API에 대해 회귀 테스트를 실행하면 새 API와 호환성 계층을 모두 테스트 할 수 있습니다.

3

첫 번째 URI 디자인 옵션은 전체 API를 버전 화한다는 아이디어를 더 잘 표현합니다. 두 번째는 메시지 자체를 버전 화하는 것으로 해석 될 수 있습니다. 따라서 이것은 더 나은 IMO입니다.

rest.product.com/api/v1/messages/send

클라이언트 라이브러리의 경우 별도의 Java 패키지로 두 가지 완전한 구현을 사용하는 것이 더 깨끗하고 사용하기 쉽고 유지 관리하기 쉽다고 생각합니다.

즉, 버전 관리보다 API를 진화시키는 더 좋은 방법이 있습니다. 나는 당신이 그것을 준비해야한다는 것에 동의하지만, 버전 관리는 최후의 수단으로 신중하고 신중하게 사용되어야한다고 생각합니다. 클라이언트를 업그레이드하는 것은 비교적 큰 노력입니다. 얼마 전 나는 이러한 생각을 블로그 게시물에 넣었습니다.

http://theamiableapi.com/2011/10/18/api-design-best-practice-plan-for-evolution/

특히 REST API 버전 관리의 경우 Mark Nottingham의이 게시물이 도움이됩니다.

http://www.mnot.net/blog/2011/10/25/web_api_versioning_smackdown


3

API 버전 관리를 처리하는 또 다른 방법은 HTTP 헤더의 버전을 사용하는 것입니다. 처럼

POST /messages/list/{user} HTTP/1.1
Host: http://rest.service.com
Content-Type: application/json
API-Version: 1.0      <----- like here
Cache-Control: no-cache

헤더를 구문 분석하고 백엔드에서 적절하게 처리 할 수 ​​있습니다.

이 접근 방식을 사용하면 클라이언트는 URL을 변경할 필요가 없으며 헤더 만 변경하면됩니다. 또한 REST 엔드 포인트를 항상 깨끗하게 만듭니다.

클라이언트가 버전 헤더를 보내지 않은 경우 400-잘못된 요청을 보내 거나 이전 버전과 호환되는 API 버전으로 처리 할 수 ​​있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.