이 문서에서는 애플리케이션의 성능을 개선할 수 있는 몇 가지 기술에 대해 설명합니다. 경우에 따라 개념을 설명하기 위해 다른 API 또는 일반적인 API의 예가 사용되기도 하지만, Gmail API에도 동일한 개념이 적용됩니다.
gzip을 사용한 압축
각 요청에 필요한 대역폭을 줄이는 쉽고 편리한 한 가지 방법은 gzip 압축을 사용하는 것입니다. 이 경우 결과를 압축 해제하려면 CPU 시간이 추가로 필요하기는 하지만 대신에 네트워크 비용을 절감할 수 있다는 장점이 있습니다.
gzip으로 인코딩된 응답을 받으려면 Accept-Encoding
헤더를 설정하고 사용자 에이전트에 gzip
문자열이 포함되도록 수정해야 합니다. 다음은 gzip 압축을 사용할 수 있도록 적절하게 구성된 HTTP 헤더의 예시입니다.
Accept-Encoding: gzip User-Agent: my program (gzip)
부분 리소스 작업
API 호출의 성능을 개선하는 또 다른 방법은 관심 있는 데이터 부분만 보내고 받는 것입니다. 이렇게 하면 애플리케이션에서 불필요한 필드를 전송하고 파싱하고 저장하지 않게 되므로 네트워크, CPU, 메모리를 포함한 리소스를 더 효율적으로 사용할 수 있습니다.
다음과 같은 두 가지 유형의 부분 요청이 있습니다.
부분 요청을 작성하는 자세한 방법은 다음 섹션에 설명되어 있습니다.
부분 응답
기본적으로 서버에서는 요청을 처리한 후에 전체 리소스 표현을 반환합니다. 더 나은 성능을 위해 서버에 필요한 필드만 전송하도록 요청하여 부분 응답을 받을 수 있습니다.
부분 응답을 요청하려면 fields
요청 매개변수를 사용하여 반환받을 필드를 지정합니다. 응답 데이터를 반환하는 모든 요청에서 이 매개변수를 사용할 수 있습니다.
fields
매개변수는 응답 데이터에만 영향을 주며 전송해야 하는 데이터에는 영향을 주지 않습니다. 리소스를 수정할 때 전송하는 데이터의 양을 줄이려면 패치 요청을 사용하세요.
예
다음 예시에서는 일반적인(가상의) 'Demo' API에 fields
매개변수를 사용하는 방법을 보여 줍니다.
단순 요청: 이 HTTP GET
요청은 fields
매개변수를 생략하고 전체 리소스를 반환합니다.
https://www.googleapis.com/demo/v1
전체 리소스 응답: 전체 리소스 데이터에는 다음과 같은 필드가 포함됩니다. 여기에는 보기 쉽게 일부 필드만 포함되었으며 다른 많은 필드는 생략되어 있습니다.
{ "kind": "demo", ... "items": [ { "title": "First title", "comment": "First comment.", "characteristics": { "length": "short", "accuracy": "high", "followers": ["Jo", "Will"], }, "status": "active", ... }, { "title": "Second title", "comment": "Second comment.", "characteristics": { "length": "long", "accuracy": "medium" "followers": [ ], }, "status": "pending", ... }, ... ] }
부분 응답 요청: 같은 리소스에 대한 다음 요청에서는 반환되는 데이터의 양을 대폭 줄이기 위해 fields
매개변수를 사용합니다.
https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)
부분 응답: 위 요청에 대해 서버에서 반환하는 응답에는 종류(kind) 정보와 짧게 줄인 항목(items) 배열만 포함되며, 이 항목 배열에는 각 항목의 HTML 제목 및 길이 특성 정보만 포함됩니다.
200 OK
{ "kind": "demo", "items": [{ "title": "First title", "characteristics": { "length": "short" } }, { "title": "Second title", "characteristics": { "length": "long" } }, ... ] }
이 응답은 선택한 필드와 해당 필드가 속한 상위 객체만 포함하는 JSON 객체입니다.
fields
매개변수의 형식을 지정하는 자세한 방법은 다음 부분에서 다루고 있으며, 그 다음 부분에는 응답에서 정확히 무엇이 반환되는지에 대해 자세히 설명되어 있습니다.
fields 매개변수 구문 요약
fields
요청 매개변수의 값 형식은 대략 XPath 구문을 기반으로 합니다. 지원되는 구문은 아래에 요약되어 있으며 이어지는 섹션에서 추가적인 예시를 확인할 수 있습니다.
- 여러 필드를 선택하려면 쉼표로 구분된 목록을 사용합니다.
a
필드 내에 중첩된b
필드를 선택하려면a/b
를 사용하고,b
내에 중첩된c
필드를 선택하려면a/b/c
를 사용합니다.
예외:
data: { ... }
와 같이 응답이data
객체 내에 중첩되도록 'data' 래퍼를 사용하는 API 응답의 경우fields
사양에 'data
'를 포함하지 마세요. 필드를 지정할 때data/a/b
와 같이 data 객체를 포함하면 오류가 발생합니다. 대신fields
를a/b
와 같이 지정하세요.- 배열 또는 객체의 특정 하위 필드 세트를 요청하려면 하위 선택자를 사용하여 표현식을 괄호 '
( )
'로 묶습니다.예:
fields=items(id,author/email)
는 items 배열에 포함된 각 요소의 항목 ID와 작성자 이메일만 반환합니다. 하위 필드를 하나만 지정할 수도 있으며, 이때fields=items(id)
는fields=items/id
와 같습니다. - 필요한 경우 필드 선택 구문에 와일드 카드를 사용합니다.
예:
fields=items/pagemap/*
는 페이지 지도 내의 모든 객체를 선택합니다.
fields 매개변수 사용 방법의 추가 예시
아래 예시에서는 fields
매개변수 값이 응답에 미치는 영향을 설명합니다.
참고: 모든 쿼리 매개변수 값과 마찬가지로 fields
매개변수 값도 URL로 인코딩되어야 합니다. 이 문서의 예시에는 보기 쉽도록 인코딩이 생략되어 있습니다.
- 반환받을 필드 지정(또는 필드 선택)
fields
요청 매개변수 값은 쉼표로 구분된 필드 목록이며 각 필드는 응답의 루트를 기준으로 지정됩니다. 따라서 list 작업을 수행하는 경우에는 응답으로 컬렉션이 반환되며, 일반적으로 이 응답에는 리소스 배열이 포함됩니다. 하나의 리소스를 반환하는 작업을 수행하는 경우에는 리소스를 기준으로 필드가 지정됩니다. 선택한 필드가 배열(또는 배열의 일부)인 경우 서버에서는 배열의 모든 요소 중에서 선택된 부분을 반환합니다.
다음은 컬렉션 수준의 몇 가지 예시입니다.
예시 효과 items
items 배열의 모든 요소를 반환하며 각 요소의 모든 필드가 포함되지만 다른 필드는 제외됩니다. etag,items
etag
필드 및 items 배열의 모든 요소를 반환합니다.items/title
items 배열에 포함된 모든 요소의 title
필드만 반환합니다.
중첩 필드가 반환되는 경우 응답에는 항상 해당 필드가 속한 상위 객체가 포함됩니다. 명시적으로 함께 선택하지 않은 다른 하위 필드는 상위 필드에 포함되지 않습니다.context/facets/label
context
객체 아래에 중첩된facets
배열의 모든 구성원에 대해label
필드만 반환합니다.items/pagemap/*/title
items 배열의 각 요소에 대해 pagemap
의 하위 항목인 모든 객체의title
필드(있는 경우)만 반환합니다.
다음은 리소스 수준의 몇 가지 예시입니다.
예시 효과 title
요청된 리소스의 title
필드를 반환합니다.author/uri
요청된 리소스에서 author
객체의uri
하위 필드를 반환합니다.links/*/href
links
의 하위 요소인 모든 객체의href
필드를 반환합니다.- 하위 선택을 사용하여 특정 필드의 일부만 요청
- 기본적으로 요청에서 특정 필드를 지정하면 서버에서는 해당하는 객체 또는 배열 요소 전체를 반환합니다. 하지만 특정 하위 필드만 포함하는 응답을 지정할 수도 있습니다. 아래 예시와 같이 '
( )
' 하위 선택 구문을 사용하면 됩니다.예 효과 items(title,author/uri)
items 배열에 포함된 각 요소에 대해 title
및 author의uri
값만 반환합니다.
부분 응답 처리
서버는 fields
쿼리 매개변수가 포함된 유효한 요청을 처리한 후 요청된 데이터와 함께 HTTP 200 OK
상태 코드를 반환합니다. fields
쿼리 매개변수에 오류가 있거나 매개변수가 유효하지 않은 경우 서버에서는 HTTP 400 Bad Request
상태 코드와 함께 필드 선택에 어떤 문제가 있는지 알려 주는 오류 메시지(예: "Invalid field selection a/b"
)를 반환합니다.
다음은 위 소개 섹션에 나와 있는 부분 응답의 예입니다. 요청에서는 fields
매개변수를 사용하여 반환할 필드를 지정합니다.
https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)
부분 응답은 다음과 같습니다.
200 OK
{ "kind": "demo", "items": [{ "title": "First title", "characteristics": { "length": "short" } }, { "title": "Second title", "characteristics": { "length": "long" } }, ... ] }
참고: 데이터 페이지 나누기를 위한 쿼리 매개변수(예: maxResults
및 nextPageToken
)를 지원하는 API의 경우 이러한 매개변수를 사용하여 각 쿼리의 결과를 관리 가능한 크기로 줄이세요. 그러지 않으면 부분 응답을 사용해도 성능이 개선되지 않을 수 있습니다.
패치(부분 업데이트)
리소스를 수정할 때 불필요한 데이터가 전송되지 않도록 할 수도 있습니다. 변경하려는 특정 필드의 업데이트된 데이터만 전송하려면 HTTP PATCH
동사를 사용합니다. 이 문서에 설명된 패치 시맨틱스는 이전에 부분 업데이트를 위해 구현되었던 GData 구문과는 다르며 더 간단해졌습니다.
아래의 짧은 예에서는 일부 데이터만 업데이트할 경우 패치를 사용하면 전송해야 하는 데이터가 얼마나 최소화되는지를 보여 줍니다.
예
이 예시에서는 일반적인(가상의) 'Demo' API 리소스의 제목만 업데이트하기 위한 간단한 패치 요청을 보여 줍니다. 이 리소스에는 comment, characteristics 세트, status 외 여러 필드가 있지만 이 요청은 title
필드만 전송합니다. 수정되는 유일한 필드이기 때문입니다.
PATCH https://www.googleapis.com/demo/v1/324 Authorization: Bearer your_auth_token Content-Type: application/json { "title": "New title" }
응답:
200 OK
{ "title": "New title", "comment": "First comment.", "characteristics": { "length": "short", "accuracy": "high", "followers": ["Jo", "Will"], }, "status": "active", ... }
서버에서는 200 OK
상태 코드와 함께 업데이트된 리소스의 전체 표현을 반환합니다. title
필드만 패치 요청에 포함되었기 때문에 이 필드 값만 이전과 다릅니다.
참고: 부분 응답 fields
매개변수를 패치와 함께 사용하면 업데이트 요청의 효율을 훨씬 더 높일 수 있습니다. 패치 요청은 요청의 크기만을 줄입니다. 부분 응답은 응답의 크기를 줄입니다. 따라서 양방향으로 전송되는 데이터의 양을 줄이려면 패치 요청과 fields
매개변수를 함께 사용합니다.
패치 요청 구문
패치 요청의 본문에는 수정하려는 리소스 필드만 포함합니다. 부분 응답에서 필드가 속한 상위 항목이 반환되는 것과 마찬가지로, 요청에서 필드를 지정할 때도 해당 필드가 속한 모든 상위 객체를 포함해야 합니다. 수정된 데이터를 전송하면 해당 데이터가 상위 객체의 데이터에 병합됩니다.
- 추가: 기존에 없던 필드를 추가하려면 새 필드와 해당 값을 지정합니다.
- 수정: 기존 필드의 값을 변경하려면 필드를 지정하고 새로운 값으로 설정합니다.
- 삭제: 필드를 삭제하려면 필드를 지정하고
null
로 설정합니다. 예를 들면"comment": null
입니다. 또한 전체 객체(변경 가능한 경우)를null
로 설정하여 삭제할 수도 있습니다. Java API 클라이언트 라이브러리를 사용 중인 경우Data.NULL_STRING
을 대신 사용하세요. 자세한 내용은 JSON null을 참조하세요.
배열 참고사항: 배열이 포함된 패치 요청은 기존 배열을 사용자가 제공하는 배열로 바꿉니다. 배열의 항목을 부분적으로 수정하거나 추가하거나 삭제할 수는 없습니다.
읽기-수정-쓰기 주기로 패치 사용
먼저 수정하려는 데이터를 포함하는 부분 응답을 가져오는 것이 유용한 경우도 있습니다. ETag를 사용하는 리소스의 경우 If-Match
HTTP 헤더에 현재 ETag를 제공해야 올바르게 업데이트되므로 이 방법이 특히 중요합니다. 데이터를 구한 후, 변경하고자 하는 값을 수정할 수 있으며, 패치 요청과 함께 수정된 부분에 대한 표시를 반송할 수 있습니다. 다음은 데모 리소스가 ETag를 사용한다는 것으로 가정한 예시입니다.
GET https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics Authorization: Bearer your_auth_token
다음은 부분 응답입니다.
200 OK
{ "etag": "ETagString" "title": "New title" "comment": "First comment.", "characteristics": { "length": "short", "level": "5", "followers": ["Jo", "Will"], } }
다음 패치 요청은 위 응답을 기반으로 합니다. 아래와 같이 이 요청은 fields
매개변수를 사용하여 패치 응답에서 반환되는 데이터를 제한하기도 합니다.
PATCH https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics Authorization: Bearer your_auth_token Content-Type: application/json If-Match: "ETagString"
{ "etag": "ETagString" "title": "", /* Clear the value of the title by setting it to the empty string. */ "comment": null, /* Delete the comment by replacing its value with null. */ "characteristics": { "length": "short", "level": "10", /* Modify the level value. */ "followers": ["Jo", "Liz"], /* Replace the followers array to delete Will and add Liz. */ "accuracy": "high" /* Add a new characteristic. */ }, }
서버에서는 200 OK HTTP 상태 코드와 함께 업데이트된 리소스의 부분 표현을 반환합니다.
200 OK
{ "etag": "newETagString" "title": "", /* Title is cleared; deleted comment field is missing. */ "characteristics": { "length": "short", "level": "10", /* Value is updated.*/ "followers": ["Jo" "Liz"], /* New follower Liz is present; deleted Will is missing. */ "accuracy": "high" /* New characteristic is present. */ } }
패치 요청 직접 작성
일부 패치 요청의 경우 이전에 가져온 데이터를 기반으로 해야 합니다. 예를 들어 배열에 항목을 추가하면서 기존 배열 요소를 잃고 싶지 않은 경우 먼저 기존 데이터를 가져와야 합니다. 마찬가지로 API에서 ETag를 사용하는 경우 리소스를 업데이트하기 위해서는 요청과 함께 이전의 ETag 값을 전송해야 합니다.
참고: ETag를 사용 중인 경우 "If-Match: *"
HTTP 헤더를 사용하여 패치가 처리되도록 할 수 있습니다. 이렇게 하면 쓰기 전에 읽기를 수행하지 않아도 됩니다.
하지만 그 외의 경우에는 기존 데이터를 먼저 가져오지 않고 패치 요청을 직접 작성할 수 있습니다. 예를 들어 필드를 새로운 값으로 업데이트하거나 새 필드를 추가하는 패치 요청을 간편하게 설정할 수 있습니다. 예를 들면 다음과 같습니다.
PATCH https://www.googleapis.com/demo/v1/324?fields=comment,characteristics Authorization: Bearer your_auth_token Content-Type: application/json { "comment": "A new comment", "characteristics": { "volume": "loud", "accuracy": null } }
이 요청을 실행할 경우 comment 필드에 기존 값이 있으면 새로운 값이 기존 값을 덮어쓰고, 그렇지 않으면 comment 필드가 새로운 값으로 설정됩니다. 마찬가지로 볼륨(volume) 특성이 있으면 해당 값이 덮어써지고, 그렇지 않으면 새로 생성됩니다. 또한 accuracy 필드는 설정된 경우 제거됩니다.
패치에 대한 응답 처리
API는 올바른 패치 요청을 처리한 후 200 OK
HTTP 응답 코드와 함께 수정된 리소스의 전체 표현을 반환합니다. API에 ETag가 사용되는 경우에는 PUT
을 사용할 때와 마찬가지로 패치 요청이 성공적으로 처리되면 서버에서 ETag 값을 업데이트합니다.
fields
매개변수를 사용하여 반환되는 데이터의 양을 줄이지 않으면 패치 요청에서 전체 리소스 표현을 반환합니다.
패치 요청으로 인해 새로운 리소스 상태의 구문 또는 의미 체계가 올바르지 않게 되면 서버에서 400 Bad Request
또는 422 Unprocessable Entity
HTTP 상태 코드를 반환하며 리소스 상태는 변경되지 않은 채 유지됩니다. 예를 들어 필수 필드의 값을 삭제하려고 하면 서버에서 오류가 반환됩니다.
PATCH HTTP 동사가 지원되지 않는 경우 대체 표기법
방화벽에서 HTTP PATCH
요청을 허용하지 않으면 아래와 같이 HTTP POST
요청을 실행하고 재정의 헤더를 PATCH
로 설정합니다.
POST https://www.googleapis.com/... X-HTTP-Method-Override: PATCH ...
패치와 업데이트의 차이점
실제로 HTTP PUT
동사를 사용하는 업데이트 요청용으로 데이터를 전송할 때는 필수항목이거나 선택항목인 필드만 전송해야 합니다. 서버에서 설정된 필드의 값을 전송하면 이 값은 무시됩니다. 이는 부분 업데이트를 수행하는 또 다른 방법처럼 보일 수도 있지만 이 접근 방식에는 몇 가지 제한사항이 있습니다. HTTP PUT
동사를 사용하는 업데이트의 경우 필수 매개변수를 제공하지 않으면 요청이 실패하고 선택적 매개변수를 제공하지 않으면 이전에 설정한 데이터가 삭제됩니다.
이러한 이유로 패치를 사용하는 것이 훨씬 안전합니다. 변경하려는 필드의 데이터만 제공하면 되며, 생략한 필드는 삭제되지 않습니다. 반복 요소 또는 배열의 경우에만 이 규칙에 예외가 적용됩니다. 즉, 모두 생략하면 이전 상태가 그대로 유지되고, 이 중 하나라도 제공하면 전체 세트가 제공한 세트로 대체됩니다.