요청 처리 방법

리전 ID

REGION_ID는 앱을 만들 때 선택한 리전을 기준으로 Google에서 할당하는 축약된 코드입니다. 일부 리전 ID는 일반적으로 사용되는 국가 및 주/도 코드와 비슷하게 표시될 수 있지만 코드는 국가 또는 주/도와 일치하지 않습니다. 기존 앱은 App Engine URL에 REGION_ID.r을 포함하는 것이 선택사항이며, 신규 앱은 모두 곧 필수가 될 예정입니다.

원활한 전환을 위해 리전 ID를 사용하도록 App Engine을 천천히 업데이트하고 있습니다. 아직 Google Cloud 프로젝트가 업데이트되지 않은 경우에는 앱의 리전 ID가 표시되지 않습니다. 기존 앱에서 ID는 선택사항이므로 기존 앱에서 리전 ID를 사용할 수 있게 되더라도 URL을 업데이트하거나 다른 변경을 수행할 필요가 없습니다.

리전 ID에 대해 자세히 알아보세요.

이 문서는 App Engine 애플리케이션이 요청을 수신하고 응답을 전송하는 방법을 설명합니다. 자세한 내용은 요청 헤더 및 응답 참조를 참조하세요.

애플리케이션이 서비스를 사용하는 경우 요청을 특정 서비스 또는 서비스의 특정 버전으로 지정할 수 있습니다. 서비스 주소 지정에 대한 자세한 내용은 요청 라우팅 방법을 참조하세요.

요청 처리

애플리케이션은 웹 서버를 시작하고 요청을 처리하는 작업을 담당합니다. 개발 언어용으로 제공되는 모든 웹 프레임워크를 사용할 수 있습니다.

App Engine에서 애플리케이션의 여러 인스턴스를 실행하며 각 인스턴스에는 요청 처리를 위한 자체 웹 서버가 있습니다. 요청이 임의의 인스턴스로 라우팅될 수 있으므로, 동일한 사용자가 보내는 연속 요청이 같은 인스턴스로 전송되지 않을 수 있습니다. 인스턴스 한 개가 여러 요청을 동시에 처리할 수 있습니다. 인스턴스 수는 트래픽의 변화에 따라 자동으로 조정될 수 있습니다. 또한 app.yaml 파일에서 max_concurrent_requests 요소를 설정하여 인스턴스 한 개가 처리할 수 있는 동시 요청 수를 변경할 수 있습니다.

서버는 요청 URL을 앱의 app.yaml 구성 파일에 있는 URL 패턴과 비교하여 실행할 PHP 핸들러 스크립트를 결정합니다. 그런 다음 요청 데이터가 채워진 스크립트를 실행합니다. 서버는 요청 데이터를 환경 변수와 표준 입력 스트림에 배치합니다. 스크립트는 요청에 적합한 작업을 수행한 후 응답을 준비하고 표준 출력 스트림에 배치합니다.

다음 예시는 모든 HTTP 요청에 'Hello World!' 메시지로 응답하는 PHP 스크립트입니다.

<?php

echo "hello world!";

다음 예시에서는 Slim 프레임워크를 사용하여 HTTP 요청에 응답합니다.

$app = new Slim\App();
$app->get('/', function ($request, $response) {
    // Use the Null Coalesce Operator in PHP7
    // http://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.coalesce
    $name = $request->getQueryParams()['name'] ?? 'World';
    return $response->getBody()->write("Hello, $name!");
});
$app->run();

할당량 및 한도

App Engine은 트래픽 증가에 따라 애플리케이션에 자동으로 리소스를 할당합니다. 그러나 여기에는 다음과 같은 제한사항이 적용됩니다.

  • App Engine은 애플리케이션이 요청에 응답하는 시간이 1초 미만인, 지연 시간이 짧은 애플리케이션을 위해 자동 확장 용량을 예약합니다. 요청이 많을 때 요청당 1초 이상으로 지연 시간이 길고 처리량이 많은 애플리케이션에는 실버, 골드, 플래티넘 지원이 필요합니다. 이러한 수준의 지원을 신청한 고객은 지원팀 담당자에게 처리량 한도를 상향 요청할 수 있습니다.

  • CPU 사용량이 많은 애플리케이션의 경우, 동일 서버의 다른 애플리케이션과 효율적으로 리소스를 공유하기 위해 지연 시간이 추가로 발생할 수 있습니다. 정적 파일에 대한 요청은 지연 시간 한도에서 제외됩니다.

애플리케이션에 수신되는 각 요청은 요청 한도에 반영됩니다. 요청에 대한 응답으로 전송되는 데이터는 발신 대역폭(청구 가능) 한도에 반영됩니다.

HTTP 및 HTTPS(보안) 요청은 모두 요청, 수신 대역폭(청구 가능), 발신 대역폭(청구 가능) 한도에 반영됩니다. Cloud Console의 할당량 세부정보 페이지도 정보 제공 목적으로 보안 요청, 보안 수신 대역폭, 보안 발신 대역폭을 별도의 값으로 보고합니다. HTTPS 요청만 이러한 값에 반영됩니다. 자세한 내용은 할당량 페이지를 참조하세요.

다음은 요청 핸들러 사용 시 적용되는 한도입니다.

한도 용량
요청 크기 32MB
응답 크기 32MB
요청 제한 시간 앱에서 사용하는 확장 유형에 따라 다름
최대 총 파일 수(앱 파일과 정적 파일) 총 10,000개
디렉터리당 1,000개
애플리케이션 파일 최대 크기 32MB
정적 파일 최대 크기 32MB
모든 애플리케이션과 정적 파일의 최대 총 크기 첫 1GB는 무료
첫 1GB 이후 1GB당 월 $0.026

응답 한도

동적 응답은 32MB로 제한됩니다. 스크립트 핸들러가 이 한도를 초과하는 응답을 생성하면 서버가 500 내부 서버 오류 상태 코드와 함께 빈 응답을 반환합니다. 이 제한은 Cloud Storage에서 데이터를 제공하는 응답에는 적용되지 않습니다.

요청 헤더

수신되는 HTTP 요청에는 클라이언트가 전송한 HTTP 헤더가 포함되어 있습니다. 보안을 위해 일부 헤더는 애플리케이션에 도달하기 전 중간 프록시에 의해 삭제 또는 수정됩니다.

자세한 내용은 요청 헤더 참조를 확인하세요.

요청 기한 지정

App Engine은 단기 요청, 일반적으로 수백 밀리초 정도 지속되는 요청을 사용하는 애플리케이션에 최적화되어 있습니다. 효율적인 앱은 대부분의 요청에 신속하게 응답합니다. 그렇지 않은 앱은 App Engine 인프라에 맞춰 제대로 확장되지 않습니다.

PHP 스크립트는 제한된 시간을 가지며 요청에 대한 응답을 생성 및 반환합니다. 기한에 도달하면 연결 상태 비트 필드의 TIMEOUT 비트가 설정됩니다. 그러면 스크립트가 장기간 실행되는 작업을 지우기 위해 짧은 두 번째 기한을 갖게 되고 사용자에게 응답을 반환합니다.

두 번째 기한까지 스크립트가 응답을 반환하지 않으면 핸들러가 종료되고 기본 오류 응답이 반환됩니다.

응답

App Engine은 $_REQUEST 배열이 채워져 있는 스크립트를 호출하고 이 스크립트의 모든 출력을 버퍼링하여 스크립트 실행이 완료되면 버퍼링된 출력을 최종 사용자에게 보냅니다.

생성하는 응답에 크기 한도가 적용되며 응답은 클라이언트에 반환되기 전에 수정될 수 있습니다.

자세한 내용은 요청 응답 참조를 확인하세요.

스트리밍 응답

App Engine은 요청이 처리되는 동안 증분 청크의 데이터가 클라이언트에 전송되는 스트리밍 응답을 지원하지 않습니다. 위 설명과 같이 코드의 모든 데이터가 수집되어 단일 HTTP 응답으로 전송됩니다.

응답 압축

코드에서 반환된 응답의 경우 다음 두 조건이 모두 충족되면 App Engine이 응답 데이터를 압축합니다.

  • 요청에 값으로 gzip을 포함하는 Accept-Encoding 헤더가 있습니다.
  • 응답에는 HTML, CSS, 자바스크립트와 같은 텍스트 기반 데이터가 포함됩니다.

App Engine 정적 파일 또는 디렉터리 핸들러에서 반환된 응답의 경우 다음 조건이 모두 충족되면 응답 데이터가 압축됩니다.

  • 요청에는 gzip을 값 중 하나로 사용하는 Accept-Encoding이 포함됩니다.
  • 클라이언트가 압축된 형식의 응답 데이터를 수신할 수 있습니다. Google 프런트엔드에서 압축된 응답 관련 문제가 있는 것으로 알려진 클라이언트 목록을 유지관리합니다. 이러한 클라이언트는 요청 헤더에 Accept-Encoding: gzip이 포함되어 있더라도 앱의 정적 핸들러에서 전송된 압축 데이터를 수신하지 않습니다.
  • 응답에는 HTML, CSS, 자바스크립트와 같은 텍스트 기반 데이터가 포함됩니다.

다음에 유의하세요.

  • 클라이언트는 Accept-EncodingUser-Agent 요청 헤더를 모두 gzip으로 설정하여 텍스트 기반 콘텐츠 유형을 강제로 압축할 수 있습니다.

  • 요청의 Accept-Encoding 헤더에 gzip이 지정되지 않으면 App Engine이 응답 데이터를 압축하지 않습니다.

  • Google 프런트엔드에서 App Engine 정적 파일 및 디렉터리 핸들러에서 수신한 응답을 캐시합니다. 어떤 유형의 응답 데이터가 먼저 캐시되는지, 응답에 어떤 Vary 헤더를 지정했는지, 요청에 어떤 헤더가 포함되는지 등의 다양한 요소에 따라 클라이언트에서 압축 데이터를 요청했지만 압축되지 않은 데이터를 수신할 수도 있고 그 반대일 수도 있습니다. 자세한 정보는 응답 캐싱을 참조하세요.

응답 캐싱

Google 프런트엔드와 잠재적으로 사용자 브라우저 및 기타 중간 캐싱 프록시 서버가 응답에 지정한 표준 캐싱 헤더 설명에 따라 앱의 응답을 캐시합니다. 프레임워크를 통해 코드에서 직접 지정하거나 App Engine 정적 파일 및 디렉터리 핸들러를 통해 이러한 응답 헤더를 지정할 수 있습니다.

Google 프런트엔드에서 캐시 키는 요청의 전체 URL입니다.

정적 콘텐츠 캐싱

업데이트된 정적 콘텐츠가 게시되는 즉시 클라이언트에서 이를 확인하려면 css/v1/styles.css와 같은 버전 디렉터리에서 정적 콘텐츠를 제공하는 것이 좋습니다. Google 프런트엔드는 캐시가 만료될 때까지 캐시를 검증하지 않고 업데이트된 콘텐츠를 확인합니다. 캐시가 만료된 후에도 요청 URL의 콘텐츠가 변경될 때까지 캐시가 업데이트되지 않습니다.

