HTTP API를 위한 구조화된 오류 메시지

Nicolas Fränkel

Nicolas Fränkel

November 2, 2022

Technology

Apache APISIX 프로젝트에서 작업을 시작한 이후로, 저는 REST RESTful HTTP API에 대한 지식과 이해를 향상시키기 위해 노력해왔습니다. 이를 위해 다음과 같은 자료를 읽고 보고 있습니다:

  • 책. 현재 API Design Patterns를 마무리하고 있습니다. 곧 리뷰를 기대해주세요.
  • YouTube. ErikWilde의 채널을 추천합니다. 모든 동영상이 API에 초점을 맞추고 있으며, 일부 동영상은 다른 것들보다 더 좋습니다.
  • IETF RFCs. 대부분의 RFC는 API에 관한 것이 아니지만, 친절한 사람이 API 관련 RFC 목록을 정리해두었습니다.

오늘은 "HTTP API를 위한 문제 세부 정보" RFC, 즉 RFC 7807을 소개하고자 합니다.

문제점

REST 원칙은 HTTP 상태를 사용하여 통신하도록 요구합니다. 오류의 경우, HTTP는 두 가지 범위를 정의합니다: 클라이언트 오류, 4xx, 그리고 서버 오류, 5xx.

은행 API가 계좌 이체를 허용한다고 상상해보세요. 계좌에 더 많은 자금을 이체하려고 하면 실패해야 합니다. 몇 가지 HTTP 상태 코드가 적합할 수 있습니다:

  • 400 Bad Request: 서버가 클라이언트 오류로 인식되는 무언가 때문에 요청을 처리할 수 없거나 처리하지 않을 것입니다.
  • 402 Payment Required: 클라이언트가 결제를 할 때까지 요청을 처리할 수 없습니다. 그러나 표준 사용 규칙이 없으며, 다른 엔티티가 다른 맥락에서 이를 사용합니다.
  • 409 Conflict: 요청이 대상 리소스의 현재 상태와 충돌합니다.

첫 번째 문제는 HTTP 상태 코드가 브라우저를 통한 인간-기계 상호작용을 위해 지정되었지, API를 통한 기계-기계 상호작용을 위해 지정된 것이 아니라는 점입니다. 따라서 사용 사례에 일대일로 매핑되는 상태 코드를 선택하는 것은 거의 직관적이지 않습니다. 참고로, Martin Fowler는 우리의 경우 409를 선호하는 것 같습니다.

상태 코드가 무엇이든, 두 번째 문제는 오류 페이로드 또는 더 정확히 말하면 그 구조에 관한 것입니다. 클라이언트와 API 제공자가 단일 조직에서 관리하는 경우 구조는 중요하지 않습니다. 각각을 전담 팀이 개발하더라도, 그들은 조율할 수 있습니다. 예를 들어, 자체 API를 호출하는 모바일 앱을 상상해보세요.

그러나 팀이 제3자 API를 사용하기로 결정할 때 문제가 발생합니다. 이 경우 응답 구조의 선택은 중요한데, 이제는 계약의 일부로 간주되기 때문입니다: 제공자의 어떤 변경도 클라이언트를 깨뜨릴 수 있습니다. 더 나쁜 것은, 구조가 제공자마다 다를 가능성이 높다는 점입니다.

따라서 표준화된 오류 보고 구조는:

  • 제공자 간의 일관성을 제공합니다.
  • API의 안정성을 증가시킵니다.

RFC 7807

RFC 7807은 표준화된 오류 구조를 제공하여 이 문제를 해결하려고 합니다.

구조는 다음과 같습니다:

구조

RFC는 필드를 설명합니다:

  • "type" (string) - 문제 유형을 식별하는 URI 참조 [RFC3986]. 이 사양은 역참조될 때 문제 유형에 대한 인간이 읽을 수 있는 문서를 제공할 것을 권장합니다 (예: HTML [W3C.REC-html5-20141028] 사용). 이 멤버가 없을 경우, 그 값은 "about:blank"로 간주됩니다.
  • "title" (string) - 문제 유형에 대한 짧고 인간이 읽을 수 있는 요약. 문제 발생마다 변경되어서는 안 되며, 지역화 목적 (예: 사전 콘텐츠 협상 사용; [RFC7231, Section 3.4] 참조)을 제외하고는 변경되어서는 안 됩니다.
  • "status" (number) - 이 문제 발생에 대해 원본 서버가 생성한 ([RFC7231], Section 6) 상태 코드.
  • "detail" (string) - 이 문제 발생에 대한 인간이 읽을 수 있는 설명.
  • "instance" (string) - 문제의 특정 발생을 식별하는 URI 참조. 역참조될 경우 추가 정보를 제공할 수도 있고 제공하지 않을 수도 있습니다.

-- 문제 세부 정보 객체의 멤버

RFC는 은행 이체를 위한 자금이 부족할 때의 샘플을 제공합니다.

RFC 예제

예제

저는 기존 데모 중 하나를 예로 사용하겠습니다. 이 데모는 API를 진화시키는 과정을 쉽게 하기 위한 여러 단계를 강조합니다.

6단계에서 사용자가 등록하도록 하고, 인증되지 않은 경우 시간 창 내의 호출 횟수를 제한합니다. 이를 위해 전용 Apache APISIX 플러그인을 만들었습니다. 호출 횟수가 제한에 도달하면 다음과 같이 반환합니다:

HTTP/1.1 429 Too Many Requests
Date: Fri, 28 Oct 2022 11:56:11 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.15.0

{"error_msg":"Please register at https:\/\/apisix.org\/register to get your API token and enjoy unlimited calls"}

이 메시지를 RFC 7807에 따라 구조화해보겠습니다.

RFC 7807 규칙

결론

RFC 7807은 클라이언트 개발자뿐만 아니라 API 구현자에게도 큰 도움이 됩니다. 이는 모든 프로젝트에서 바퀴를 다시 발명하지 않도록 빠른 지침을 제공합니다.

더 알아보기:

원본은 2022년 10월 30일 A Java Geek에 게시되었습니다.

Tags: