Lambda@Edge 이벤트 구조 - Amazon CloudFront

Lambda@Edge 이벤트 구조

다음 주제에서는 트리거될 때 CloudFront가 Lambda@Edge 함수에 전달하는 요청 및 응답 이벤트 객체에 대해 설명합니다.

동적 오리진 선택

캐시 동작의 경로 패턴을 사용하여 images/*.jpg와 같이 요청된 객체의 경로와 이름을 기반으로 오리진에 요청을 라우팅할 수 있습니다. 또한 Lambda@Edge를 사용하여 요청 헤더의 값과 같은 기타 특성을 기반으로 오리진에 요청을 라우팅할 수 있습니다.

여러 경우에 이러한 동적 오리진 선택이 유용할 수 있습니다. 예를 들어, 각기 다른 지리 영역에 있는 오리진에 걸쳐 요청을 배포하여 전역 로드 밸런싱에 도움이 될 수 있습니다. 또는 봇 처리, SEO 최적화, 인증 등과 같은 특정 기능을 서비스하는 각기 다른 오리진에 요청을 선택적으로 라우팅할 수 있습니다. 이 기능을 사용하는 방법을 보여주는 코드 예제는 콘텐츠 기반 동적 오리진 선택 - 예제 단원을 참조하십시오.

CloudFront 오리진 요청 이벤트에서 이벤트 구조의 오리진 origin 객체에는 요청이 경로 패턴을 기반으로 라우팅될 오리진에 대한 정보가 들어 있습니다. origin 객체의 값을 업데이트하여 요청을 다른 오리진으로 라우팅할 수 있습니다. origin 객체를 업데이트할 때 배포에서 오리진을 정의할 필요가 없습니다. 또한 Amazon S3 오리진 객체를 사용자 지정 오리진 객체로 바꿀 수 있으며, 그 반대의 경우도 마찬가지입니다. 요청당 하나의 오리진만 지정할 수 있습니다. 즉, 사용자 지정 오리진 또는 Amazon S3 오리진 중 하나를 지정할 수 있지만 둘 모두 지정할 수는 없습니다.

이벤트 요청

다음 주제에서는 CloudFront가 최종 사용자 및 오리진 요청 이벤트에 대한 Lambda 함수에 전달하는 객체의 구조를 보여줍니다. 이 예제에서는 본문이 없는 GET 요청을 보여줍니다. 다음 예제는 최종 사용자 및 오리진 요청 이벤트에서 가능한 모든 필드의 목록입니다.

최종 사용자 요청 예제

다음 예제에서는 최종 사용자 요청 이벤트 객체를 보여줍니다.

{ "Records": [ { "cf": { "config": { "distributionDomainName": "d111111abcdef8.cloudfront.net", "distributionId": "EDFDVBD6EXAMPLE", "eventType": "viewer-request", "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ==" }, "request": { "clientIp": "203.0.113.178", "headers": { "host": [ { "key": "Host", "value": "d111111abcdef8.cloudfront.net" } ], "user-agent": [ { "key": "User-Agent", "value": "curl/7.66.0" } ], "accept": [ { "key": "accept", "value": "*/*" } ] }, "method": "GET", "querystring": "", "uri": "/" } } } ] }

오리진 요청 예제

다음 예제에서는 오리진 요청 이벤트 객체를 보여줍니다.

{ "Records": [ { "cf": { "config": { "distributionDomainName": "d111111abcdef8.cloudfront.net", "distributionId": "EDFDVBD6EXAMPLE", "eventType": "origin-request", "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ==" }, "request": { "clientIp": "203.0.113.178", "headers": { "x-forwarded-for": [ { "key": "X-Forwarded-For", "value": "203.0.113.178" } ], "user-agent": [ { "key": "User-Agent", "value": "Amazon CloudFront" } ], "via": [ { "key": "Via", "value": "2.0 2afae0d44e2540f472c0635ab62c232b.cloudfront.net (CloudFront)" } ], "host": [ { "key": "Host", "value": "example.org" } ], "cache-control": [ { "key": "Cache-Control", "value": "no-cache, cf-no-cache" } ] }, "method": "GET", "origin": { "custom": { "customHeaders": {}, "domainName": "example.org", "keepaliveTimeout": 5, "path": "", "port": 443, "protocol": "https", "readTimeout": 30, "sslProtocols": [ "TLSv1", "TLSv1.1", "TLSv1.2" ] } }, "querystring": "", "uri": "/" } } } ] }

요청 이벤트 필드

요청 이벤트 객체 데이터는 두 개의 하위 객체(config(Records.cf.config) 및 request(Records.cf.request))에 포함되어 있습니다. 다음 목록에서는 각 하위 객체의 필드에 대해 설명합니다.

구성 객체의 필드

다음 표에서는 config 객체(Records.cf.config)의 필드에 대해 설명합니다.

distributionDomainName(읽기 전용)

요청과 연결된 배포의 도메인 이름입니다.

distributionID(읽기 전용)

요청과 관련이 있는 배포의 ID입니다.

eventType(읽기 전용)

요청(viewer-request 또는 origin-request)과 관련된 트리거의 유형입니다.

requestId(읽기 전용)

최종 사용자 요청/CloudFront 요청을 고유하게 식별하는 암호화된 문자열입니다. 또한 requestId 값은 CloudFront 액세스 로그에 x-edge-request-id로 표시됩니다. 자세한 내용은 액세스 로그 구성 및 사용웹 배포 로그 파일 형식 단원을 참조하십시오.

요청 객체의 필드

다음 표에서는 request 객체(Records.cf.request)의 필드에 대해 설명합니다.

clientIp(읽기 전용)

요청을 생성한 최종 사용자의 IP 주소입니다. 최종 사용자가 HTTP 프록시 또는 로드 밸런서를 사용하여 요청을 전송한 경우 이 값은 프록시 또는 로드 밸런서의 IP 주소입니다.

headers(읽기/쓰기)

요청의 헤더입니다. 다음을 참조하십시오.

  • headers 객체 내 키는 표준 HTTP 헤더 이름의 소문자 버전입니다. 소문자 키를 사용하여 대/소문자를 구분하지 않고 헤더 값에 액세스할 수 있습니다.

  • 각 헤더 객체(예: headers["accept"] 또는 headers["host"])는 키–값 페어의 어레이입니다. 해당 헤더에 대해 어레이에는 요청의 각 값에 대한 하나의 키–값 페어를 포함합니다.

  • key에는 HTTP 요청에 표시되는 헤더의 대/소문자 구분 이름을 포함합니다(예: Host, User-Agent, X-Forwarded-For 등).

  • value에는 HTTP 요청에 표시되는 헤더 값을 포함합니다.

  • Lambda 함수가 요청 헤더를 추가하거나 수정하고 사용자가 헤더 key 필드를 포함시키지 않으면, Lambda@Edge는 사용자가 입력한 헤더 이름을 사용하여 헤더 key를 자동으로 삽입합니다. 헤더 이름의 형식을 어떻게 지정했든 상관없이, 자동으로 삽입된 헤더 키는 각 부분의 첫 문자가 대문자로 지정되고 각 부분이 하이픈(-)으로 구분됩니다.

    예를 들어 헤더를 다음과 같이 헤더 key 없이 추가할 수 있습니다.

    "user-agent": [ { "value": "ExampleCustomUserAgent/1.X.0" } ]

    이 예제에서는 Lambda@Edge가 자동으로 "key": "User-Agent"를 삽입합니다.

헤더 사용 시 제한 사항에 대한 자세한 내용은 헤더 단원을 참조하십시오.

method(읽기 전용)

요청의 HTTP 메서드.

querystring(읽기/쓰기)

요청의 쿼리 문자열입니다(있는 경우). 요청에 쿼리 문자열이 포함되지 않더라도 이벤트 객체에는 여전히 빈 값과 함께 querystring이 포함됩니다. 쿼리 문자열에 대한 자세한 내용은 쿼리 문자열 파라미터 기반의 콘텐츠 캐싱 단원을 참조하십시오.

uri(읽기/쓰기)

요청된 객체의 상대 경로입니다. Lambda 함수가 uri 값을 수정하는 경우 다음 사항에 유의하십시오.

  • uri 값은 슬래시(/) 로 시작해야 합니다.

  • 함수가 uri 값을 변경하는 경우 이로 인해 최종 사용자가 요청 중인 객체가 변경됩니다.

  • 함수가 uri 값을 변경하는 경우 이로 인해 요청 또는 요청이 전송되는 오리진에 대한 캐시 동작이 변경되지 않습니다.

body(읽기/쓰기)

HTTP 요청의 본문입니다. body 구조에는 다음과 같은 필드가 포함될 수 있습니다.

inputTruncated(읽기 전용)

Lambda@Edge가 본문을 잘랐는지 여부를 나타내는 부울 플래그. 자세한 내용은 본문 포함 옵션이 적용된 요청 본문에 대한 크기 할당량 단원을 참조하십시오.

action(읽기/쓰기)

본문을 사용해 수행하고자 한 작업. action의 옵션은 다음과 같습니다.

  • read-only: 이 값이 기본값입니다. Lambda 함수에서 응답이 반환되었는데 action이 read-only이면, Lambda@Edge는 encoding 또는 data에 대한 모든 변경 사항을 무시합니다.

  • replace: 오리진으로 전송된 본문을 바꾸려는 경우 이 옵션을 지정합니다.

encoding(읽기/쓰기)

본문에 대한 인코딩. Lambda@Edge가 Lambda 함수에 본문을 노출시키는 경우 먼저 본문을 base64-encoding 으로 변환합니다. 본문을 바꾸기 위해 actionreplace를 선택한 경우 base64(기본값) 또는 text 인코딩을 사용하도록 선택할 수 있습니다. encodingbase64로 지정하지만 본문이 유효한 base64 가 아닌 경우 CloudFront에서는 오류를 반환합니다.

data(읽기/쓰기)

요청 본문의 내용

origin(읽기/쓰기) (오리진 이벤트만 해당)

요청을 전송할 오리진입니다. origin 구조에는 하나의 오리진만 포함되어야 합니다. 즉, 오리진은 사용자 지정 오리진 또는 Amazon S3 오리진일 수 있습니다. 오리진 구조에는 다음과 같은 필드가 포함될 수 있습니다.

customHeaders(읽기/쓰기) (사용자 지정 오리진 및 Amazon S3 오리진)

각 사용자 지정 헤더에 대한 헤더 이름 및 값 페어를 지정하여 요청을 포함한 사용자 지정 헤더를 포함할 수 있습니다. 블랙리스트에 등록된 헤더는 추가할 수 없으며 동일한 이름의 헤더가 Records.cf.request.headers에 존재할 수 없습니다. 요청 헤더에 대한 노트는 사용자 지정 헤더에도 적용됩니다. 자세한 내용은 CloudFront가 오리진 요청에 추가할 수 없는 사용자 지정 헤더블랙리스트 헤더 단원을 참조하십시오.

domainName(읽기/쓰기) (사용자 지정 오리진 및 Amazon S3 오리진)

오리진의 도메인 이름입니다. 도메인 이름은 비워둘 수 없습니다.

  • 사용자 지정 오리진의 경우 – DNS 도메인 이름을 지정합니다(예: www.example.com). 도메인 이름에는 콜론(:)이 포함될 수 없으며 IP 주소가 될 수 없습니다. 도메인 이름은 최대 253자일 수 있습니다.

  • Amazon S3 오리진의 경우 – Amazon S3 버킷의 DNS 도메인 이름을 지정합니다(예: awsexamplebucket.s3.eu-west-1.amazonaws.com). 이름은 최대 128자여야 하며, 모두 소문자여야 합니다.

path(읽기/쓰기) (사용자 지정 오리진 및 Amazon S3 오리진)

요청이 콘텐츠를 찾아야 하는 오리진의 디렉터리 경로입니다. 경로는 슬래시(/)로 시작해야 하지만 슬래시 하나로 끝나지 않아야 합니다(예: example-path/와 같이 끝나면 안 됨). 사용자 지정 오리진의 경우만, 경로는 URL로 인코딩되어야 하고 최대 길이는 255자여야 합니다.

keepaliveTimeout(읽기/쓰기) (사용자 지정 오리진만 해당)

CloudFront가 응답의 마지막 패킷을 수신한 후 오리진 연결을 유지하기 위해 시도해야 하는 시간(초)입니다. 값은 1~60(경계값 포함) 사이의 숫자여야 합니다.

port(읽기/쓰기) (사용자 지정 오리진만 해당)

CloudFront가 사용자 지정 오리진에서 연결해야 하는 포트입니다. 포트는 80, 443 또는 1024~65535(경계값 포함) 사이의 숫자여야 합니다.

protocol(읽기/쓰기) (사용자 지정 오리진만 해당)

오리진에 연결할 때 CloudFront가 사용해야 하는 연결 프로토콜입니다. http 또는 https 값을 가질 수 있습니다.

readTimeout(읽기/쓰기) (사용자 지정 오리진만 해당)

요청을 오리진으로 전송한 후 CloudFront가 응답을 대기해야 하는 시간(초)입니다. 또한 다음 패킷을 수신하기 전에 응답 패킷을 수신한 후 CloudFront가 대기해야 하는 시간도 지정합니다. 값은 4~60(경계값 포함) 사이의 숫자여야 합니다.

sslProtocols(읽기/쓰기) (사용자 지정 오리진만 해당)

오리진과의 HTTPS 연결을 설정할 때 CloudFront가 사용할 수 있는 최소 SSL/TLS 프로토콜입니다. 값은 TLSv1.2, TLSv1.1, TLSv1 또는 SSLv3 중 하나일 수 있습니다.

authMethod(읽기/쓰기) (Amazon S3 오리진만 해당)

OAI(원본 액세스 ID)를 사용하는 경우 이 필드를 origin-access-identity로 설정하거나 OAI를 사용하지 않는 경우 none으로 설정합니다. authMethodorigin-access-identity로 설정하면 다음과 같은 몇 가지 요구 사항이 있습니다.

  • region을 지정해야 합니다(다음 필드 참조).

  • 하나의 Amazon S3 오리진에서 다른 오리진으로 요청을 변경할 때 동일한 OAI를 사용해야 합니다.

  • 사용자 지정 오리진에서 Amazon S3 오리진으로 요청을 변경할 때 OAI를 사용할 수 없습니다.

region(읽기/쓰기) (Amazon S3 오리진만 해당)

Amazon S3 버킷의 AWS 리전입니다. 이 작업은 authMethodorigin-access-identity로 설정한 경우에만 필요합니다.

응답 이벤트

다음 주제에서는 CloudFront가 최종 사용자 및 오리진 응답 이벤트에 대한 Lambda 함수에 전달하는 객체의 구조를 보여줍니다. 다음 예제는 최종 사용자 및 오리진 응답 이벤트에서 가능한 모든 필드의 목록입니다.

오리진 응답 예제

다음 예제에서는 오리진 응답 이벤트 객체를 보여줍니다.

{ "Records": [ { "cf": { "config": { "distributionDomainName": "d111111abcdef8.cloudfront.net", "distributionId": "EDFDVBD6EXAMPLE", "eventType": "origin-response", "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ==" }, "request": { "clientIp": "203.0.113.178", "headers": { "x-forwarded-for": [ { "key": "X-Forwarded-For", "value": "203.0.113.178" } ], "user-agent": [ { "key": "User-Agent", "value": "Amazon CloudFront" } ], "via": [ { "key": "Via", "value": "2.0 8f22423015641505b8c857a37450d6c0.cloudfront.net (CloudFront)" } ], "host": [ { "key": "Host", "value": "example.org" } ], "cache-control": [ { "key": "Cache-Control", "value": "no-cache, cf-no-cache" } ] }, "method": "GET", "origin": { "custom": { "customHeaders": {}, "domainName": "example.org", "keepaliveTimeout": 5, "path": "", "port": 443, "protocol": "https", "readTimeout": 30, "sslProtocols": [ "TLSv1", "TLSv1.1", "TLSv1.2" ] } }, "querystring": "", "uri": "/" }, "response": { "headers": { "access-control-allow-credentials": [ { "key": "Access-Control-Allow-Credentials", "value": "true" } ], "access-control-allow-origin": [ { "key": "Access-Control-Allow-Origin", "value": "*" } ], "date": [ { "key": "Date", "value": "Mon, 13 Jan 2020 20:12:38 GMT" } ], "referrer-policy": [ { "key": "Referrer-Policy", "value": "no-referrer-when-downgrade" } ], "server": [ { "key": "Server", "value": "ExampleCustomOriginServer" } ], "x-content-type-options": [ { "key": "X-Content-Type-Options", "value": "nosniff" } ], "x-frame-options": [ { "key": "X-Frame-Options", "value": "DENY" } ], "x-xss-protection": [ { "key": "X-XSS-Protection", "value": "1; mode=block" } ], "content-type": [ { "key": "Content-Type", "value": "text/html; charset=utf-8" } ], "content-length": [ { "key": "Content-Length", "value": "9593" } ] }, "status": "200", "statusDescription": "OK" } } } ] }

최종 사용자 응답 예제

다음 예제에서는 최종 사용자 응답 이벤트 객체를 보여줍니다.