app.yaml에서 설정할 수 있는 다음 응답 헤더는 Google 프런트엔드에서 콘텐츠를 캐시하는 방식과 시기에 영향을 줍니다.

  • Google Fontend에서 콘텐츠를 캐시하려면 Cache-Controlpublic으로 설정해야 합니다. app.yaml에 이 헤더를 설정하지 않으면 App Engine이 정적 파일이나 디렉터리 핸들러에 의해 처리되는 모든 응답에 자동으로 헤더를 추가합니다. 자세한 내용은 추가 또는 대체되는 헤더를 참조하세요.

  • Vary: 요청에서 전송되는 헤더를 기반으로 URL에 대해 서로 다른 응답을 반환하도록 하려면 Vary 응답 헤더에 다음 값 중 하나 이상을 설정합니다. Accept, Accept-Encoding, Origin 또는 X-Origin

    카디널리티가 발생할 가능성이 높기 때문에 다른 Vary 값에서는 데이터가 캐시되지 않습니다.

    예:

    1. 다음 응답 헤더를 지정합니다.

      Vary: Accept-Encoding

    2. 앱에서 Accept-Encoding: gzip 헤더가 포함된 요청을 받습니다. App Engine은 압축된 응답을 반환하고 Google 프런트엔드는 응답 데이터의 gzip 버전을 캐시합니다. Accept-Encoding: gzip 헤더가 포함된 이 URL의 모든 후속 요청은 캐시가 만료된 후 콘텐츠가 변경되어 캐시가 무효화되기 전까지는 캐시에서 gzip 처리된 데이터를 수신합니다.

    3. 앱에서 Accept-Encoding 헤더를 포함하지 않는 요청을 수신합니다. App Engine은 압축되지 않은 응답을 반환하고 Google 프런트엔드는 압축되지 않은 버전의 응답 데이터를 캐시합니다. Accept-Encoding 헤더가 포함되지 않은 이 URL의 모든 후속 요청은 캐시가 무효화될 때까지 캐시에서 압축된 데이터를 수신합니다.

    Vary 응답 헤더를 지정하지 않으면 Google 프런트엔드는 URL에 대한 단일 캐시 항목을 만들고 요청의 헤더와 관계없이 모든 요청에 이 항목을 사용합니다. 예:

    1. Vary: Accept-Encoding 응답 헤더를 지정하지 않습니다.
    2. 요청에 Accept-Encoding: gzip 헤더가 포함되고 응답 데이터의 gzip 버전이 캐시됩니다.
    3. 두 번째 요청에는 Accept-Encoding: gzip 헤더가 포함되어 있지 않습니다. 그러나 캐시에는 응답 데이터의 gzip 버전이 포함되어 있으므로, 클라이언트가 압축되지 않은 데이터를 요청했더라도 응답이 gzip으로 압축됩니다.

요청에 포함된 헤더는 캐싱에도 영향을 미칩니다.

  • 요청에 Authorization 헤더가 포함된 경우 Google 프런트엔드에서 콘텐츠를 캐시하지 않습니다.

캐시 만료

기본적으로 App Engine 정적 파일 및 디렉터리 핸들러가 응답에 추가하는 캐싱 헤더는 클라이언트 및 Google 프런트엔드와 같은 웹 프록시에 10분 후에 캐시를 만료하도록 지시합니다.

지정된 만료 시간으로 파일이 전송된 후에는 사용자가 자신의 브라우저 캐시를 삭제하더라도 웹 프록시 캐시에서 파일을 지울 수 있는 일반적인 방법은 없습니다. 앱의 새 버전을 다시 배포해도 캐시는 재설정되지 않습니다. 따라서 정적 파일을 수정할 계획이 있다면 만료 시간이 짧아야 합니다(1시간 미만). 대부분의 경우 만료 시간 기본값인 10분이 적합합니다.

app.yaml에서 default_expiration 요소를 지정하면 모든 정적 파일 및 디렉터리 핸들러의 기본 만료 시간을 변경할 수 있습니다. 개별 핸들러의 특정 만료 시간을 설정하려면 app.yaml 파일에서 핸들러 요소 안의 expiration 요소를 지정합니다.

만료 요소 시간에 지정된 값은 Cache-ControlExpires HTTP 응답 헤더를 설정하는 데 사용됩니다.

HTTPS 연결 강제 적용

보안상의 이유로 모든 애플리케이션은 클라이언트가 https를 통해 연결하도록 권장해야 합니다. 브라우저가 특정 페이지 또는 전체 도메인에 대해 http보다 https를 우선 사용하도록 하려면 응답에 Strict-Transport-Security 헤더를 설정합니다. 예:

Strict-Transport-Security: max-age=31536000; includeSubDomains
앱에서 제공하는 모든 정적 콘텐츠에 이 헤더를 설정하려면 앱의 정적 파일 및 디렉터리 핸들러에 헤더를 추가합니다.

스크립트에서 생성된 응답의 헤더 설정에 대한 자세한 내용은 앱에서 사용하는 웹 프레임워크의 안내를 참조하세요. 웹 프레임워크를 사용하지 않는 경우 PHP header 함수를 사용합니다.