이 문서에서는 Google API와 다양한 HTTP 버전 및 구현이 함께 작동하는 방식을 설명합니다. 생성되었거나 직접 작성된 클라이언트 라이브러리 (대부분 사용 사례에서 권장되는 방식)를 사용하는 경우 이러한 세부정보에 대해 걱정할 필요가 없습니다. 라이브러리는 서버와의 하위 수준 통신을 자동으로 처리합니다.
서드 파티 HTTP 클라이언트를 사용하여 API의 REST 인터페이스에 액세스하는 맞춤 코드를 작성하는 숙련된 개발자라면 여기에 설명된 관련 개념과 선택한 HTTP 라이브러리에서 제공하는 기능을 이해해야 합니다.
통신 프로토콜 사용(HTTP/*)
이 섹션에서는 Google API가 클라이언트와 서버 간 통신에 사용할 수 있도록 지원되는 통신 프로토콜 (일반적으로 HTTP 버전)과 지원되는 통신 프로토콜 사용 시 권장하는 방식을 설명합니다.
HTTP 시맨틱스
API 클라이언트 코드를 개발할 때는 표준 HTTP 프로토콜 시맨틱스를 따릅니다. 서버 측 프록시 또는 API 스택은 표준 HTTP 기능의 하위 집합만 지원하거나, 혹은 하위 호환이 가능한 버전까지 지원할 수도 있습니다.
API의 서버 측 구현체에서 처리해야 하는 HTTP 프로토콜 시맨틱스는 서버 스택에서 제어됩니다. 이러한 기능이 캐싱 지원처럼 API 사양에 명시적으로 포함되어 있는 경우에는 HTTP 프로토콜 시맨틱스만 사용하세요.
HTTP 버전
클라이언트는 클라이언트 플랫폼 또는 클라이언트 측 네트워크에서 허용되거나 서버 측 프록시와의 협상에 따라 모든 HTTP/* 프로토콜을 사용할 수 있습니다. 지원되는 프로토콜에는 HTTP/1.1, HTTP/2, HTTP/3 (QUIC)이 있습니다. HTTP/1.0의 기존 지원은 권장되지 않습니다.
일부 API 기능은 최신 HTTP 프로토콜 버전에서만 지원될 수 있고, 전이중 멀티플렉스 스트리밍과 같은 일부 기능은 HTTP/2 및 HTTP/3에서만 완전하게 지정될 수 있습니다. API 사양에 이러한 기능이 필요한 경우 HTTP 버전에 따라 사용이 제한된다는 점을 알고 있어야 합니다. HTTP/2 서버 푸시와 같은 이전 기능은 지원 중단되었으며 최신 웹 클라이언트에서 지원되지 않습니다.
일반적으로 성능 향상, HOL 차단 감소, 네트워크 오류에 대한 복원력 향상을 위해 HTTP/3 또는 HTTP/2를 사용하는 것이 좋습니다.
채널
채널은 일반적으로 HTTP/1.1 및 HTTP/2의 경우 TCP 소켓, HTTP/3 (QUIC)의 경우 UDP 소켓인 Layer 4 네트워크 연결을 말합니다. 연결은 거의 항상 서버 프로세스를 대신하여 Google 프런트엔드(GFE) 프록시에 의해 종료되므로 클라이언트 애플리케이션은 채널이 엔드 투 엔드로 관리되는 방식에 대해 가정해서는 안 됩니다.
HTTP/1.1 클라이언트: HTTP/1.1을 사용하는 경우 항상 TCP 연결(연결: 연결 유지)을 재사용합니다. HTTP 클라이언트 라이브러리는 일반적으로 재사용을 용이하게 하기 위해 연결 풀을 관리합니다. HTTP/1.1 연결에서 HTTP 파이프라인을 사용하지 마세요. 지원이 제대로 되지 않아 문제가 발생할 수 있습니다. 자세한 내용은 HTTP 및 TCP를 참고하세요.
HTTP/2 및 HTTP/3 클라이언트: 최신 클라이언트와 브라우저는 주로 HTTP/2 또는 HTTP/3을 사용합니다. 두 프로토콜 모두 멀티플렉싱을 지원하므로 단일 연결을 통해 여러 요청과 응답이 동시에 진행될 수 있습니다.
- HTTP/2: 원본당 단일 TCP 연결을 사용합니다.
- HTTP/3: 출처당 UDP를 통해 단일 QUIC 연결을 사용합니다. QUIC는 TLS 암호화, 정체 제어, 연결 관리를 통합하여 연결 설정 속도 (0-RTT 또는 1-RTT) 및 스트림 간 TCP HOL 차단에 대한 내성과 같은 이점을 제공하는 경우가 많습니다.
HTTP/2 및 HTTP/3에서는 단일 호스트에 대한 병렬 TCP 연결 수에 대한 브라우저 제한 (예: 2~10)이 더 이상 주요 성능 문제가 아닙니다. 하지만 서버 (또는 GFE와 같은 프록시)는 단일 HTTP/2 또는 HTTP/3 연결 내에서 동시 스트림의 최대 수를 제한할 수 있습니다. 이렇게 하면 과부하를 방지하고 공정한 리소스 사용을 보장할 수 있습니다 (예: 연결당 동시 요청 또는 스트림을 100개로 제한).
HTTPS
클라이언트는 API 사양에서 지원하는 HTTPS 또는 HTTP를 사용하여 API에 액세스할 수 있습니다. TLS 협상 및 TLS 버전은 클라이언트 애플리케이션에 투명합니다. Google API는 기본적으로 HTTPS 트래픽만 허용합니다.
요청 및 응답 형식
이 섹션에서는 URL 인코딩 데이터 사용, RESTful 작업을 위한 특정 HTTP 메서드, JSON 기반 페이로드 형식을 비롯한 API 상호작용 구조를 설명합니다.
요청 URL
JSON-REST 매핑은 URL로 인코딩된 요청 데이터를 지원하며 HTTP 요청과 응답 본문은 application/json을 Content-Type으로 사용합니다.
HTTP 본문은 JSON 배열을 사용하여 스트리밍되는 RPC 메서드를 지원하며, JSON 배열에는 다수의 JSON 메시지 또는 오류 상태 JSON 메시지가 포함될 수 있습니다.
긴 요청 URL
URL에는 실제 길이 제한이 있으며, 일반적으로 기본적으로 16KB로 설정되지만 서버에 따라 다를 수 있습니다. API가 이 길이를 초과하는 URL과 함께 GET 요청을 사용하면 요청이 대상 API 서버에 도달하지 못하고 Google 프런트엔드 (GFE)에서 Your client has issued a malformed or illegal request. 오류 메시지와 함께 거부됩니다.
이러한 제한을 우회하려면 클라이언트 코드는 HTTP 헤더 X-HTTP-Method-Override: GET과 함께 Content-Type을 application/x-www-form-urlencoded로 하여 POST 요청을 사용해야 합니다. 이 방법은 DELETE 요청에도 사용할 수 있습니다.
HTTP 메서드 (동사)
요청 URL이 REST 모델을 따르는 경우에는 HTTP 메소드가 API 사양의 일부로 지정됩니다. 특히 모든 API 메서드는 API 메서드가 매핑되는 특정 HTTP 동사에 따라 HTTP 프로토콜의 요구사항을 준수해야 합니다 자세한 내용은 HTTP(Hypertext Transfer Protocol) 사양과 PATCH 메서드 RFC를 참고하세요.
HTTP GET 및 HEAD와 같은 안전한 메서드는 가져오기 외에 다른 작업을 표현해서는 안 됩니다. 특히 HTTP GET은 안전한 메서드로 간주되어야 하며 클라이언트에서 나타나는 부작용이 있어서는 안 됩니다.
HTTP의 멱등성은 다수의 동일한 요청에서 발생하는 부작용이 단일 요청에서 발생하는 부작용과 동일하다는 것을 의미합니다. GET, PUT, DELETE는 스타일 가이드와 관련된 멱등성을 갖는 HTTP 메서드입니다. 단, 멱등성은 오직 서버 부작용과 관련하여 표현되며, 응답에 대해서는 어떤 것도 지정하지 않습니다. 특히 존재하지 않는 리소스의 DELETE는 404 (Not Found)를 반환해야 합니다.
HTTP POST 및 PATCH는 안전한 메소드도 아니고 멱등성을 갖지도 않습니다. PATCH는 RFC 5789에서 도입되었습니다.
| HTTP 동사 | 안전 | 멱등성 |
|---|---|---|
GET |
예 | 예 |
PUT |
예 | |
DELETE |
예 | |
POST |
||
PATCH |
페이로드 형식
요청과 응답은 '
application/x-www-form-urlencoded' 본문에서 요청이GET또는POST인 경우를 제외하고 동일한 Content-Type을 공유해야 합니다.JSON은
application/jsonMIME 유형에서 지원됩니다. proto3과 JSON의 매핑은 JSON 매핑에서 공식적으로 지정됩니다.양식 매개변수 (
POST)는 URL 쿼리 매개변수 (GET) 대신에 사용될 수 있지만 요청 필드를 쿼리 매개변수에 매핑할 때는 동일한 REST 스타일 매핑 규칙을 따라야 합니다. 지원되는Content-Type은application/x-www-form-urlencoded입니다.
스트리밍
이 섹션에서는 Google API가 클라이언트 및 서버 스트리밍을 처리하는 방법을 자세히 설명하며, 특히 반이중 통신과 전이중 통신의 제약 조건과 스트리밍된 JSON 메시지의 인코딩 요구사항을 다룹니다.
반이중과 전이중의 비교
HTTP는 TCP(HTTP/1.x) 또는 다중화 변형(SPDY, HTTP/2, QUIC) 같이 서로 다른 스트림 중심 전송을 통해 요청 또는 응답 본문을 전송할 수 있는 요청-응답 프로토콜입니다.
클라이언트 개발자의 애플리케이션은 요청 본문을 스트리밍 모드인 클라이언트 스트리밍으로 작성할 수 있습니다. 마찬가지로 애플리케이션은 응답 본문을 스트리밍 모드인 서버 스트리밍으로 사용할 수도 있습니다.
하지만 HTTP 사양은 요청 본문이 여전히 대기 중일 때 서버에서 응답 본문을 다시 스트리밍할 수 있는지 여부를 지정하지 않습니다 (오류 응답인 경우 제외). 이러한 시맨틱스는 전이중 스트리밍이라고 알려져 있습니다. 다수의 HTTP 클라이언트/서버/프록시 소프트웨어 프로그램이 HTTP/1.1일 때도 전이중 스트리밍을 허용하여 상호 운용성 문제를 피하고 있지만 HTTP 기반 Cloud API에서는 반이중 스트리밍으로 제한됩니다.
기본적으로 Cloud API의 양방향 스트리밍 방식은 전이중 시맨틱스라고 가정합니다. 즉, HTTP를 사용하여 이러한 메서드를 호출하는 것은 안전하지 않습니다. 스트리밍 방식이 서버에서 적용되는 반이중 방식인 경우 API 문서는 반이중 동작을 명확하게 지정해야 합니다.
브라우저 클라이언트의 경우 표준 HTTP 시맨틱스는 브라우저 네트워크 API에 의해 추가 제한을 받습니다. 브라우저는 XHR 또는 Fetch를 사용하여 서버 스트리밍 (일반적으로 전송 수준 프레이밍 준수)을 지원합니다. Fetch API는 whatwg 스트림을 사용합니다.
브라우저 제한이 있으므로 브라우저 지원이 필요한 Cloud API는 클라이언트 스트리밍과 전이중 스트리밍을 피하거나 브라우저 클라이언트 전용 별도의 API를 제공해야 합니다.
일반적으로 인터넷을 통한 클라이언트 스트리밍은 서버 스트리밍보다 유용하지 못합니다. 클라이언트 스트리밍을 사용하면 종종 상태 저장 서비스로 이어져 부하 분산에 악영향을 미칠 뿐만 아니라 장애 또는 공격에 대한 시스템 취약점이 더욱 커지기 때문입니다. 반면에 서버 스트리밍은 긴 RTT 지연으로 네트워크의 지연 시간을 크게 줄일 수 있으므로 유용합니다.
메시지 인코딩
JSON 메시지는 스트리밍할 때 JSON 메시지 배열로 인코딩됩니다. 이때 요청 또는 응답 본문은 유효한 JSON MIME 유형을 유지합니다.
클라이언트 스트리밍 인코딩 예는 다음과 같습니다.
1 <length> <message-bytes> 1 <length> <message-bytes> … EOF
서버 스트리밍 인코딩 예는 다음과 같습니다.
1 <length> <message-bytes> … 2 <length> <status-bytes> EOF
통신 수준 인코딩: StreamBody 정의는 '메시지' 및 '상태' 필드의 태그-id 할당에서만 의미가 있으며 <length>는 일반 메시지일 때 1~2바이트로 인코딩되는 변형이므로 전체 인코딩 오버헤드는 메시지당 2~3바이트입니다.
선택 사항인 패딩 필드는 base64 인코딩 스트림을 지원하는 데 필요합니다.
message StreamBody {
repeated bytes message = 1;
google.rpc.Status status = 2;
repeated bytes padding = 15; // max one-byte tag-id: xxx01111
}
오류 메시지는 일반 메시지와 동일한 형식에 따라 JSON 또는 protobuf 배열의 마지막 요소로 첨부되어야 합니다.
상태 관리
절반 종료 동작은 클라이언트 또는 서버가 본문이 완성되었다는 사실을 서로 반대쪽에 알리기 위해 사용하는 모든 HTTP 버전에 알기 쉽게 정의되어 있습니다.
특히 응답을 기다리고 있을 때도 클라이언트 코드를 자유롭게 사용하여 요청을 완성할 수 있습니다. 마찬가지로 클라이언트는 요청 본문이 서버에 작성되고 있는 도중에서 완성된 응답을 볼 수 있습니다. HTTP 표준에 따라 클라이언트는 예상치 못한 방식으로 응답이 완성되었을 때 일반적으로 오류 상태와 함께 요청을 취소하거나 완성할 수 있습니다. 다시 말해서 정상적인 조건에서 클라이언트가 요청을 보내고 있을 때 서버가 응답을 완성해서는 안 됩니다.
해지
클라이언트는 취소 기능이 지원되어 요청 또는 응답이 대기 중일 때 요청을 취소할 수 있습니다.
HTTP/1.* 클라이언트에서는 안정적으로 지원되는 취소 기능이 없습니다. 요청 또는 응답 트랜잭션을 중단하지 않고 요청이 완료된 후에는 클라이언트가 자유롭게 TCP 연결을 종료할 수 있기 때문입니다. HTTP/1.1에 따른 TCP FIN은 연결이 연결 유지로 표시되어 있더라도 (연결: 연결 유지) 취소로 해석되어서는 안 됩니다.
하지만 클라이언트가 TCP 연결을 종료한 이후에 서버가 데이터를 클라이언트에 작성하려고 하면 RST가 생성되어 취소 기능을 트리거할 수 있습니다.
스트리밍이 아닌 API에서도 취소는 문제가 될 수 있습니다. 특히 응답에 긴 폴링이 포함되어 연결이 장시간 유휴 상태로 유지되는 경우에 그렇습니다.
명시적인 취소 기능은 SPDY, HTTP/2 및 QUIC에서, 특히 종료 메시지와 함께 지원됩니다.
연결 유지
연결 유지 기능이 지원되어 클라이언트 또는 서버가 패킷 손실 또는 네트워크 장애가 발생하는 이벤트에서도 잘못된 피어를 찾아낼 수 있습니다.
HTTP/1.1에서는 연결 유지 기능이 지원되지 않습니다. TCP 연결 유지가 가능하지 않기 때문입니다.
QUIC 또는 HTTP/2는 브라우저를 포함해 애플리케이션에서 연결 유지 기능을 지원할 수 있도록 특별한 제어 메시지를 제공합니다.
하지만 안정적인 연결 유지와 장애 감지를 위해서는 서버 측 지원과 함께 클라이언트 라이브러리가 필요할 수 있습니다. 인터넷을 통해 스트리밍을 장시간 지속할 때 기본적인 HTTP에만 의존하여 통신 프로토콜을 이용할 경우 오류가 자주 발생하기 때문입니다.
흐름 관리
흐름 제어 기능을 지원하려면 클라이언트가 전송 수준의 흐름 제어 이벤트를 클라이언트 애플리케이션까지 전파해야 합니다. 실제 메커니즘은 클라이언트 애플리케이션이 사용하는 HTTP 클라이언트 API의 스타일에 따라 달라집니다. 예를 들어 애플리케이션이 클라이언트 또는 서버가 과부하에 걸리지 않도록 흐름 제어 이벤트를 처리하거나 따를 수 있도록 하려면 명시적인 흐름 제어 지원과 함께 블로킹 쓰기 및 읽기 또는 비블로킹 읽기 및 쓰기가 필요합니다.
HTTP/1.1은 TCP 흐름 제어를 이용합니다.
SPDY와 HTTP/2에는 자체적으로 스트림 수준의 흐름 제어 기능이 있지만 요청이 단일 TCP 연결을 통해 다중화될 때는 연결 수준의 TCP 흐름 제어 기능이 추가로 적용됩니다.
QUIC는 UDP에서 실행되기 때문에 흐름 제어 기능을 완전히 자체적으로 관리합니다.