{ "Records": [ { "cf": { "config": { "distributionDomainName": "d111111abcdef8.cloudfront.net", "distributionId": "EDFDVBD6EXAMPLE", "eventType": "viewer-response", "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ==" }, "request": { "clientIp": "203.0.113.178", "headers": { "host": [ { "key": "Host", "value": "d111111abcdef8.cloudfront.net" } ], "user-agent": [ { "key": "User-Agent", "value": "curl/7.66.0" } ], "accept": [ { "key": "accept", "value": "*/*" } ] }, "method": "GET", "querystring": "", "uri": "/" }, "response": { "headers": { "access-control-allow-credentials": [ { "key": "Access-Control-Allow-Credentials", "value": "true" } ], "access-control-allow-origin": [ { "key": "Access-Control-Allow-Origin", "value": "*" } ], "date": [ { "key": "Date", "value": "Mon, 13 Jan 2020 20:14:56 GMT" } ], "referrer-policy": [ { "key": "Referrer-Policy", "value": "no-referrer-when-downgrade" } ], "server": [ { "key": "Server", "value": "ExampleCustomOriginServer" } ], "x-content-type-options": [ { "key": "X-Content-Type-Options", "value": "nosniff" } ], "x-frame-options": [ { "key": "X-Frame-Options", "value": "DENY" } ], "x-xss-protection": [ { "key": "X-XSS-Protection", "value": "1; mode=block" } ], "age": [ { "key": "Age", "value": "2402" } ], "content-type": [ { "key": "Content-Type", "value": "text/html; charset=utf-8" } ], "content-length": [ { "key": "Content-Length", "value": "9593" } ] }, "status": "200", "statusDescription": "OK" } } } ] }

응답 이벤트 필드

응답 이벤트 객체 데이터는 세 개의 하위 객체(config(Records.cf.config), request(Records.cf.request) 및 response(Records.cf.response))에 포함되어 있습니다. 요청 객체의 필드에 대한 자세한 내용은 요청 객체의 필드 단원을 참조하십시오. 다음 목록에서는 configresponse 하위 객체의 필드에 대해 설명합니다.

구성 객체의 필드

다음 표에서는 config 객체(Records.cf.config)의 필드에 대해 설명합니다.

distributionDomainName(읽기 전용)

응답과 연결된 배포의 도메인 이름입니다.

distributionID(읽기 전용)

응답과 관련이 있는 배포의 ID입니다.

eventType(읽기 전용)

응답과 관련된 트리거의 유형입니다(origin-response 또는 viewer-response).

requestId(읽기 전용)

이 응답이 연결된 최종 사용자 요청/CloudFront 요청을 고유하게 식별하는 암호화된 문자열입니다. 또한 requestId 값은 CloudFront 액세스 로그에 x-edge-request-id로 표시됩니다. 자세한 내용은 액세스 로그 구성 및 사용웹 배포 로그 파일 형식 단원을 참조하십시오.

응답 객체의 필드

다음 표에서는 response 객체(Records.cf.response)의 필드에 대해 설명합니다. Lambda@Edge 함수를 사용하여 HTTP 응답을 생성하는 방법에 대한 자세한 내용은 요청 트리거에서 HTTP 응답 생성 단원을 참조하십시오.

headers(읽기/쓰기)

응답의 헤더입니다. 다음을 참조하십시오.

  • headers 객체 내 키는 표준 HTTP 헤더 이름의 소문자 버전입니다. 소문자 키를 사용하여 대/소문자를 구분하지 않고 헤더 값에 액세스할 수 있습니다.

  • 각 헤더 객체(예: headers["content-type"] 또는 headers["content-length"])는 키–값 페어의 어레이입니다. 해당 헤더에 대해 어레이에는 응답의 각 값에 대한 하나의 키–값 페어를 포함합니다.

  • key에는 HTTP 응답에 표시되는 헤더의 대/소문자 구분 이름을 포함합니다(예: Content-Type, Content-Length 등).

  • value에는 HTTP 응답에 표시되는 헤더 값을 포함합니다.

  • Lambda 함수가 응답 헤더를 추가하거나 수정하고 사용자가 헤더 key 필드를 포함시키지 않으면, Lambda@Edge는 사용자가 입력한 헤더 이름을 사용하여 헤더 key를 자동으로 삽입합니다. 헤더 이름의 형식을 어떻게 지정했든 상관없이, 자동으로 삽입된 헤더 키는 각 부분의 첫 문자가 대문자로 지정되고 각 부분이 하이픈(-)으로 구분됩니다.

    예를 들어 헤더를 다음과 같이 헤더 key 없이 추가할 수 있습니다.

    "content-type": [ { "value": "text/html;charset=UTF-8" } ]

    이 예제에서는 Lambda@Edge가 자동으로 "key": "Content-Type"을 삽입합니다.

헤더 사용 시 제한 사항에 대한 자세한 내용은 헤더 단원을 참조하십시오.

status

응답의 HTTP 상태 코드입니다.

statusDescription

응답의 HTTP 상태 설명입니다.