커스텀 메서드

이번 장에서는 API를 디자인할 때 커스텀 메서드를 사용하는 방법에 대해서 설명합니다.

커스텀 메서드란 5가지 표준 메서드를 제외한 API 메서드를 말합니다. 이 메서드는 표준 메서드를 통해 쉽게 표현할 수 없는 기능에만 사용되어야 합니다 일반적으로 API 디자이너는 가능하다면 커스텀 메서드보다는 표준 메서드를 선택해야 합니다. 표준 메서드는 간단할 뿐만 아니라 시맨틱스에 대한 정의도 효과적이고 대부분 개발자들에게 익숙하기 때문에 사용이 더욱 쉽고 발생하는 오류도 적습니다. 표준 메서드의 또 다른 이점은 결제, 오류 처리, 로깅, 모니터링 등에서 표준 메서드에 대한 API 플랫폼의 이해와 지원이 더욱 우수하다는 점입니다.

커스텀 메서드는 리소스, 컬렉션 또는 서비스와 연결될 수 있습니다. 또한 임의 요청을 사용해 임의 응답을 반환할 수 있으며, 그 밖에 스트리밍 요청 및 응답도 지원합니다.

커스텀 메서드 이름은 메서드 이름 지정 규칙따라야 합니다.

HTTP 매핑

커스텀 메서드는 다음과 같이 일반적인 HTTP 매핑을 사용해야 합니다.

https://service.name/v1/some/resource/name:customVerb

커스텀 동사를 리소스 이름과 구분할 때 /가 아닌 :를 사용하는 이유는 임의 경로를 지원하기 때문입니다. 예를 들어 파일 삭제 취소는 POST /files/a/long/file/name:undelete로 매핑될 수 있습니다.

HTTP 매핑을 선택할 때는 다음 가이드라인이 적용되어야 합니다.

  • 커스텀 메서드는 가장 유연한 시맨틱스를 가지고 있으므로 가능하면 GET을 사용할 있는 대체 get 또는 list의 역할을 하는 메서드를 제외하고 HTTP POST 동사를 사용해야 합니다. (자세한 내용은 세 번째 항목 참조)
  • 커스텀 메서드는 HTTP PATCH를 사용해서는 안 되지만 다른 HTTP 동사를 사용할 있습니다. 이러한 경우 메서드는 해당하는 동사에 맞는 표준 HTTP 시맨틱스따라야 합니다.
  • 특히 HTTP GET을 사용하는 커스텀 메서드는 반드시 멱등성을 가져야 하며 부작용이 없어야 합니다. 예를 들어 리소스에 대해 특별한 뷰를 구현하는 커스텀 메서드는 HTTP GET사용해야 합니다.
  • 커스텀 메서드가 연결되는 리소스 또는 컬렉션의 리소스 이름을 수신하는 요청 메시지 필드는 URL 경로에 매핑되어야 합니다.
  • URL 경로는 콜론에 이어 커스텀 동사로 구성되는 서픽스로 끝나야 합니다.
  • 커스텀 메서드에 사용되는 HTTP 동사가 HTTP 요청 본문을 허용하는 경우(POST, PUT, PATCH, 커스텀 HTTP 동사에 적용됨) 이러한 커스텀 메서드의 HTTP 구성은 body: "*" 절을 사용해야 하며 나머지 모든 요청 메시지 필드는 HTTP 요청 본문으로 매핑되어야 합니다.
  • 커스텀 메서드에 사용되는 HTTP 동사가 HTTP 요청 본문을 허용하지 않는 경우(GET, DELETE) 이러한 메서드의 HTTP 구성이 body 절을 사용해서는 안 되며 나머지 모든 요청 메시지 필드는 URL 쿼리 매개변수로 매핑되어야 합니다.

경고: 서비스가 다수의 API를 구현하는 경우 API 작성자는 서비스 구성을 만들 때 커스텀 동사가 API 사이에 충돌을 일으키지 않도록 신중해야 합니다.

// This is a service level custom method.
rpc Watch(WatchRequest) returns (WatchResponse) {
  // Custom method maps to HTTP POST. All request parameters go into body.
  option (google.api.http) = {
    post: "/v1:watch"
    body: "*"
  };
}

// This is a collection level custom method.
rpc ClearEvents(ClearEventsRequest) returns (ClearEventsResponse) {
  option (google.api.http) = {
    post: "/v3/events:clear"
    body: "*"
  };
}

// This is a resource level custom method.
rpc CancelEvent(CancelEventRequest) returns (CancelEventResponse) {
  option (google.api.http) = {
    post: "/v3/{name=events/*}:cancel"
    body: "*"
  };
}

// This is a batch get custom method.
rpc BatchGetEvents(BatchGetEventsRequest) returns (BatchGetEventsResponse) {
  // The batch get method maps to HTTP GET verb.
  option (google.api.http) = {
    get: "/v3/events:batchGet"
  };
}

사용 사례

커스텀 메서드가 올바른 선택이 될 수 있는 추가 시나리오는 다음과 같습니다.

  • 가상 머신 재부팅. 더욱 복잡하게 느낄 수도 있지만 '재부팅 컬렉션에 재부팅 리소스를 만드는 방법', 혹은 '클라이언트가 RUNNING에서 RESTARTING으로 업데이트할 수 있는 변경 가능 상태를 가상 머신이 갖는 방법'이 디자인 대안이 될 수 있습니다. 특히 두 번째 대안은 그 밖에 가능한 상태 전환에 대해 묻는 질문들을 떠올리게 됩니다. 더욱이 재부팅은 개발자의 기대치를 직관적으로 충족하는 커스텀 메서드로 변환하기에 잘 알려진 개념입니다.
  • 메일 보내기. 이메일 메시지를 작성한다고 해서 반드시 보내야 하는 것은 아닙니다(초안). 커스텀 메서드는 디자인 대안(메시지를 '보낼편지함' 컬렉션으로 이동)과 비교했을 때 API 사용자 및 모델에서 개념을 더욱 직접적으로 찾아낼 가능성이 더욱 높다는 이점이 있습니다.
  • 직원 승격. 표준 update로 구현될 경우 승격이 동일한 위계 내에서 올바른 수준으로 발생하도록 하려면 클라이언트가 승격 프로세스에 대한 기업 정책을 복제해야 합니다.
  • 일괄 메서드. 성능이 중요한 메서드일 경우에는 커스텀 일괄 메서드를 제공하여 요청별 오버헤드를 줄이는 것이 유용할 수 있습니다. 예를 들면 accounts.locations.batchGet이 있습니다.

표준 메서드가 커스텀 메서드보다 적합한 사례는 다음과 같습니다.

  • 쿼리 매개변수가 다른 쿼리 리소스(표준 목록 필터링과 함께 표준 list 메서드 사용)
  • 단순한 리소스 속성 변경(필드 마스크와 함께 표준 update 메서드 사용)
  • 알림 닫기(표준 delete 메서드 사용)

공통 커스텀 메서드

공통적으로 사용되거나 유용한 커스텀 메서드 이름의 선별 목록은 아래와 같습니다. API 디자이너가 자신의 메서드를 도입하여 API 사이의 일관성을 높이려면 먼저 다음과 같은 이름을 고려해야 합니다.

메서드 이름 커스텀 동사 HTTP 동사 참고사항
Cancel :cancel POST 대기 중인 작업(예: operations.cancel)을 취소합니다.
BatchGet :batchGet GET 다수의 리소스를 일괄 방식으로 가져옵니다. 자세한 내용은 List 설명을 참조하세요.
Move :move POST 리소스를 상위 수준에서 다른 수준으로 이동합니다(예: folders.move).
Search :search GET List 시맨틱스를 따르지 않는 데이터를 가져오기 위한 List의 대안입니다(예: services.search).
Undelete :undelete POST 이전에 삭제했던 리소스를 복원합니다(예: services.undelete). 권장 보관 기간은 30일입니다.