

# 함수 코드 작성
<a name="writing-function-code"></a>

CloudFront Functions를 사용하여 지연 시간에 민감한 대규모 CDN 사용자 지정을 위해 JavaScript로 경량 함수를 작성할 수 있습니다. 함수 코드는 CloudFront를 통해 흐르는 요청 및 응답을 조작하고, 기본 인증 및 권한 부여를 수행하고, 엣지에서 HTTP 응답을 생성하는 등의 작업을 수행할 수 있습니다.

CloudFront Functions의 함수 코드를 작성하는 데 도움을 받으려면 다음 주제를 참조하세요. 코드 예제는 [CloudFront의 CloudFront Functions 예제](service_code_examples_cloudfront_functions_examples.md) 및 GitHub의 [amazon-cloudfront-functions 리포지토리](https://github.com/aws-samples/amazon-cloudfront-functions)를 참조하시기 바랍니다.

**Topics**
+ [함수 용도 결정](function-code-choose-purpose.md)
+ [이벤트 구조](functions-event-structure.md)
+ [JavaScript 런타임 기능](functions-javascript-runtime-features.md)
+ [키 값 저장소를 위한 도우미 메서드](functions-custom-methods.md)
+ [오리진 수정용 헬퍼 메서드](helper-functions-origin-modification.md)
+ [CloudFront SaaS Manager 속성에 대한 헬퍼 메서드](saas-specific-logic-function-code.md)
+ [async 및 await 사용](async-await-syntax.md)
+ [CloudFront Functions에 대한 CWT 지원](cwt-support-cloudfront-functions.md)
+ [일반 헬퍼 메서드](general-helper-methods.md)

# 함수 용도 결정
<a name="function-code-choose-purpose"></a>

함수 코드를 작성하기 전에 함수의 용도를 결정합니다. CloudFront 함수의 대부분의 함수는 다음 용도 중 하나를 가지고 있습니다.

**Topics**
+ [뷰어 요청 이벤트 유형의 HTTP 요청 수정](#function-code-modify-request)
+ [뷰어 요청 이벤트 유형에 HTTP 응답 생성](#function-code-generate-response)
+ [뷰어 응답 이벤트 유형의 HTTP 응답 수정](#function-code-modify-response)
+ [연결 요청 이벤트 유형에서 mTLS 연결 검증](#function-code-connection-request)
+ [관련 정보](#related-information-cloudfront-functions-purpose)

함수의 용도에 관계없이 `handler`은(는) 모든 함수의 진입점입니다. CloudFront에 의해 함수에 전달되는 `event`(이)라고 하는 단일 인수가 필요합니다. `event`은(는) HTTP 요청(그리고 함수가 HTTP 응답을 수정하는 경우 응답)의 표현을 포함하는 JSON 객체입니다.

## 뷰어 요청 이벤트 유형의 HTTP 요청 수정
<a name="function-code-modify-request"></a>

함수는 CloudFront가 최종 사용자(클라이언트)로부터 수신하는 HTTP 요청을 수정하고 수정된 요청을 CloudFront로 반환하여 처리를 계속할 수 있습니다. 예를 들어 함수 코드가 [캐시 키](understanding-the-cache-key.md)를 정규화하거나 요청 헤더를 수정할 수 있습니다.

HTTP 요청을 수정하는 함수를 만들고 게시한 후 *뷰어 요청* 이벤트 유형 연결을 추가해야 합니다. 자세한 내용은 [함수 생성](functions-tutorial.md#functions-tutorial-create) 섹션을 참조하세요. 즉, 요청된 객체가 CloudFront 캐시에 있는지 여부를 확인하기 위해 점검하기 전에 CloudFront가 뷰어의 요청을 수신할 때마다 함수가 실행됩니다.

**Example 예제**  
다음 유사 코드는 HTTP 요청을 수정하는 함수의 구조를 보여줍니다.  

```
function handler(event) {
    var request = event.request;

    // Modify the request object here.

    return request;
}
```
이 함수는 수정된 `request` 객체를 CloudFront로 반환합니다. CloudFront는 CloudFront 캐시에서 캐시 적중률을 확인하고 필요한 경우 오리진에 요청을 전송하여 반환된 요청을 계속 처리합니다.

## 뷰어 요청 이벤트 유형에 HTTP 응답 생성
<a name="function-code-generate-response"></a>

함수는 CloudFront에서 캐시된 응답이나 추가 처리를 확인하지 않고 엣지에서 HTTP 응답을 생성하여 최종 사용자(클라이언트)에게 직접 반환할 수 있습니다. 예를 들어 함수 코드는 요청을 새 URL로 리디렉션하거나 권한 부여를 확인하고 권한 없는 요청에 `401` 또는 `403` 응답을 반환할 수 있습니다.

HTTP 응답을 생성하는 함수를 생성할 때는 *최종 사용자 요청* 이벤트 유형을 선택해야 합니다. 즉, CloudFront가 추가 요청을 처리하기 전에 CloudFront가 최종 사용자의 요청을 수신할 때마다 함수가 실행됩니다.

**Example 예제**  
다음 유사 코드는 HTTP 응답을 생성하는 함수의 구조를 보여줍니다.  

```
function handler(event) {
    var request = event.request;

    var response = ...; // Create the response object here,
                        // using the request properties if needed.

    return response;
}
```
이 함수는 CloudFront에 `response` 객체를 반환하며, CloudFront는 CloudFront 캐시를 확인하거나 오리진에 요청을 보내지 않고 즉시 최종 사용자에게 반환합니다.

## 뷰어 응답 이벤트 유형의 HTTP 응답 수정
<a name="function-code-modify-response"></a>

CloudFront가 HTTP 응답을 최종 사용자(클라이언트)에게 전송하기 전에 함수는 HTTP 응답을 수정할 수 있습니다. 응답이 CloudFront 캐시에서 왔는지 오리진에서 왔는지는 관계없습니다. 예를 들어 함수 코드에서 응답 헤더, 상태 코드 및 본문 콘텐츠를 추가하거나 수정할 수 있습니다.

HTTP 응답을 수정하는 함수를 생성할 때는 *최종 사용자 응답* 이벤트 유형을 선택해야 합니다. 즉, 응답이 CloudFront 캐시에서 왔는지 오리진에서 왔는지 관계없이 CloudFront가 최종 사용자에게 응답을 반환하기 전에 함수가 실행됩니다.

**Example 예제**  
다음 유사 코드는 HTTP 응답을 수정하는 함수의 구조를 보여줍니다.  

```
function handler(event) {
    var request = event.request;
    var response = event.response;

    // Modify the response object here,
    // using the request properties if needed.

    return response;
}
```
이 함수는 수정된 `response` 객체를 CloudFront로 반환하며 CloudFront는 즉시 최종 사용자에게 반환합니다.

## 연결 요청 이벤트 유형에서 mTLS 연결 검증
<a name="function-code-connection-request"></a>

연결 함수는 사용자 지정 검증 및 인증 로직을 제공하기 위해 TLS 연결 중에 실행되는 CloudFront Functions의 한 유형입니다. 연결 함수는 현재 상호 TLS(mTLS) 연결에 사용할 수 있으며, 여기서 클라이언트 인증서를 검증하고 표준 인증서 검증을 넘어 사용자 지정 인증 로직을 구현할 수 있습니다. 연결 함수는 TLS 핸드셰이크 프로세스 중에 실행되며 인증서 속성, 클라이언트 IP 주소 또는 기타 기준에 따라 연결을 허용하거나 거부할 수 있습니다.

연결 함수를 생성하고 게시한 후에는 mTLS 지원 배포에 *연결 요청* 이벤트 유형에 대한 연결을 추가해야 합니다. 이렇게 하면 클라이언트가 CloudFront와 mTLS 연결을 설정하려고 할 때마다 함수가 실행됩니다.

**Example**  
다음 의사 코드는 연결 함수의 구조를 보여줍니다.  

```
function connectionHandler(connection) {
    // Validate certificate and connection properties here.
    
    if (/* validation passes */) {
        connection.allow();
    } else {
        connection.deny();
    }
}
```
함수는 헬퍼 메서드를 사용하여 연결을 허용할지 거부할지를 결정합니다. 뷰어 요청 및 뷰어 응답 함수와 달리 연결 함수는 HTTP 요청 또는 응답을 수정할 수 없습니다.

## 관련 정보
<a name="related-information-cloudfront-functions-purpose"></a>

CloudFront Functions 작업에 대한 자세한 내용은 다음 주제를 참조하세요.
+ [이벤트 구조](functions-event-structure.md)
+ [JavaScript 런타임 기능](functions-javascript-runtime-features.md)
+ [CloudFront Functions 예제 ](service_code_examples_cloudfront_functions_examples.md)
+ [엣지 함수에 대한 제한 사항](edge-functions-restrictions.md)

# CloudFront 함수 이벤트 구조
<a name="functions-event-structure"></a>

CloudFront 함수는 함수를 실행할 때 `event` 객체를 함수 코드에 입력으로 전달합니다. [함수를 테스트](test-function.md)할 때 `event` 객체를 생성하여 함수에 전달합니다. 함수를 테스트하기 위해 `event` 객체를 생성할 때 `distributionDomainName` 객체의 `distributionId`, `requestId` 및 `context` 필드를 생략할 수 있습니다. 헤더의 이름이 소문자인지 확인합니다. CloudFront Functions가 프로덕션 환경에서 함수에 전달하는 `event` 객체의 경우 항상 소문자입니다.

다음은 이 이벤트 객체의 구조에 대한 개요를 보여 줍니다.

```
{
    "version": "1.0",
    "context": {
        <context object>
    },
    "viewer": {
        <viewer object>
    },
    "request": {
        <request object>
    },
    "response": {
        <response object>
    }
}
```

자세한 내용은 다음 항목을 참조하세요.

**Topics**
+ [버전 필드](#functions-event-structure-version)
+ [컨텍스트 객체](#functions-event-structure-context)
+ [연결 이벤트 구조](#functions-event-structure-connection)
+ [최종 사용자 객체](#functions-event-structure-viewer)
+ [요청 객체](#functions-event-structure-request)
+ [응답 객체](#functions-event-structure-response)
+ [상태 코드 및 본문](#functions-event-structure-status-body)
+ [쿼리 문자열, 헤더 및 쿠키 구조](#functions-event-structure-query-header-cookie)
+ [예시 응답 객체](#functions-response-structure-example)
+ [예시 이벤트 객체](#functions-event-structure-example)

## 버전 필드
<a name="functions-event-structure-version"></a>

`version` 필드에는 CloudFront 함수 이벤트 객체의 버전을 지정하는 문자열이 포함되어 있습니다. 현재 버전은 `1.0`입니다.

## 컨텍스트 객체
<a name="functions-event-structure-context"></a>

`context` 객체는 이벤트에 대한 컨텍스트 정보를 포함합니다. 여기에는 다음 필드가 포함됩니다.

**`distributionDomainName`**  
이벤트와 연결된 표준 배포의 CloudFront 도메인 이름(예: d111111abcdef8.cloudfront.net)입니다.  
`distributionDomainName` 필드는 함수가 표준 배포에서 호출될 때만 나타납니다.

**`endpoint`**  
이벤트와 연결된 연결 그룹의 CloudFront 도메인 이름(예: d111111abcdef8.cloudfront.net)입니다.  
`endpoint` 필드는 함수가 다중 테넌트 배포에서 호출될 때만 나타납니다.

**`distributionId`**  
이벤트와 연결된 배포의 ID(예: EDFDVBD6EXAMPLE)입니다.

**`eventType`**  
이벤트 유형(`viewer-request` 또는 `viewer-response`)입니다.

**`requestId`**  
CloudFront 요청(및 연결된 응답)을 고유하게 식별하는 문자열입니다.

## 연결 이벤트 구조
<a name="functions-event-structure-connection"></a>

연결 함수는 뷰어 함수와 다른 이벤트 구조를 수신합니다. 연결 이벤트 구조 및 응답 형식에 대한 자세한 내용은 [CloudFront 연결 함수 연결](connection-functions.md) 섹션을 참조하세요.

## 최종 사용자 객체
<a name="functions-event-structure-viewer"></a>

`viewer` 객체는 요청을 보낸 최종 사용자(클라이언트)의 IP 주소 값이 있는 `ip` 필드를 포함합니다. 최종 사용자가 HTTP 프록시 또는 로드 밸런서를 사용하여 요청을 전송한 경우 이 값은 프록시 또는 로드 밸런서의 IP 주소입니다.

## 요청 객체
<a name="functions-event-structure-request"></a>

`request` 객체는 viewer-to-CloudFront HTTP 요청의 표현을 포함합니다. 함수에 전달된 `event` 객체에서 `request` 객체는 CloudFront가 뷰어에게 받은 실제 요청을 나타냅니다.

함수 코드가 CloudFront에 `request` 객체를 반환하는 경우 동일한 구조를 사용해야 합니다.

`request` 객체는 다음 필드를 포함합니다.

**`method`**  
요청의 HTTP 메서드. 함수 코드가 `request`를 반환하면 이 필드를 수정할 수 없습니다. 이 필드는 `request` 객체에서 유일한 읽기 전용 필드입니다.

**`uri`**  
요청된 객체의 상대 경로입니다.  
함수가 `uri` 값을 수정하는 경우 다음 사항이 적용됩니다.  
+ 새 `uri` 값은 슬래시(`/`)로 시작해야 합니다.
+ 함수가 `uri` 값을 변경하는 경우 이로 인해 최종 사용자가 요청 중인 객체가 변경됩니다.
+ 함수가 `uri` 값을 변경하는 경우 이로 인해 요청 또는 요청이 전송되는 오리진에 대한 캐시 동작이 변경되지 **않습니다.

**`querystring`**  
요청의 쿼리 문자열을 나타내는 객체입니다. 요청에 쿼리 문자열이 포함되지 않더라도 `request` 객체에는 여전히 빈 `querystring` 객체가 포함됩니다.  
`querystring` 객체는 요청의 각 쿼리 문자열 파라미터에 대해 하나의 필드를 포함합니다.

**`headers`**  
요청의 HTTP 헤더를 나타내는 객체입니다. 요청에 `Cookie` 헤더가 포함되어 있으면 해당 헤더는 `headers` 객체의 일부가 아닙니다. 쿠키는 `cookies` 객체에서 별도로 표시됩니다.  
`headers` 객체는 요청의 각 헤더에 대해 하나의 필드를 포함합니다. 헤더 이름은 이벤트 객체에서 ASCII 소문자로 변환되므로 함수 코드에서 추가될 경우 헤더 이름은 ASCII 소문자여야 합니다. CloudFront Functions이 이벤트 객체를 HTTP 요청으로 다시 변환할 경우 헤더 이름이 ASCII 문자이면 헤더 이름에 있는 각 단어의 첫 글자가 대문자로 표시됩니다. CloudFront Functions은 헤더 이름의 ASCII가 아닌 기호에 변경 사항을 적용하지 않습니다. 예를 들어 `TÈst-header`는 함수 내 `tÈst-header`에 있게 됩니다. ASCII가 아닌 기호(`È`)는 변경되지 않습니다.  
단어는 하이픈(`-`)으로 구분됩니다. 예를 들어 함수 코드가 `example-header-name`이라는 이름의 헤더를 추가하는 경우, CloudFront는 이것을 HTTP 요청에서 `Example-Header-Name`으로 변환합니다.

**`cookies`**  
요청(`Cookie` 헤더)의 쿠키를 나타내는 객체입니다.  
`cookies` 객체는 요청의 각 쿠키에 대해 하나의 필드를 포함합니다.

쿼리 문자열, 헤더 및 쿠키의 구조에 대한 자세한 내용은 [쿼리 문자열, 헤더 및 쿠키 구조](#functions-event-structure-query-header-cookie) 단원을 참조하세요.

예제 `event` 객체에 대해서는 [예시 이벤트 객체](#functions-event-structure-example) 단원을 참조하세요.

## 응답 객체
<a name="functions-event-structure-response"></a>

`response` 객체는 CloudFront-to-Viewer HTTP 응답의 표현을 포함합니다. 함수에 전달된 `event` 객체에서 `response` 객체는 뷰어 요청에 대한 CloudFront의 실제 응답을 나타냅니다.

함수 코드가 `response` 객체를 반환하는 경우 이 동일한 구조를 사용해야 합니다.

`response` 객체는 다음 필드를 포함합니다.

**`statusCode`**  
응답의 HTTP 상태 코드입니다. 이 값은 문자열이 아닌 정수입니다.  
함수는 `statusCode`를 생성하거나 수정할 수 있습니다.

**`statusDescription`**  
응답의 HTTP 상태 설명입니다. 함수 코드에서 응답을 생성하는 경우 이 필드는 선택 사항입니다.

**`headers`**  
응답에서 HTTP 헤더를 나타내는 객체입니다. 응답에 `Set-Cookie` 헤더가 포함되어 있으면 해당 헤더는 `headers` 객체의 일부가 아닙니다. 쿠키는 `cookies` 객체에서 별도로 표시됩니다.  
`headers` 객체는 응답의 각 헤더에 대해 하나의 필드를 포함합니다. 헤더 이름은 이벤트 객체에서 소문자로 변환되므로, 헤더 이름은 함수 코드에 의해 추가될 때 소문자여야 합니다. CloudFront 함수가 이벤트 객체를 HTTP 응답으로 다시 변환하는 경우 헤더 이름에 있는 각 단어의 첫 글자가 대문자로 표시됩니다. 단어는 하이픈(`-`)으로 구분됩니다. 예를 들어 함수 코드가 `example-header-name`이라는 이름의 헤더를 추가하는 경우, CloudFront는 이것을 HTTP 응답에서 `Example-Header-Name`으로 변환합니다.

**`cookies`**  
응답(`Set-Cookie` 헤더)에서 쿠키를 나타내는 객체입니다.  
`cookies` 객체는 응답의 각 쿠키에 대해 하나의 필드를 포함합니다.

**`body`**  
`body` 필드 추가는 선택 사항이며 함수에서 지정하지 않는 한 `response` 객체에 표시되지 않습니다. 함수는 CloudFront 캐시 또는 오리진에서 반환된 원래 본문에 액세스할 수 없습니다. 뷰어 응답 함수에서 `body` 필드를 지정하지 않으면 CloudFront 캐시 또는 오리진에서 반환되는 원래 본문이 뷰어에게 반환됩니다.  
CloudFront에서 뷰어에게 사용자 지정 본문을 반환하도록 하려면 `data` 필드에 본문 콘텐츠를 지정하고 `encoding` 필드에 본문 인코딩을 지정하세요. 인코딩을 일반 텍스트(`"encoding": "text"`) 또는 Base64로 인코딩된 콘텐츠(`"encoding": "base64"`)로 지정할 수 있습니다.  
단축키로 `body` 필드(`"body": "<specify the body content here>"`)에서 직접 본문 콘텐츠를 지정할 수도 있습니다. 이 작업을 수행할 때는 `data` 및 `encoding` 필드를 생략하세요. 이 경우 CloudFront는 본문을 일반 텍스트로 취급합니다.    
`encoding`  
`body` 콘텐츠(`data`필드)의 인코딩입니다. 유일하게 유효한 인코딩은 `text`과 `base64`입니다.  
`encoding`을 `base64`로 지정하지만 본문이 유효한 base64가 아닌 경우 CloudFront는 오류를 반환합니다.  
`data`  
`body` 콘텐츠입니다.

수정된 상태 코드 및 본문 콘텐츠에 대한 자세한 내용은 [상태 코드 및 본문](#functions-event-structure-status-body)를 참조하세요.

헤더 및 쿠키의 구조에 대한 자세한 내용은 [쿼리 문자열, 헤더 및 쿠키 구조](#functions-event-structure-query-header-cookie) 단원을 참조하세요.

예제 `response` 객체에 대해서는 [예시 응답 객체](#functions-response-structure-example) 단원을 참조하세요.

## 상태 코드 및 본문
<a name="functions-event-structure-status-body"></a>

CloudFront Functions를 사용하여 뷰어 응답 상태 코드를 업데이트하고 응답 본문 전체를 새것으로 바꾸거나 제거할 수 있습니다. CloudFront 캐시 또는 오리진에서 응답의 여러 측면을 평가한 후 뷰어 응답을 업데이트하는 일반적인 시나리오는 다음과 같습니다.
+ 상태를 변경하여 HTTP 200 상태 코드를 설정하고 정적 본문 콘텐츠를 생성하여 뷰어에게 반환합니다.
+ 상태를 변경하여 HTTP 301 또는 302 상태 코드를 설정하고 사용자를 다른 웹 페이지로 리디렉션합니다.
+ 뷰어 응답의 본문을 제공할지 아니면 삭제할지 결정합니다.

**참고**  
오리진에서 400 이상의 HTTP 오류를 반환하는 경우 CloudFront Function이 실행되지 않습니다. 자세한 내용은 [모든 엣지 함수에 대한 제한 사항](edge-function-restrictions-all.md)을 참조하세요.

HTTP 응답 본문을 사용하여 작업 중일 때 CloudFront Functions가 응답 본문에 액세스하지 못합니다. 원하는 값으로 설정하여 본문 콘텐츠를 바꾸거나 값을 비어 있음으로 설정하여 본문을 제거할 수 있습니다. 함수의 본문 필드를 업데이트하지 않은 경우 CloudFront 캐시 또는 오리진에서 반환된 원래 본문이 뷰어에게 반환됩니다.

**작은 정보**  
CloudFront Functions를 사용하여 본문을 교체하는 경우`content-encoding`, `content-type` 또는 `content-length` 등의 해당 헤더를 새 본문 콘텐츠에 맞게 정렬해야 합니다.  
예를 들어 CloudFront 오리진 또는 캐시가 `content-encoding: gzip`을 반환하지만 뷰어 응답 함수가 일반 텍스트인 본문을 설정하는 경우 함수는 `content-encoding` 및 `content-type` 헤더도 그에 따라 변경해야 합니다.

CloudFront Function이 400 이상의 HTTP 오류를 반환하도록 구성된 경우 동일한 상태 코드에 대해 지정한 [사용자 지정 오류 페이지](creating-custom-error-pages.md)가 뷰어에게 표시되지 않습니다.

## 쿼리 문자열, 헤더 및 쿠키 구조
<a name="functions-event-structure-query-header-cookie"></a>

쿼리 문자열, 헤더 및 쿠키는 동일한 구조를 공유합니다. 쿼리 문자열은 요청에 표시될 수 있습니다. 헤더는 요청 및 응답에 표시됩니다. 쿠키는 요청 및 응답에 표시됩니다.

각 쿼리 문자열, 헤더 또는 쿠키는 상위 `querystring`, `headers` 또는 `cookies` 객체 내에서 고유한 필드입니다. 필드 이름은 쿼리 문자열, 헤더 또는 쿠키의 이름입니다. 각 필드에는 쿼리 문자열, 헤더 또는 쿠키의 값이 있는 `value` 속성이 포함됩니다.

**Contents**
+ [쿼리 문자열 값 또는 쿼리 문자열 객체](#functions-event-structure-query)
+ [헤더에 대한 특별 고려 사항](#functions-event-structure-headers)
+ [중복 쿼리 문자열, 헤더 및 쿠키(`multiValue` 배열)](#functions-event-structure-multivalue)
+ [쿠키 속성](#functions-event-structure-cookie-attributes)

### 쿼리 문자열 값 또는 쿼리 문자열 객체
<a name="functions-event-structure-query"></a>

함수는 쿼리 문자열 객체 외에도 쿼리 문자열 값을 반환할 수 있습니다. 쿼리 문자열 값을 사용하여 쿼리 문자열 파라미터를 사용자 지정 순서로 정렬할 수 있습니다.

**Example 예제**  
함수 코드에서 쿼리 문자열을 수정하려면 다음과 같은 코드를 사용합니다.  

```
var request = event.request; 
request.querystring = 'ID=42&Exp=1619740800&TTL=1440&NoValue=&querymv=val1&querymv=val2,val3';
```

### 헤더에 대한 특별 고려 사항
<a name="functions-event-structure-headers"></a>

헤더의 경우, 헤더 이름은 이벤트 객체에서 소문자로 변환되므로, 헤더 이름은 함수 코드에 의해 추가될 때 소문자여야 합니다. CloudFront 함수가 이벤트 객체를 HTTP 요청 또는 응답으로 다시 변환하는 경우 헤더 이름에 있는 각 단어의 첫 글자가 대문자로 표시됩니다. 단어는 하이픈(`-`)으로 구분됩니다. 예를 들어 함수 코드가 `example-header-name`이라는 이름의 헤더를 추가하는 경우, CloudFront는 이것을 HTTP 요청 또는 응답에서 `Example-Header-Name`으로 변환합니다.

**Example 예제**  
HTTP 요청에서 다음 `Host` 헤더를 고려합니다.  

```
Host: video.example.com
```
이 헤더는 `request` 객체에서 다음과 같이 표시됩니다.  

```
"headers": {
    "host": {
        "value": "video.example.com"
    }
}
```
함수 코드의 `Host` 헤더에 액세스하려면 다음과 같은 코드를 사용합니다.  

```
var request = event.request;
var host = request.headers.host.value;
```
함수 코드에서 헤더를 추가하거나 수정하려면 다음과 같은 코드를 사용합니다(이 코드는 `X-Custom-Header` 값이 있는 `example value`(이)라는 이름의 헤더를 추가함).  

```
var request = event.request;
request.headers['x-custom-header'] = {value: 'example value'};
```

### 중복 쿼리 문자열, 헤더 및 쿠키(`multiValue` 배열)
<a name="functions-event-structure-multivalue"></a>

HTTP 요청 또는 응답은 동일한 이름의 하나 이상의 쿼리 문자열, 헤더 또는 쿠키를 포함할 수 있습니다. 이 경우 중복 쿼리 문자열, 헤더 또는 쿠키가 `request` 또는 `response` 객체의 한 필드로 축소되지만 이 필드에는 `multiValue`(이)라는 추가 속성이 포함되어 있습니다. `multiValue` 속성에는 중복 쿼리 문자열, 헤더 또는 쿠키의 각 값이 포함된 배열이 포함됩니다.

**Example 예제**  
예를 들어 다음 `Accept` 헤더가 있는 HTTP 요청을 고려합니다.  

```
Accept: application/json
Accept: application/xml
Accept: text/html
```
이러한 헤더는 `request` 객체에 다음과 같이 표시됩니다.  

```
"headers": {
    "accept": {
        "value": "application/json",
        "multiValue": [
            {
                "value": "application/json"
            },
            {
                "value": "application/xml"
            },
            {
                "value": "text/html"
            }
        ]
    }
}
```

**참고**  
첫 번째 헤더 값(이 경우 `application/json`)은 `value` 및 `multiValue` 속성 모두에서 반복됩니다. 이렇게 하면 `multiValue` 배열을 반복하여 *모든* 값에 액세스할 수 있습니다.

함수 코드가 `multiValue` 배열이 있는 쿼리 문자열, 헤더 또는 쿠키를 수정하는 경우 CloudFront 함수는 다음 규칙을 사용하여 변경 사항을 적용합니다.

1. `multiValue` 배열이 존재하고 수정이 있으면 해당 수정이 적용됩니다. `value` 속성의 첫 번째 요소는 무시됩니다.

1. 그렇지 않으면 `value` 속성에 대한 수정 사항이 적용되고 후속 값(있는 경우)은 변경되지 않습니다.

`multiValue` 속성은 앞의 예제와 같이 HTTP 요청 또는 응답에 동일한 이름의 중복 쿼리 문자열, 헤더 또는 쿠키가 포함된 경우에만 사용됩니다. 그러나 단일 쿼리 문자열, 헤더 또는 쿠키에 값이 여러 개 있으면 `multiValue` 속성이 사용되지 않습니다.

**Example 예제**  
예를 들어 세 개의 값을 포함하는 하나의 `Accept` 헤더가 있는 요청을 고려합니다.  

```
Accept: application/json, application/xml, text/html
```
이 헤더는 `request` 객체에서 다음과 같이 표시됩니다.  

```
"headers": {
    "accept": {
        "value": "application/json, application/xml, text/html"
    }
}
```

### 쿠키 속성
<a name="functions-event-structure-cookie-attributes"></a>

HTTP 응답의 `Set-Cookie` 헤더에서 헤더에는 쿠키의 이름-값 쌍과 세미콜론으로 구분된 속성 집합이 포함됩니다.

**Example 예제**  

```
Set-Cookie: cookie1=val1; Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT
```
`response` 객체에서 이러한 속성은 쿠키 필드의 `attributes` 속성에 표시됩니다. 예를 들어, 앞의 `Set-Cookie` 헤더는 다음과 같이 표시됩니다.  

```
"cookie1": {
    "value": "val1",
    "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT"
}
```

## 예시 응답 객체
<a name="functions-response-structure-example"></a>

다음 예시는 본문이 뷰어 응답 함수로 대체된 `response` 객체(뷰어 응답 함수의 출력)를 보여줍니다.

```
{
  "response": {
    "statusCode": 200,
    "statusDescription": "OK",
    "headers": {
      "date": {
        "value": "Mon, 04 Apr 2021 18:57:56 GMT"
      },
      "server": {
        "value": "gunicorn/19.9.0"
      },
      "access-control-allow-origin": {
        "value": "*"
      },
      "access-control-allow-credentials": {
        "value": "true"
      },
      "content-type": {
        "value": "text/html"
      },
      "content-length": {
        "value": "86"
      }
    },
    "cookies": {
      "ID": {
        "value": "id1234",
        "attributes": "Expires=Wed, 05 Apr 2021 07:28:00 GMT"
      },
      "Cookie1": {
        "value": "val1",
        "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT",
        "multiValue": [
          {
            "value": "val1",
            "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT"
          },
          {
            "value": "val2",
            "attributes": "Path=/cat; Domain=example.com; Expires=Wed, 10 Jan 2021 07:28:00 GMT"
          }
        ]
      }
    },
    
    // Adding the body field is optional and it will not be present in the response object
    // unless you specify it in your function.
    // Your function does not have access to the original body returned by the CloudFront
    // cache or origin.
    // If you don't specify the body field in your viewer response function, the original
    // body returned by the CloudFront cache or origin is returned to viewer.

     "body": {
      "encoding": "text",
      "data": "<!DOCTYPE html><html><body><p>Here is your custom content.</p></body></html>"
    }
  }
}
```

## 예시 이벤트 객체
<a name="functions-event-structure-example"></a>

다음 예는 완전한 `event` 객체를 보여줍니다. 이 예제는 다중 테넌트 배포가 아닌 표준 배포에서의 호출입니다. 다중 테넌트 배포의 경우 `distributionDomainName` 대신 `endpoint` 필드가 사용됩니다. `endpoint`의 값은 이벤트와 연결된 연결 그룹의 CloudFront 도메인 이름(예: d111111abcdef8.cloudfront.net)입니다.

**참고**  
`event` 객체는 함수에 대한 입력입니다. 함수는 `request` 또는 `response` 객체만 반환하고 전체 `event` 객체는 반환하지 않습니다.

```
{
    "version": "1.0",
    "context": {
        "distributionDomainName": "d111111abcdef8.cloudfront.net",
        "distributionId": "EDFDVBD6EXAMPLE",
        "eventType": "viewer-response",
        "requestId": "EXAMPLEntjQpEXAMPLE_SG5Z-EXAMPLEPmPfEXAMPLEu3EqEXAMPLE=="
    },
    "viewer": {"ip": "198.51.100.11"},
    "request": {
        "method": "GET",
        "uri": "/media/index.mpd",
        "querystring": {
            "ID": {"value": "42"},
            "Exp": {"value": "1619740800"},
            "TTL": {"value": "1440"},
            "NoValue": {"value": ""},
            "querymv": {
                "value": "val1",
                "multiValue": [
                    {"value": "val1"},
                    {"value": "val2,val3"}
                ]
            }
        },
        "headers": {
            "host": {"value": "video.example.com"},
            "user-agent": {"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0"},
            "accept": {
                "value": "application/json",
                "multiValue": [
                    {"value": "application/json"},
                    {"value": "application/xml"},
                    {"value": "text/html"}
                ]
            },
            "accept-language": {"value": "en-GB,en;q=0.5"},
            "accept-encoding": {"value": "gzip, deflate, br"},
            "origin": {"value": "https://website.example.com"},
            "referer": {"value": "https://website.example.com/videos/12345678?action=play"},
            "cloudfront-viewer-country": {"value": "GB"}
        },
        "cookies": {
            "Cookie1": {"value": "value1"},
            "Cookie2": {"value": "value2"},
            "cookie_consent": {"value": "true"},
            "cookiemv": {
                "value": "value3",
                "multiValue": [
                    {"value": "value3"},
                    {"value": "value4"}
                ]
            }
        }
    },
    "response": {
        "statusCode": 200,
        "statusDescription": "OK",
        "headers": {
            "date": {"value": "Mon, 04 Apr 2021 18:57:56 GMT"},
            "server": {"value": "gunicorn/19.9.0"},
            "access-control-allow-origin": {"value": "*"},
            "access-control-allow-credentials": {"value": "true"},
            "content-type": {"value": "application/json"},
            "content-length": {"value": "701"}
        },
        "cookies": {
            "ID": {
                "value": "id1234",
                "attributes": "Expires=Wed, 05 Apr 2021 07:28:00 GMT"
            },
            "Cookie1": {
                "value": "val1",
                "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT",
                "multiValue": [
                    {
                        "value": "val1",
                        "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT"
                    },
                    {
                        "value": "val2",
                        "attributes": "Path=/cat; Domain=example.com; Expires=Wed, 10 Jan 2021 07:28:00 GMT"
                    }
                ]
            }
        }
    }
}
```

# CloudFront 함수에 대한 JavaScript 런타임 기능
<a name="functions-javascript-runtime-features"></a>

CloudFront Functions JavaScript 런타임 환경은 [ECMAScript(ES) 버전 5.1](https://www.ecma-international.org/ecma-262/5.1/)을 준수하며, ES 버전 6에서 12까지의 일부 기능을 지원합니다.

최신 기능을 이용하려면 JavaScript 런타임 2.0을 사용하는 것이 좋습니다.

JavaScript 1.0과 비교한 JavaScript 2.0의 변경 사항은 다음과 같습니다.
+ 버퍼 모듈 메서드 사용 가능
+ 다음과 같은 비표준 문자열 프로토타입 메서드는 사용할 수 없습니다.
  + `String.prototype.bytesFrom()`
  + `String.prototype.fromBytes()`
  + `String.prototype.fromUTF8()`
  + `String.prototype.toBytes()`
  + `String.prototype.toUTF8()`
+ 암호화 모듈의 변경 사항은 다음과 같습니다.
  + `hash.digest()` - 인코딩이 제공되지 않은 경우 반환 유형이 `Buffer`로 변경됩니다.
  + `hmac.digest()` - 인코딩이 제공되지 않은 경우 반환 유형이 `Buffer`로 변경됩니다.
+ 이 밖의 새로운 기능에 대한 자세한 내용은 [CloudFront Functions를 위한 JavaScript 런타임 2.0 기능](functions-javascript-runtime-20.md) 섹션을 참조하세요.

**Topics**
+ [JavaScript 런타임 1.0 기능](functions-javascript-runtime-10.md)
+ [JavaScript 런타임 2.0 기능](functions-javascript-runtime-20.md)

# CloudFront Functions를 위한 JavaScript 런타임 1.0 기능
<a name="functions-javascript-runtime-10"></a>

CloudFront 함수 JavaScript 런타임 환경은 [ECMAScript(ES) 버전 5.1](https://262.ecma-international.org/5.1/)을 준수하며, ES 버전 6에서 9까지의 일부 기능을 지원합니다. 또한 ES 사양의 일부가 아닌 일부 비표준 방법을 제공합니다.

다음 항목에는 지원되는 모든 언어 기능이 나열되어 있습니다.

**Topics**
+ [핵심 기능](#writing-functions-javascript-features-core)
+ [기본 객체](#writing-functions-javascript-features-primitive-objects)
+ [기본 제공 객체](#writing-functions-javascript-features-builtin-objects)
+ [오류 유형](#writing-functions-javascript-features-error-types)
+ [Globals](#writing-functions-javascript-features-globals)
+ [기본 제공 모듈](#writing-functions-javascript-features-builtin-modules)
+ [제한된 기능](#writing-functions-javascript-features-restricted-features)

## 핵심 기능
<a name="writing-functions-javascript-features-core"></a>

ES의 다음과 같은 핵심 기능이 지원됩니다.

**유형**  
모든 ES 5.1 유형이 지원됩니다. 여기에는 부울 값, 숫자, 문자열, 객체, 배열, 함수, 함수 생성자 및 정규 표현식이 포함됩니다.

**연산자**  
모든 ES 5.1 연산자가 지원됩니다.  
ES 7 거듭제곱 연산자(`**`)가 지원됩니다.

**Statement**  
`const` 및 `let` 문은 지원되지 않습니다.
다음 ES 5.1 문이 지원됩니다.  
+ `break`
+ `catch`
+ `continue`
+ `do-while`
+ `else`
+ `finally`
+ `for`
+ `for-in`
+ `if`
+ `return`
+ `switch`
+ `throw`
+ `try`
+ `var`
+ `while`
+ 레이블이 지정된 명령문

**리터럴**  
ES 6 템플릿 리터럴은 여러 줄 문자열, 표현식 보간 및 중첩 템플릿에 대해 지원됩니다..

**함수**  
모든 ES 5.1 함수 기능이 지원됩니다.  
ES 6 화살표 함수가 지원되며 ES 6 나머지 파라미터 구문이 지원됩니다.

**유니코드**  
소스 텍스트 및 문자열 리터럴에는 유니코드로 인코딩된 문자가 포함될 수 있습니다. 6자의 유니코드 코드 포인트 이스케이프 시퀀스(예: `\uXXXX`)도 지원됩니다.

**엄격 모드**  
함수는 기본적으로 엄격 모드에서 작동하므로 함수 코드에 `use strict` 명령문을 추가할 필요가 없습니다. 이것은 변경할 수 없습니다.

## 기본 객체
<a name="writing-functions-javascript-features-primitive-objects"></a>

ES의 다음과 같은 기본 객체가 지원됩니다.

**객체**  
객체에 대해 다음과 같은 ES 5.1 메서드가 지원됩니다.  
+ `create`(속성 목록 제외)
+ `defineProperties`
+ `defineProperty`
+ `freeze`
+ `getOwnPropertyDescriptor`
+ `getOwnPropertyNames`
+ `getPrototypeOf`
+ `hasOwnProperty`
+ `isExtensible`
+ `isFrozen`
+ `prototype.isPrototypeOf`
+ `isSealed`
+ `keys`
+ `preventExtensions`
+ `prototype.propertyIsEnumerable`
+ `seal`
+ `prototype.toString`
+ `prototype.valueOf`
객체에 대해 다음 ES 6 메서드가 지원됩니다.  
+ `assign`
+ `is`
+ `prototype.setPrototypeOf`
객체에 대해 다음과 같은 ES 8 메서드가 지원됩니다.  
+ `entries`
+ `values`

**문자열**  
문자열에 대해 다음 ES 5.1 메서드가 지원됩니다.  
+ `fromCharCode`
+ `prototype.charAt`
+ `prototype.concat`
+ `prototype.indexOf`
+ `prototype.lastIndexOf`
+ `prototype.match`
+ `prototype.replace`
+ `prototype.search`
+ `prototype.slice`
+ `prototype.split`
+ `prototype.substr`
+ `prototype.substring`
+ `prototype.toLowerCase`
+ `prototype.trim`
+ `prototype.toUpperCase`
문자열에 대해 다음 ES 6 메서드가 지원됩니다.  
+ `fromCodePoint`
+ `prototype.codePointAt`
+ `prototype.endsWith`
+ `prototype.includes`
+ `prototype.repeat`
+ `prototype.startsWith`
문자열에 대해 다음 ES 8 메서드가 지원됩니다.  
+ `prototype.padStart`
+ `prototype.padEnd`
문자열에 대해 다음 ES 9 메서드가 지원됩니다.  
+ `prototype.trimStart`
+ `prototype.trimEnd`
문자열에 대해 다음과 같은 비표준 메서드가 지원됩니다.  
+ `prototype.bytesFrom(array | string, encoding)`

  옥텟 배열 또는 인코딩된 문자열에서 바이트 문자열을 만듭니다. 문자열 인코딩 옵션은 `hex`, `base64` 및 `base64url`입니다.
+ `prototype.fromBytes(start[, end])`

  각 바이트가 해당 유니코드 코드 포인트로 대체되는 바이트 문자열에서 유니코드 문자열을 만듭니다.
+ `prototype.fromUTF8(start[, end])`

  UTF-8 인코딩된 바이트 문자열에서 유니코드 문자열을 만듭니다. 인코딩이 올바르지 않으면 `null`이(가) 반환됩니다.
+ `prototype.toBytes(start[, end])`

  유니코드 문자열에서 바이트 문자열을 만듭니다. 모든 문자는 [0,255] 범위에 있어야 합니다. 그렇지 않은 경우 `null`이 반환됩니다.
+ `prototype.toUTF8(start[, end])`

  유니코드 문자열에서 UTF-8 인코딩된 바이트 문자열을 만듭니다.

**번호**  
숫자에 대한 모든 ES 5.1 메서드가 지원됩니다.  
숫자에 대해 다음 ES 6 메서드가 지원됩니다.  
+ `isFinite`
+ `isInteger`
+ `isNaN`
+ `isSafeInteger`
+ `parseFloat`
+ `parseInt`
+ `prototype.toExponential`
+ `prototype.toFixed`
+ `prototype.toPrecision`
+ `EPSILON`
+ `MAX_SAFE_INTEGER`
+ `MAX_VALUE`
+ `MIN_SAFE_INTEGER`
+ `MIN_VALUE`
+ `NEGATIVE_INFINITY`
+ `NaN`
+ `POSITIVE_INFINITY`

## 기본 제공 객체
<a name="writing-functions-javascript-features-builtin-objects"></a>

ES의 다음 내장 객체가 지원됩니다.

**수학 연산**  
모든 ES 5.1 수학 메서드가 지원됩니다.  
CloudFront 함수 런타임 환경에서 `Math.random()` 구현은 함수가 실행될 때의 타임스탬프와 함께 시드된 OpenBSD `arc4random`을(를) 사용합니다.
다음 ES 6 수학 메서드가 지원됩니다.  
+ `acosh`
+ `asinh`
+ `atanh`
+ `cbrt`
+ `clz32`
+ `cosh`
+ `expm1`
+ `fround`
+ `hypot`
+ `imul`
+ `log10`
+ `log1p`
+ `log2`
+ `sign`
+ `sinh`
+ `tanh`
+ `trunc`
+ `E`
+ `LN10`
+ `LN2`
+ `LOG10E`
+ `LOG2E`
+ `PI`
+ `SQRT1_2`
+ `SQRT2`

**날짜**  
모든 ES 5.1 `Date` 기능이 지원됩니다.  
보안상의 이유로 단일 함수 실행의 수명 동안 `Date`은(는) 항상 동일한 값(함수의 시작 시간)을 반환합니다. 자세한 내용은 [제한된 기능](#writing-functions-javascript-features-restricted-features) 단원을 참조하세요.

**함수**  
`apply`, `bind` 및 `call` 메서드가 지원됩니다.  
함수 생성자는 지원되지 않습니다.

**정규식**  
모든 ES 5.1 정규 표현식 기능이 지원됩니다. 정규 표현식 언어는 Perl과 호환됩니다. ES 9 명명된 캡처 그룹이 지원됩니다.

**JSON**  
`parse` 및 `stringify`을(를) 포함하여 모든 ES 5.1 JSON 기능이 지원됩니다.

**배열**  
배열에 대해 다음 ES 5.1 메서드가 지원됩니다.  
+ `isArray`
+ `prototype.concat`
+ `prototype.every`
+ `prototype.filter`
+ `prototype.forEach`
+ `prototype.indexOf`
+ `prototype.join`
+ `prototype.lastIndexOf`
+ `prototype.map`
+ `prototype.pop`
+ `prototype.push`
+ `prototype.reduce`
+ `prototype.reduceRight`
+ `prototype.reverse`
+ `prototype.shift`
+ `prototype.slice`
+ `prototype.some`
+ `prototype.sort`
+ `prototype.splice`
+ `prototype.unshift`
배열에 대해 다음 ES 6 메서드가 지원됩니다.  
+ `of`
+ `prototype.copyWithin`
+ `prototype.fill`
+ `prototype.find`
+ `prototype.findIndex`
배열에 대해 다음 ES 7 메서드가 지원됩니다.  
+ `prototype.includes`

**형식화된 배열**  
다음 ES 6 형식화된 배열이 지원됩니다.  
+ `Int8Array`
+ `Uint8Array`
+ `Uint8ClampedArray`
+ `Int16Array`
+ `Uint16Array`
+ `Int32Array`
+ `Uint32Array`
+ `Float32Array`
+ `Float64Array`
+ `prototype.copyWithin`
+ `prototype.fill`
+ `prototype.join`
+ `prototype.set`
+ `prototype.slice`
+ `prototype.subarray`
+ `prototype.toString`

**배열 버퍼**  
`ArrayBuffer`에 대해 메서드가 지원됩니다.  
+ `prototype.isView`
+ `prototype.slice`

**Promise**  
Promise에 대해 다음 메서드가 지원됩니다.  
+ `reject`
+ `resolve`
+ `prototype.catch`
+ `prototype.finally`
+ `prototype.then`

**crypto**  
암호화 모듈은 표준 해싱 및 HMAC(해시 기반 메시지 인증 코드) 헬퍼를 제공합니다. `require('crypto')`을(를) 사용하여 모듈을 로드할 수 있습니다. 모듈은 해당 Node.js 대응으로 정확하게 동작하는 다음과 같은 메서드를 노출합니다.  
+ `createHash(algorithm)`
+ `hash.update(data)`
+ `hash.digest([encoding])`
+ `createHmac(algorithm, secret key)`
+ `hmac.update(data)`
+ `hmac.digest([encoding])`
자세한 내용은 기본 제공 모듈 단원의 [암호화(해시 및 HMAC)](#writing-functions-javascript-features-builtin-modules-crypto)를 참조하세요.

**콘솔**  
디버깅을 위한 헬퍼 객체입니다. 로그 메시지를 기록하는 `log()` 메서드만 지원합니다.  
CloudFront 함수는 `console.log('a', 'b')`와 같은 쉼표 구문을 지원하지 않습니다. 대신 `console.log('a' + ' ' + 'b')` 형식을 사용합니다.

## 오류 유형
<a name="writing-functions-javascript-features-error-types"></a>

다음과 같은 오류 객체가 지원됩니다.
+ `Error`
+ `EvalError`
+ `InternalError`
+ `MemoryError`
+ `RangeError`
+ `ReferenceError`
+ `SyntaxError`
+ `TypeError`
+ `URIError`

## Globals
<a name="writing-functions-javascript-features-globals"></a>

`globalThis` 객체가 지원됩니다.

다음 ES 5.1 전역 함수가 지원됩니다.
+ `decodeURI`
+ `decodeURIComponent`
+ `encodeURI`
+ `encodeURIComponent`
+ `isFinite`
+ `isNaN`
+ `parseFloat`
+ `parseInt`

다음과 같은 글로벌 제약이 지원됩니다.
+ `NaN`
+ `Infinity`
+ `undefined`

## 기본 제공 모듈
<a name="writing-functions-javascript-features-builtin-modules"></a>

다음 기본 제공 모듈이 지원됩니다.

**Topics**
+ [암호화(해시 및 HMAC)](#writing-functions-javascript-features-builtin-modules-crypto)
+ [쿼리 문자열](#writing-functions-javascript-features-builtin-modules-query-string)

### 암호화(해시 및 HMAC)
<a name="writing-functions-javascript-features-builtin-modules-crypto"></a>

암호화 모듈(`crypto`)은 표준 해싱 및 HMAC(해시 기반 메시지 인증 코드) 헬퍼를 제공합니다. `require('crypto')`을(를) 사용하여 모듈을 로드할 수 있습니다. 이 모듈은 Node.js 대응물과 정확히 동일하게 동작하는 다음과 같은 메서드를 제공합니다.

**해싱 메서드**

`crypto.createHash(algorithm)`  
지정된 알고리즘(`md5`, `sha1` 또는 `sha256`)을 사용하여 해시 다이제스트를 생성하는 데 사용할 수 있는 해시 객체를 생성하고 반환합니다.

`hash.update(data)`  
지정된 `data`(으)로 해시 콘텐츠를 업데이트합니다.

`hash.digest([encoding])`  
`hash.update()`을(를) 사용하여 전달된 모든 데이터의 다이제스트를 계산합니다. 인코딩은 `hex`, `base64` 또는 `base64url`일 수 있습니다.

**HMAC 메서드**

`crypto.createHmac(algorithm, secret key)`  
지정된 `algorithm` 및 `secret key`을(를) 사용하는 HMAC 객체를 생성 및 반환합니다. 알고리즘은 `md5`, `sha1` 또는 `sha256`일 수 있습니다.

`hmac.update(data)`  
지정된 `data`(으)로 HMAC 콘텐츠를 업데이트합니다.

`hmac.digest([encoding])`  
`hmac.update()`을(를) 사용하여 전달된 모든 데이터의 다이제스트를 계산합니다. 인코딩은 `hex`, `base64` 또는 `base64url`일 수 있습니다.

### 쿼리 문자열
<a name="writing-functions-javascript-features-builtin-modules-query-string"></a>

**참고**  
[CloudFront 함수 이벤트 객체](functions-event-structure.md)는 URL 쿼리 문자열을 자동으로 구문 분석합니다. 즉, 대부분의 경우 이 모듈을 사용할 필요가 없습니다.

쿼리 문자열 모듈(`querystring`)은 URL 쿼리 문자열을 구문 분석하고 서식을 지정하는 메서드를 제공합니다. `require('querystring')`을 사용하여 모듈을 로드할 수 있습니다. 이 모듈은 다음과 같은 방법을 제공합니다.

`querystring.escape(string)`  
지정된 `string`을 URL-인코딩하여 이스케이프된 쿼리 문자열을 반환합니다. 이 방법은 `querystring.stringify()`에서 사용되며 직접 사용해서는 안 됩니다.

`querystring.parse(string[, separator[, equal[, options]]])`  
쿼리 문자열(`string`)을 구문 분석하고 객체를 반환합니다.  
`separator` 파라미터는 쿼리 문자열에서 키와 값 페어를 구분하기 위한 하위 문자열입니다. 기본 설정은 `&`입니다.  
`equal` 파라미터는 쿼리 문자열에서 키와 값을 구분하기 위한 하위 문자열입니다. 기본 설정은 `=`입니다.  
`options` 파라미터는 다음 키를 가진 객체입니다.    
`decodeURIComponent function`  
쿼리 문자열에서 백분율로 인코딩된 문자를 디코딩하는 함수입니다. 기본 설정은 `querystring.unescape()`입니다.  
`maxKeys number`  
구문 분석할 최대 키 수입니다. 기본 설정은 `1000`입니다. `0` 값을 사용하여 키 카운트 제한을 제거합니다.
기본적으로 쿼리 문자열 내의 백분율로 인코딩된 문자는 UTF-8 인코딩을 사용하는 것으로 간주됩니다. 잘못된 UTF-8 시퀀스는 `U+FFFD` 대체 문자로 대체됩니다.  
예를 들어 다음 쿼리 문자열의 경우:  

```
'name=value&abc=xyz&abc=123'
```
`querystring.parse()`의 반환 값:  

```
{
name: 'value',
abc: ['xyz', '123']
}
```
`querystring.decode()`는 `querystring.parse()`의 별칭입니다.

`querystring.stringify(object[, separator[, equal[, options]]])`  
`object`를 직렬화하고 쿼리 문자열을 반환합니다.  
`separator` 파라미터는 쿼리 문자열에서 키와 값 쌍을 구분하기 위한 하위 문자열입니다. 기본 설정은 `&`입니다.  
`equal` 파라미터는 쿼리 문자열에서 키와 값을 구분하기 위한 하위 문자열입니다. 기본 설정은 `=`입니다.  
`options` 파라미터는 다음 키를 가진 객체입니다.    
`encodeURIComponent function`  
URL에 안전하지 않은 문자를 쿼리 문자열에서 백분율 인코딩으로 변환하는 데 사용할 함수입니다. 기본 설정은 `querystring.escape()`입니다.
기본적으로 쿼리 문자열 내에서 백분율 인코딩이 필요한 문자는 UTF-8로 인코딩됩니다. 다른 인코딩을 사용하려면 `encodeURIComponent` 옵션을 지정합니다.  
예를 들어, 다음 코드의 경우:  

```
querystring.stringify({ name: 'value', abc: ['xyz', '123'], anotherName: '' });
```
반환 값:  

```
'name=value&abc=xyz&abc=123&anotherName='
```
`querystring.encode()`는 `querystring.stringify()`의 별칭입니다.

`querystring.unescape(string)`  
지정된 `string`의 URL 백분율로 인코딩된 문자를 디코딩하여 이스케이프되지 않은 쿼리 문자열을 반환합니다. 이 방법은 `querystring.parse()`에서 사용되며 직접 사용해서는 안 됩니다.

## 제한된 기능
<a name="writing-functions-javascript-features-restricted-features"></a>

다음 JavaScript 언어 기능은 보안 문제로 인해 지원되지 않거나 제한됩니다.

**동적 코드 평가**  
동적 코드 평가는 지원되지 않습니다. 시도하면 `eval()` 및 `Function` 생성자 모두 오류가 발생합니다. 예를 들어 `const sum = new Function('a', 'b', 'return a + b')`에서 오류가 발생합니다.

**타이머**  
`setTimeout()`, `setImmediate()` 및 `clearTimeout()` 함수는 지원되지 않습니다. 함수 실행 내에서 연기하거나 출력할 프로비전이 없습니다. 함수가 완료되려면 동기적으로 실행되어야 합니다.

**날짜 및 타임스탬프**  
보안상의 이유로 고해상도 타이머에 액세스할 수 없습니다. 현재 시간을 쿼리하는 모든 `Date` 메서드는 단일 함수 실행의 수명 동안 항상 동일한 값을 반환합니다. 반환된 타임 스탬프는 함수가 실행을 시작한 시간입니다. 따라서 함수에서 경과 시간을 측정할 수 없습니다.

**파일 시스템 액세스**  
파일 시스템 액세스가 없습니다. 예를 들어 Node.js에서처럼 파일 시스템 액세스를 위한 `fs` 모듈이 없습니다.

**프로세스 액세스**  
프로세스 액세스가 없습니다. 예를 들어 Node.js와는 달리 정보 액세스를 처리하기 위한 `process` 글로벌 객체가 없습니다.

**환경 변수**  
환경 변수에 액세스할 수 없습니다.  
대신 CloudFront KeyValueStore를 사용하여 CloudFront Functions에 대한 키 값 페어의 중앙 집중식 데이터 스토어를 생성할 수 있습니다. CloudFront KeyValueStore를 사용하면 코드 변경 사항을 배포할 필요 없이 구성 데이터를 동적으로 업데이트할 수 있습니다. CloudFront KeyValueStore를 사용하려면 [JavaScript 런타임 2.0](functions-javascript-runtime-20.md)을 사용해야 합니다. 자세한 내용은 [Amazon CloudFront KeyValueStore](kvs-with-functions.md) 섹션을 참조하세요.

**네트워크 액세스**  
네트워크 통화에 대한 지원이 없습니다. 예를 들어 XHR, HTTP(S) 및 소켓은 지원되지 않습니다.

# CloudFront Functions를 위한 JavaScript 런타임 2.0 기능
<a name="functions-javascript-runtime-20"></a>

CloudFront Functions JavaScript 런타임 환경은 [ECMAScript(ES) 버전 5.1](https://262.ecma-international.org/5.1/)을 준수하며, ES 버전 6에서 12까지의 일부 기능을 지원합니다. 또한 ES 사양의 일부가 아닌 일부 비표준 방법을 제공합니다. 다음 주제에는 이 런타임에서 지원되는 모든 기능이 나열되어 있습니다.

**Topics**
+ [핵심 기능](#writing-functions-javascript-features-core-20)
+ [기본 객체](#writing-functions-javascript-features-primitive-objects-20)
+ [기본 제공 객체](#writing-functions-javascript-features-builtin-objects-20)
+ [오류 유형](#writing-functions-javascript-features-error-types-20)
+ [Globals](#writing-functions-javascript-features-globals-20)
+ [기본 제공 모듈](#writing-functions-javascript-features-builtin-modules-20)
+ [제한된 기능](#writing-functions-javascript-features-restricted-features-20)

## 핵심 기능
<a name="writing-functions-javascript-features-core-20"></a>

ES의 다음과 같은 핵심 기능이 지원됩니다.

**유형**  
모든 ES 5.1 유형이 지원됩니다. 여기에는 부울 값, 숫자, 문자열, 객체, 배열, 함수, 정규 표현식이 포함됩니다.

**연산자**  
모든 ES 5.1 연산자가 지원됩니다.  
ES 7 거듭제곱 연산자(`**`)가 지원됩니다.

**Statement**  
다음 ES 5.1 문이 지원됩니다.  
+ `break`
+ `catch`
+ `continue`
+ `do-while`
+ `else`
+ `finally`
+ `for`
+ `for-in`
+ `if`
+ `label`
+ `return`
+ `switch`
+ `throw`
+ `try`
+ `var`
+ `while`
다음 ES 6 문이 지원됩니다.  
+ `const`
+ `let`
다음 ES 8 문이 지원됩니다.  
+ `async`
+ `await`
`async`, `await`, `const` 및 `let`가 JavaScript 런타임 2.0에서 지원됩니다.  
`await`는 `async` 함수 내에서만 사용할 수 있습니다. `async` 인수 및 종료는 지원되지 않습니다.

**리터럴**  
ES 6 템플릿 리터럴은 여러 줄 문자열, 표현식 보간 및 중첩 템플릿에 대해 지원됩니다..

**함수**  
모든 ES 5.1 함수 기능이 지원됩니다.  
ES 6 화살표 함수가 지원되며 ES 6 나머지 파라미터 구문이 지원됩니다.

**유니코드**  
소스 텍스트 및 문자열 리터럴에는 유니코드로 인코딩된 문자가 포함될 수 있습니다. 6자의 유니코드 코드 포인트 이스케이프 시퀀스(예: `\uXXXX`)도 지원됩니다.

**엄격 모드**  
함수는 기본적으로 엄격 모드에서 작동하므로 함수 코드에 `use strict` 명령문을 추가할 필요가 없습니다. 이것은 변경할 수 없습니다.

## 기본 객체
<a name="writing-functions-javascript-features-primitive-objects-20"></a>

ES의 다음과 같은 기본 객체가 지원됩니다.

**객체**  
객체에 대해 다음과 같은 ES 5.1 메서드가 지원됩니다.  
+ `Object.create()`(속성 목록 제외)
+ `Object.defineProperties()`
+ `Object.defineProperty()`
+ `Object.freeze()`
+ `Object.getOwnPropertyDescriptor()`
+ `Object.getOwnPropertyDescriptors()`
+ `Object.getOwnPropertyNames()`
+ `Object.getPrototypeOf()`
+ `Object.isExtensible()`
+ `Object.isFrozen()`
+ `Object.isSealed()`
+ `Object.keys()`
+ `Object.preventExtensions()`
+ `Object.seal()`
객체에 대해 다음 ES 6 메서드가 지원됩니다.  
+ `Object.assign()`
객체에 대해 다음과 같은 ES 8 메서드가 지원됩니다.  
+ `Object.entries()`
+ `Object.values()`
객체에 대해 다음과 같은 ES 5.1 프로토타입 메서드가 지원됩니다.  
+ `Object.prototype.hasOwnProperty()`
+ `Object.prototype.isPrototypeOf()`
+ `Object.prototype.propertyIsEnumerable()`
+ `Object.prototype.toString()`
+ `Object.prototype.valueOf()`
객체에 대해 다음과 같은 ES 6 프로토타입 메서드가 지원됩니다.  
+ `Object.prototype.is()`
+ `Object.prototype.setPrototypeOf()`

**문자열**  
문자열에 대해 다음 ES 5.1 메서드가 지원됩니다.  
+ `String.fromCharCode()`
문자열에 대해 다음 ES 6 메서드가 지원됩니다.  
+ `String.fromCodePoint()`
문자열에 대해 다음 ES 5.1 프로토타입 메서드가 지원됩니다.  
+ `String.prototype.charAt()`
+ `String.prototype.concat()`
+ `String.prototype.indexOf()`
+ `String.prototype.lastIndexOf()`
+ `String.prototype.match()`
+ `String.prototype.replace()`
+ `String.prototype.search()`
+ `String.prototype.slice()`
+ `String.prototype.split()`
+ `String.prototype.substr()`
+ `String.prototype.substring()`
+ `String.prototype.toLowerCase()`
+ `String.prototype.trim()`
+ `String.prototype.toUpperCase()`
문자열에 대해 다음 ES 6 프로토타입 메서드가 지원됩니다.  
+ `String.prototype.codePointAt()`
+ `String.prototype.endsWith()`
+ `String.prototype.includes()`
+ `String.prototype.repeat()`
+ `String.prototype.startsWith()`
문자열에 대해 다음 ES 8 프로토타입 메서드가 지원됩니다.  
+ `String.prototype.padStart()`
+ `String.prototype.padEnd()`
문자열에 대해 다음 ES 9 프로토타입 메서드가 지원됩니다.  
+ `String.prototype.trimStart()`
+ `String.prototype.trimEnd()`
문자열에 대해 다음 ES 12 프로토타입 메서드가 지원됩니다.  
+ `String.prototype.replaceAll()`
**참고**  
`String.prototype.replaceAll()`이 JavaScript 런타임 2.0에 새로 추가되었습니다.

**숫자**  
모든 ES 5.1 숫자가 지원됩니다.  
숫자에 대해 다음 ES 6 속성이 지원됩니다.  
+ `Number.EPSILON`
+ `Number.MAX_SAFE_INTEGER`
+ `Number.MIN_SAFE_INTEGER`
+ `Number.MAX_VALUE`
+ `Number.MIN_VALUE`
+ `Number.NaN`
+ `Number.NEGATIVE_INFINITY`
+ `Number.POSITIVE_INFINITY`
숫자에 대해 다음 ES 6 메서드가 지원됩니다.  
+ `Number.isFinite()`
+ `Number.isInteger()`
+ `Number.isNaN()`
+ `Number.isSafeInteger()`
+ `Number.parseInt()`
+ `Number.parseFloat()`
숫자에 대해 다음 ES 5.1 프로토타입 메서드가 지원됩니다.  
+ `Number.prototype.toExponential()`
+ `Number.prototype.toFixed()`
+ `Number.prototype.toPrecision()`
ES 12 숫자 구분자가 지원됩니다.  
ES 12 숫자 구분자가 JavaScript 런타임 2.0에 새로 추가되었습니다.

## 기본 제공 객체
<a name="writing-functions-javascript-features-builtin-objects-20"></a>

ES의 다음 내장 객체가 지원됩니다.

**수학 연산**  
모든 ES 5.1 수학 메서드가 지원됩니다.  
CloudFront 함수 런타임 환경에서 `Math.random()` 구현은 함수가 실행될 때의 타임스탬프와 함께 시드된 OpenBSD `arc4random`을(를) 사용합니다.
다음 ES 6 수학 속성이 지원됩니다.  
+ `Math.E`
+ `Math.LN10`
+ `Math.LN2`
+ `Math.LOG10E`
+ `Math.LOG2E`
+ `Math.PI`
+ `Math.SQRT1_2`
+ `Math.SQRT2`
다음 ES 6 수학 메서드가 지원됩니다.  
+ `Math.abs()`
+ `Math.acos()`
+ `Math.acosh()`
+ `Math.asin()`
+ `Math.asinh()`
+ `Math.atan()`
+ `Math.atan2()`
+ `Math.atanh()`
+ `Math.cbrt()`
+ `Math.ceil()`
+ `Math.clz32()`
+ `Math.cos()`
+ `Math.cosh()`
+ `Math.exp()`
+ `Math.expm1()`
+ `Math.floor()`
+ `Math.fround()`
+ `Math.hypot()`
+ `Math.imul()`
+ `Math.log()`
+ `Math.log1p()`
+ `Math.log2()`
+ `Math.log10()`
+ `Math.max()`
+ `Math.min()`
+ `Math.pow()`
+ `Math.random()`
+ `Math.round()`
+ `Math.sign()`
+ `Math.sinh()`
+ `Math.sin()`
+ `Math.sqrt()`
+ `Math.tan()`
+ `Math.tanh()`
+ `Math.trunc()`

**날짜**  
모든 ES 5.1 `Date` 기능이 지원됩니다.  
보안상의 이유로 단일 함수 실행의 수명 동안 `Date`은(는) 항상 동일한 값(함수의 시작 시간)을 반환합니다. 자세한 내용은 [제한된 기능](functions-javascript-runtime-10.md#writing-functions-javascript-features-restricted-features) 단원을 참조하세요.

**함수**  
다음 ES 5.1 프로토타입 메서드가 지원됩니다.  
+ `Function.prototype.apply()`
+ `Function.prototype.bind()`
+ `Function.prototype.call()`
함수 생성자는 지원되지 않습니다.

**정규식**  
모든 ES 5.1 정규 표현식 기능이 지원됩니다. 정규 표현식 언어는 Perl과 호환됩니다.  
다음 ES 5.1 프로토타입 접근자 속성이 지원됩니다.  
+ `RegExp.prototype.global`
+ `RegExp.prototype.ignoreCase`
+ `RegExp.protoype.multiline`
+ `RegExp.protoype.source`
+ `RegExp.prototype.sticky`
+ `RegExp.prototype.flags`
**참고**  
`RegExp.prototype.sticky`, `RegExp.prototype.flags`가 JavaScript 런타임 2.0에 새로 추가되었습니다.
다음 ES 5.1 프로토타입 메서드가 지원됩니다.  
+ `RegExp.prototype.exec()`
+ `RegExp.prototype.test()`
+ `RegExp.prototype.toString()`
+ `RegExp.prototype[@@replace]()`
+ `RegExp.prototype[@@split]()`
**참고**  
`RegExp.prototype[@@split]()`이 JavaScript 런타임 2.0에 새로 추가되었습니다.
다음 ES 5.1 인스턴스 속성이 지원됩니다.  
+ `lastIndex`
ES 9 명명된 캡처 그룹이 지원됩니다.

**JSON**  
다음 ES 5.1 메서드가 지원됩니다.  
+ `JSON.parse()`
+ `JSON.stringify()`

**배열**  
배열에 대해 다음 ES 5.1 메서드가 지원됩니다.  
+ `Array.isArray()`
배열에 대해 다음 ES 6 메서드가 지원됩니다.  
+ `Array.of()`
다음 ES 5.1 프로토타입 메서드가 지원됩니다.  
+ `Array.prototype.concat()`
+ `Array.prototype.every()`
+ `Array.prototype.filter()`
+ `Array.prototype.forEach()`
+ `Array.prototype.indexOf()`
+ `Array.prototype.join()`
+ `Array.prototype.lastIndexOf()`
+ `Array.prototype.map()`
+ `Array.prototype.pop()`
+ `Array.prototype.push()`
+ `Array.prototype.reduce()`
+ `Array.prototype.reduceRight()`
+ `Array.prototype.reverse()`
+ `Array.prototype.shift()`
+ `Array.prototype.slice()`
+ `Array.prototype.some()`
+ `Array.prototype.sort()`
+ `Array.prototype.splice()`
+ `Array.prototype.unshift()`
다음 ES 6 프로토타입 메서드가 지원됩니다.  
+ `Array.prototype.copyWithin()`
+ `Array.prototype.fill()`
+ `Array.prototype.find()`
+ `Array.prototype.findIndex()`
다음 ES 7 프로토타입 메서드가 지원됩니다.  
+ `Array.prototype.includes()`

**형식화된 배열**  
다음 ES 6 형식화된 배열 생성자가 지원됩니다.  
+ `Float32Array`
+ `Float64Array`
+ `Int8Array`
+ `Int16Array`
+ `Int32Array`
+ `Uint8Array`
+ `Uint8ClampedArray`
+ `Uint16Array`
+ `Uint32Array`
다음 ES 6 메서드가 지원됩니다.  
+ `TypedArray.from()`
+ `TypedArray.of()`
**참고**  
`TypedArray.from()`, `TypedArray.of()`가 JavaScript 런타임 2.0에 새로 추가되었습니다.
다음 ES 6 프로토타입 메서드가 지원됩니다.  
+ `TypedArray.prototype.copyWithin()`
+ `TypedArray.prototype.every()`
+ `TypedArray.prototype.fill()`
+ `TypedArray.prototype.filter()`
+ `TypedArray.prototype.find()`
+ `TypedArray.prototype.findIndex()`
+ `TypedArray.prototype.forEach()`
+ `TypedArray.prototype.includes()`
+ `TypedArray.prototype.indexOf()`
+ `TypedArray.prototype.join()`
+ `TypedArray.prototype.lastIndexOf()`
+ `TypedArray.prototype.map()`
+ `TypedArray.prototype.reduce()`
+ `TypedArray.prototype.reduceRight()`
+ `TypedArray.prototype.reverse()`
+ `TypedArray.prototype.some()`
+ `TypedArray.prototype.set()`
+ `TypedArray.prototype.slice()`
+ `TypedArray.prototype.sort()`
+ `TypedArray.prototype.subarray()`
+ `TypedArray.prototype.toString()`
**참고**  
`TypedArray.prototype.every()`, `TypedArray.prototype.fill()`, `TypedArray.prototype.filter()`, `TypedArray.prototype.find()`, `TypedArray.prototype.findIndex()`, `TypedArray.prototype.forEach()`, `TypedArray.prototype.includes()`, `TypedArray.prototype.indexOf()`, `TypedArray.prototype.join()`, `TypedArray.prototype.lastIndexOf()`, `TypedArray.prototype.map()`, `TypedArray.prototype.reduce()`, `TypedArray.prototype.reduceRight()`, `TypedArray.prototype.reverse()`, `TypedArray.prototype.some()`이 JavaScript 런타임 2.0에 새로 추가되었습니다.

**배열 버퍼**  
ArrayBuffer에 대해 다음 ES 6 메서드가 지원됩니다.  
+ `isView()`
ArrayBuffer에 대해 다음 ES 6 프로토타입 메서드가 지원됩니다.  
+ `ArrayBuffer.prototype.slice()`

**Promise**  
프로미스에 대해 다음 ES 6 메서드가 지원됩니다.  
+ `Promise.all()`
+ `Promise.allSettled()`
+ `Promise.any()`
+ `Promise.reject()`
+ `Promise.resolve()`
+ `Promise.race()`
**참고**  
`Promise.all()`, `Promise.allSettled()`, `Promise.any()`, `Promise.race()`가 JavaScript 런타임 2.0에 새로 추가되었습니다.
프로미스에 대해 다음 ES 6 프로토타입 메서드가 지원됩니다.  
+ `Promise.prototype.catch()`
+ `Promise.prototype.finally()`
+ `Promise.prototype.then()`

**DataView**  
다음 ES 6 프로토타입 메서드가 지원됩니다.  
+ `DataView.prototype.getFloat32()`
+ `DataView.prototype.getFloat64()`
+ `DataView.prototype.getInt16()`
+ `DataView.prototype.getInt32()`
+ `DataView.prototype.getInt8()`
+ `DataView.prototype.getUint16()`
+ `DataView.prototype.getUint32()`
+ `DataView.prototype.getUint8()`
+ `DataView.prototype.setFloat32()`
+ `DataView.prototype.setFloat64()`
+ `DataView.prototype.setInt16()`
+ `DataView.prototype.setInt32()`
+ `DataView.prototype.setInt8()`
+ `DataView.prototype.setUint16()`
+ `DataView.prototype.setUint32()`
+ `DataView.prototype.setUint8()`
**참고**  
모든 Dataview ES 6 프로토타입 메서드가 JavaScript 런타임 2.0에 새로 추가되었습니다.

**Symbol**  
다음 ES 6 메서드가 지원됩니다.  
+ `Symbol.for()`
+ `Symbol.keyfor()`
**참고**  
모든 Symbol ES 6 메서드가 JavaScript 런타임 2.0에 새로 추가되었습니다.

**텍스트 디코더**  
다음 프로토타입 메서드가 지원됩니다.  
+ `TextDecoder.prototype.decode()`
다음 프로토타입 접근자 속성이 지원됩니다.  
+ `TextDecoder.prototype.encoding`
+ `TextDecoder.prototype.fatal`
+ `TextDecoder.prototype.ignoreBOM`

**텍스트 인코더**  
다음 프로토타입 메서드가 지원됩니다.  
+ `TextEncoder.prototype.encode()`
+ `TextEncoder.prototype.encodeInto()`

## 오류 유형
<a name="writing-functions-javascript-features-error-types-20"></a>

다음과 같은 오류 객체가 지원됩니다.
+ `Error`
+ `EvalError`
+ `InternalError`
+ `RangeError`
+ `ReferenceError`
+ `SyntaxError`
+ `TypeError`
+ `URIError`

## Globals
<a name="writing-functions-javascript-features-globals-20"></a>

`globalThis` 객체가 지원됩니다.

다음 ES 5.1 전역 함수가 지원됩니다.
+ `decodeURI()`
+ `decodeURIComponent()`
+ `encodeURI()`
+ `encodeURIComponent()`
+ `isFinite()`
+ `isNaN()`
+ `parseFloat()`
+ `parseInt()`

다음 ES 6 전역 함수가 지원됩니다.
+ `atob()`
+ `btoa()`
**참고**  
`atob()`, `btoa()`가 JavaScript 런타임 2.0에 새로 추가되었습니다.

다음과 같은 글로벌 제약이 지원됩니다.
+ `NaN`
+ `Infinity`
+ `undefined`
+ `arguments`

## 기본 제공 모듈
<a name="writing-functions-javascript-features-builtin-modules-20"></a>

다음 기본 제공 모듈이 지원됩니다.

**Topics**
+ [Buffer](#writing-functions-javascript-features-builtin-modules-buffer-20)
+ [쿼리 문자열](#writing-functions-javascript-features-builtin-modules-query-string-20)
+ [crypto](#writing-functions-javascript-features-builtin-modules-crypto-20)

### Buffer
<a name="writing-functions-javascript-features-builtin-modules-buffer-20"></a>

이 모듈은 다음과 같은 메서드를 제공합니다.
+ `Buffer.alloc(size[, fill[, encoding]])`

  `Buffer`를 할당합니다.
  + `size`: 버퍼 크기입니다. 정수를 입력합니다.
  + `fill`: 선택 사항입니다. 문자열, `Buffer`, Uint8Array 또는 정수를 입력합니다. 기본값은 `0`입니다.
  + `encoding`: 선택 사항입니다. `fill`이 문자열인 경우 `utf8`, `hex`, `base64`, `base64url` 중 하나를 입력합니다. 기본값은 `utf8`입니다.
+ `Buffer.allocUnsafe(size)`

  초기화되지 않은 `Buffer` 값을 할당합니다.
  + `size`: 정수를 입력합니다.
+ `Buffer.byteLength(value[, encoding])`

  값의 길이를 바이트 단위로 반환합니다.
  + `value`: 문자열, `Buffer`, TypedArray, Dataview 또는 Arraybuffer입니다.
  + `encoding`: 선택 사항입니다. `value`가 문자열인 경우 `utf8`, `hex`, `base64`, `base64url` 중 하나를 입력합니다. 기본값은 `utf8`입니다.
+ `Buffer.compare(buffer1, buffer2)`

  두 `Buffer`를 비교하면 배열을 정렬하는 데 도움이 됩니다. 두 값이 같으면 `0`, `buffer1`이 먼저 오면 `-1`, `buffer2`가 먼저 오면 `1`을 반환합니다.
  + `buffer1`: `Buffer`를 입력합니다.
  + `buffer2`: 다른 `Buffer`를 입력합니다.
+ `Buffer.concat(list[, totalLength])`

  여러 개의 `Buffer`를 연결합니다. 없으면 `0`을 반환합니다. `totalLength`까지 반환합니다.
  + `list`: `Buffer` 목록을 입력합니다. 이 항목은 `totalLength` 기준으로 잘려서 표시된다는 점에 유의하세요.
  + `totalLength`: 선택 사항입니다. 부호 없는 정수를 입력합니다. 비어 있는 경우 목록에 있는 `Buffer` 인스턴스의 합계를 사용하세요.
+ `Buffer.from(array)`

  배열에서 `Buffer`를 생성합니다.
  + `array`: `0`에서 `255`까지 바이트 배열을 입력합니다.
+ `Buffer.from(arrayBuffer, byteOffset[, length]))`

  `byteOffset` 오프셋에서 시작하여 `length` 길이를 기준으로 `arrayBuffer`에서 뷰를 생성합니다.
  + `arrayBuffer`: `Buffer` 배열을 입력합니다.
  + `byteOffset`: 정수를 입력합니다.
  + `length`: 선택 사항입니다. 정수를 입력합니다.
+ `Buffer.from(buffer)`

  `Buffer`의 사본을 생성합니다.
  + `buffer`: `Buffer`를 입력합니다.
+ `Buffer.from(object[, offsetOrEncoding[, length]])`

  객체에서 `Buffer`를 생성합니다. `valueOf()` 값이 객체와 동일하지 않으면 `Buffer.from(object.valueOf(), offsetOrEncoding, length)` 값을 반환합니다.
  + `object`: 객체를 입력합니다.
  + `offsetOrEncoding`: 선택 사항입니다. 정수 또는 인코딩 문자열을 입력합니다.
  + `length`: 선택 사항입니다. 정수를 입력합니다.
+ `Buffer.from(string[, encoding])`

  문자열에서 `Buffer`를 생성합니다.
  + `string`: 문자열을 입력합니다.
  + `encoding`: 선택 사항입니다. `utf8`, `hex`, `base64`, `base64url` 중 하나를 입력합니다. 기본값은 `utf8`입니다.
+ `Buffer.isBuffer(object)`

  `object`가 버퍼인지 확인합니다. `true` 또는 `false`를 반환합니다.
  + `object`: 객체를 입력합니다.
+ `Buffer.isEncoding(encoding)`

  `encoding`이 지원되는지 확인합니다. `true` 또는 `false`를 반환합니다.
  + `encoding`: 선택 사항입니다. `utf8`, `hex`, `base64`, `base64url` 중 하나를 입력합니다. 기본값은 `utf8`입니다.

이 모듈은 다음과 같은 버퍼 프로토타입 메서드를 제공합니다.
+ `Buffer.prototype.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])`

  `Buffer`를 대상과 비교합니다. 두 값이 같으면 `0`, `buffer`이 먼저 오면 `1`, `target`가 먼저 오면 `-1`을 반환합니다.
  + `target`: `Buffer`를 입력합니다.
  + `targetStart`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.
  + `targetEnd`: 선택 사항입니다. 정수를 입력합니다. 기본값은 `target` 길이입니다.
  + `sourceStart`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.
  + `sourceEnd`: 선택 사항입니다. 정수를 입력합니다. 기본값은 `Buffer` 길이입니다.
+ `Buffer.prototype.copy(target[, targetStart[, sourceStart[, sourceEnd]]])`

  버퍼를 `target`으로 복사합니다.
  + `target`: `Buffer` 또는 `Uint8Array`를 입력합니다.
  + `targetStart`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.
  + `sourceStart`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.
  + `sourceEnd`: 선택 사항입니다. 정수를 입력합니다. 기본값은 `Buffer` 길이입니다.
+ `Buffer.prototype.equals(otherBuffer)`

  `Buffer`와 `otherBuffer`를 비교합니다. `true` 또는 `false`를 반환합니다.
  + `otherBuffer`: 문자열을 입력합니다.
+ `Buffer.prototype.fill(value[, offset[, end][, encoding])`

  `Buffer`를 `value`로 채웁니다.
  + `value`: 문자열, `Buffer` 또는 정수를 입력합니다.
  + `offset`: 선택 사항입니다. 정수를 입력합니다.
  + `end`: 선택 사항입니다. 정수를 입력합니다.
  + `encoding`: 선택 사항입니다. `utf8`, `hex`, `base64`, `base64url` 중 하나를 입력합니다. 기본값은 `utf8`입니다.
+ `Buffer.prototype.includes(value[, byteOffset][, encoding])`

  `Buffer`에서 `value`를 찾습니다. `true` 또는 `false`를 반환합니다.
  + `value`: 문자열, `Buffer`, `Uint8Array` 또는 정수를 입력합니다.
  + `byteOffset`: 선택 사항입니다. 정수를 입력합니다.
  + `encoding`: 선택 사항입니다. `utf8`, `hex`, `base64`, `base64url` 중 하나를 입력합니다. 기본값은 `utf8`입니다.
+ `Buffer.prototype.indexOf(value[, byteOffset][, encoding])`

  `Buffer`에서 첫 번째 `value`를 찾습니다. 값이 발견되면 `index`, 발견되지 않으면 `-1`을 반환합니다.
  + `value`: 문자열, `Buffer`, Unit8Array 또는 0에서 255 사이의 정수를 입력합니다.
  + `byteOffset`: 선택 사항입니다. 정수를 입력합니다.
  + `encoding`: 선택 사항입니다. `value`가 문자열인 경우 `utf8`, `hex`, `base64`, `base64url` 중 하나를 입력합니다. 기본값은 `utf8`입니다.
+ `Buffer.prototype.lastIndexOf(value[, byteOffset][, encoding])`

  `Buffer`에서 마지막 `value`를 찾습니다. 값이 발견되면 `index`, 발견되지 않으면 `-1`을 반환합니다.
  + `value`: 문자열, `Buffer`, Unit8Array 또는 0에서 255 사이의 정수를 입력합니다.
  + `byteOffset`: 선택 사항입니다. 정수를 입력합니다.
  + `encoding`: 선택 사항입니다. `value`가 문자열인 경우 `utf8`, `hex`, `base64`, `base64url` 중 하나를 입력합니다. 기본값은 `utf8`입니다.
+ `Buffer.prototype.readInt8(offset)`

  `Buffer`의 `offset`에서 `Int8`을 읽습니다.
  + `offset`: 정수를 입력합니다.
+ `Buffer.prototype.readIntBE(offset, byteLength)`

  `Buffer`의 `offset`에서 `Int`를 빅 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: 선택 사항입니다. `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.readInt16BE(offset)`

  `Buffer`의 `offset`에서 `Int16`을 빅 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
+ `Buffer.prototype.readInt32BE(offset)`

  `Buffer`의 `offset`에서 `Int32`를 빅 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
+ `Buffer.prototype.readIntLE(offset, byteLength)`

  `Buffer`의 `offset`에서 `Int`를 리틀 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.readInt16LE(offset)`

  `Buffer`의 `offset`에서 `Int16`을 리틀 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
+ `Buffer.prototype.readInt32LE(offset)`

  `Buffer`의 `offset`에서 `Int32`을 리틀 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
+ `Buffer.prototype.readUInt8(offset)`

  `Buffer`의 `offset`에서 `UInt8`을 읽습니다.
  + `offset`: 정수를 입력합니다.
+ `Buffer.prototype.readUIntBE(offset, byteLength)`

  `Buffer`의 `offset`에서 `UInt`를 빅 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.readUInt16BE(offset)`

  `Buffer`의 `offset`에서 `UInt16`을 빅 엔디안으로 읽습니다.
+ 
  + `offset`: 정수를 입력합니다.
+ `Buffer.prototype.readUInt32BE(offset)`

  `Buffer`의 `offset`에서 `UInt32`를 빅 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
+ `Buffer.prototype.readUIntLE(offset, byteLength)`

  `Buffer`의 `offset`에서 `UInt`을 리틀 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.readUInt16LE(offset)`

  `Buffer`의 `offset`에서 `UInt16`을 리틀 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
+ `Buffer.prototype.readUInt32LE(offset)`

  `Buffer`의 `offset`에서 `UInt32`을 리틀 엔디안으로 읽습니다.
  + `offset`: 정수를 입력합니다.
+ `Buffer.prototype.readDoubleBE([offset])`

  `Buffer`의 `offset`에서 64비트 배정도를 빅 엔디안으로 읽습니다.
  + `offset`: 선택 사항입니다. 정수를 입력합니다.
+ `Buffer.prototype.readDoubleLE([offset])`

  `Buffer`의 `offset`에서 64비트 배정도를 리틀 엔디안으로 읽습니다.
  + `offset`: 선택 사항입니다. 정수를 입력합니다.
+ `Buffer.prototype.readFloatBE([offset])`

  `Buffer`의 `offset`에서 32비트 부동소수점을 빅 엔디안으로 읽습니다.
  + `offset`: 선택 사항입니다. 정수를 입력합니다.
+ `Buffer.prototype.readFloatLE([offset])`

  `Buffer`의 `offset`에서 32비트 부동소수점을 리틀 엔디안으로 읽습니다.
  + `offset`: 선택 사항입니다. 정수를 입력합니다.
+ `Buffer.prototype.subarray([start[, end]])`

  오프셋되고 새 `start` 및 `end`로 크롭된 `Buffer`의 복사본을 반환합니다.
  + `start`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.
  + `end`: 선택 사항입니다. 정수를 입력합니다. 기본값은 버퍼 길이입니다.
+ `Buffer.prototype.swap16()`

  `Buffer` 배열을 16비트 숫자로 구성된 배열로 취급하여 바이트 순서를 바꿉니다. `Buffer` 길이는 2로 나눌 수 있어야 합니다. 그렇지 않으면 오류가 발생합니다.
+ `Buffer.prototype.swap32()`

  `Buffer` 배열을 32비트 숫자로 구성된 배열로 취급하여 바이트 순서를 바꿉니다. `Buffer` 길이는 4로 나눌 수 있어야 합니다. 그렇지 않으면 오류가 발생합니다.
+ `Buffer.prototype.swap64()`

  `Buffer` 배열을 64비트 숫자로 구성된 배열로 취급하여 바이트 순서를 바꿉니다. `Buffer` 길이는 8로 나눌 수 있어야 합니다. 그렇지 않으면 오류가 발생합니다.
+ `Buffer.prototype.toJSON()`

  `Buffer`를 JSON으로 반환합니다.
+ `Buffer.prototype.toString([encoding[, start[, end]]])`

  `start`에서 `end`로, 인코딩된 문자열로 `Buffer`를 변환합니다.
  + `encoding`: 선택 사항입니다. `utf8`, `hex`, `base64`, `base64url` 중 하나를 입력합니다. 기본값은 `utf8`입니다.
  + `start`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.
  + `end`: 선택 사항입니다. 정수를 입력합니다. 기본값은 버퍼 길이입니다.
+ `Buffer.prototype.write(string[, offset[, length]][, encoding])`

  공간이 있는 경우 인코딩된 `string`을 `Buffer`에 쓰고, 공간이 충분하지 않으면 잘라낸 `string`을 씁니다.
  + `string`: 문자열을 입력합니다.
  + `offset`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.
  + `length`: 선택 사항입니다. 정수를 입력합니다. 기본값은 문자열 길이입니다.
  + `encoding`: 선택 사항입니다. 필요에 따라 `utf8`, `hex`, `base64`, `base64url` 중 하나를 입력합니다. 기본값은 `utf8`입니다.
+ `Buffer.prototype.writeInt8(value, offset, byteLength)`

  `offset`에서 `byteLength`의 `Int8` `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeIntBE(value, offset, byteLength)`

  빅 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeInt16BE(value, offset, byteLength)`

  빅 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeInt32BE(value, offset, byteLength)`

  빅 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeIntLE(offset, byteLength)`

  리틀 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeInt16LE(offset, byteLength)`

  리틀 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeInt32LE(offset, byteLength)`

  리틀 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeUInt8(value, offset, byteLength)`

  `offset`에서 `byteLength`의 `UInt8` `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeUIntBE(value, offset, byteLength)`

  빅 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeUInt16BE(value, offset, byteLength)`

  빅 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeUInt32BE(value, offset, byteLength)`

  빅 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeUIntLE(value, offset, byteLength)`

  리틀 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeUInt16LE(value, offset, byteLength)`

  리틀 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeUInt32LE(value, offset, byteLength)`

  리틀 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 정수를 입력합니다.
  + `byteLength`: `1`에서 `6`까지의 정수를 입력합니다.
+ `Buffer.prototype.writeDoubleBE(value, [offset])`

  빅 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.
+ `Buffer.prototype.writeDoubleLE(value, [offset])`

  리틀 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.
+ `Buffer.prototype.writeFloatBE(value, [offset])`

  빅 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.
+ `Buffer.prototype.writeFloatLE(value, [offset])`

  리틀 엔디안을 사용하여 `offset`에서 `value`를 `Buffer`에 씁니다.
  + `value`: 정수를 입력합니다.
  + `offset`: 선택 사항입니다. 정수를 입력합니다. 기본값은 0.

다음 인스턴스 메서드가 지원됩니다.
+ `buffer[index]`

  `Buffer`에 `index`의 8진수(바이트)를 가져와 설정합니다.
  + `0`에서 `255`의 숫자를 가져옵니다. 또는 `0`부터 `255`까지의 숫자를 설정할 수도 있습니다.

다음 인스턴스 속성이 지원됩니다.
+ `buffer`

  버퍼의 `ArrayBuffer` 객체를 가져옵니다.
+ `byteOffset`

  버퍼의 `Arraybuffer` 객체에 대한 `byteOffset`을 가져옵니다.
+ `length`

  버퍼 바이트 수를 가져옵니다.

**참고**  
모든 버퍼 모듈 메서드가 JavaScript 런타임 2.0에 새로 추가되었습니다.

### 쿼리 문자열
<a name="writing-functions-javascript-features-builtin-modules-query-string-20"></a>

**참고**  
[CloudFront 함수 이벤트 객체](functions-event-structure.md)는 URL 쿼리 문자열을 자동으로 구문 분석합니다. 즉, 대부분의 경우 이 모듈을 사용할 필요가 없습니다.

쿼리 문자열 모듈(`querystring`)은 URL 쿼리 문자열을 구문 분석하고 서식을 지정하는 메서드를 제공합니다. `require('querystring')`을 사용하여 모듈을 로드할 수 있습니다. 이 모듈은 다음과 같은 방법을 제공합니다.

`querystring.escape(string)`  
지정된 `string`을 URL-인코딩하여 이스케이프된 쿼리 문자열을 반환합니다. 이 방법은 `querystring.stringify()`에서 사용되며 직접 사용해서는 안 됩니다.

`querystring.parse(string[, separator[, equal[, options]]])`  
쿼리 문자열(`string`)을 구문 분석하고 객체를 반환합니다.  
`separator` 파라미터는 쿼리 문자열에서 키와 값 페어를 구분하기 위한 하위 문자열입니다. 기본 설정은 `&`입니다.  
`equal` 파라미터는 쿼리 문자열에서 키와 값을 구분하기 위한 하위 문자열입니다. 기본 설정은 `=`입니다.  
`options` 파라미터는 다음 키를 가진 객체입니다.    
`decodeURIComponent function`  
쿼리 문자열에서 백분율로 인코딩된 문자를 디코딩하는 함수입니다. 기본 설정은 `querystring.unescape()`입니다.  
`maxKeys number`  
구문 분석할 최대 키 수입니다. 기본 설정은 `1000`입니다. `0` 값을 사용하여 키 카운트 제한을 제거합니다.
기본적으로 쿼리 문자열 내의 백분율로 인코딩된 문자는 UTF-8 인코딩을 사용하는 것으로 간주됩니다. 잘못된 UTF-8 시퀀스는 `U+FFFD` 대체 문자로 대체됩니다.  
예를 들어 다음 쿼리 문자열의 경우:  

```
'name=value&abc=xyz&abc=123'
```
`querystring.parse()`의 반환 값:  

```
{
name: 'value',
abc: ['xyz', '123']
}
```
`querystring.decode()`는 `querystring.parse()`의 별칭입니다.

`querystring.stringify(object[, separator[, equal[, options]]])`  
`object`를 직렬화하고 쿼리 문자열을 반환합니다.  
`separator` 파라미터는 쿼리 문자열에서 키와 값 쌍을 구분하기 위한 하위 문자열입니다. 기본 설정은 `&`입니다.  
`equal` 파라미터는 쿼리 문자열에서 키와 값을 구분하기 위한 하위 문자열입니다. 기본 설정은 `=`입니다.  
`options` 파라미터는 다음 키를 가진 객체입니다.    
`encodeURIComponent function`  
URL에 안전하지 않은 문자를 쿼리 문자열에서 백분율 인코딩으로 변환하는 데 사용할 함수입니다. 기본 설정은 `querystring.escape()`입니다.
기본적으로 쿼리 문자열 내에서 백분율 인코딩이 필요한 문자는 UTF-8로 인코딩됩니다. 다른 인코딩을 사용하려면 `encodeURIComponent` 옵션을 지정합니다.  
예를 들어, 다음 코드의 경우:  

```
querystring.stringify({ name: 'value', abc: ['xyz', '123'], anotherName: '' });
```
반환 값:  

```
'name=value&abc=xyz&abc=123&anotherName='
```
`querystring.encode()`는 `querystring.stringify()`의 별칭입니다.

`querystring.unescape(string)`  
지정된 `string`의 URL 백분율로 인코딩된 문자를 디코딩하여 이스케이프되지 않은 쿼리 문자열을 반환합니다. 이 방법은 `querystring.parse()`에서 사용되며 직접 사용해서는 안 됩니다.

### crypto
<a name="writing-functions-javascript-features-builtin-modules-crypto-20"></a>

암호화 모듈(`crypto`)은 표준 해싱 및 HMAC(해시 기반 메시지 인증 코드) 헬퍼를 제공합니다. `require('crypto')`을(를) 사용하여 모듈을 로드할 수 있습니다.

**해싱 메서드**

`crypto.createHash(algorithm)`  
지정된 알고리즘(`md5`, `sha1` 또는 `sha256`)을 사용하여 해시 다이제스트를 생성하는 데 사용할 수 있는 해시 객체를 생성하고 반환합니다.

`hash.update(data)`  
지정된 `data`(으)로 해시 콘텐츠를 업데이트합니다.

`hash.digest([encoding])`  
`hash.update()`을(를) 사용하여 전달된 모든 데이터의 다이제스트를 계산합니다. 인코딩은 `hex`, `base64` 또는 `base64url`일 수 있습니다.

**HMAC 메서드**

`crypto.createHmac(algorithm, secret key)`  
지정된 `algorithm` 및 `secret key`을(를) 사용하는 HMAC 객체를 생성 및 반환합니다. 알고리즘은 `md5`, `sha1` 또는 `sha256`일 수 있습니다.

`hmac.update(data)`  
지정된 `data`(으)로 HMAC 콘텐츠를 업데이트합니다.

`hmac.digest([encoding])`  
`hmac.update()`을(를) 사용하여 전달된 모든 데이터의 다이제스트를 계산합니다. 인코딩은 `hex`, `base64` 또는 `base64url`일 수 있습니다.

## 제한된 기능
<a name="writing-functions-javascript-features-restricted-features-20"></a>

다음 JavaScript 언어 기능은 보안 문제로 인해 지원되지 않거나 제한됩니다.

**동적 코드 평가**  
동적 코드 평가는 지원되지 않습니다. 시도하면 `eval()` 및 `Function` 생성자 모두 오류가 발생합니다. 예를 들어 `const sum = new Function('a', 'b', 'return a + b')`에서 오류가 발생합니다.

**타이머**  
`setTimeout()`, `setImmediate()` 및 `clearTimeout()` 함수는 지원되지 않습니다. 함수 실행 내에서 연기하거나 출력할 프로비전이 없습니다. 함수가 완료되려면 동기적으로 실행되어야 합니다.

**날짜 및 타임스탬프**  
보안상의 이유로 고해상도 타이머에 액세스할 수 없습니다. 현재 시간을 쿼리하는 모든 `Date` 메서드는 단일 함수 실행의 수명 동안 항상 동일한 값을 반환합니다. 반환된 타임 스탬프는 함수가 실행을 시작한 시간입니다. 따라서 함수에서 경과 시간을 측정할 수 없습니다.

**파일 시스템 액세스**  
파일 시스템 액세스가 없습니다. 예를 들어 Node.js에서처럼 파일 시스템 액세스를 위한 `fs` 모듈이 없습니다.

**프로세스 액세스**  
프로세스 액세스가 없습니다. 예를 들어 Node.js와는 달리 정보 액세스를 처리하기 위한 `process` 글로벌 객체가 없습니다.

**환경 변수**  
환경 변수에 액세스할 수 없습니다. 대신 CloudFront KeyValueStore를 사용하여 CloudFront Functions에 대한 키 값 페어의 중앙 집중식 데이터 스토어를 생성할 수 있습니다. CloudFront KeyValueStore를 사용하면 코드 변경 사항을 배포할 필요 없이 구성 데이터를 동적으로 업데이트할 수 있습니다. 자세한 내용은 [Amazon CloudFront KeyValueStore](kvs-with-functions.md) 섹션을 참조하세요.

**네트워크 액세스**  
네트워크 통화에 대한 지원이 없습니다. 예를 들어 XHR, HTTP(S) 및 소켓은 지원되지 않습니다.

# 키 값 저장소를 위한 도우미 메서드
<a name="functions-custom-methods"></a>

**참고**  
CloudFront Functions의 키 값 저장소 헬퍼 메서드 호출은 AWS CloudTrail 데이터 이벤트를 트리거하지 않습니다. 이러한 이벤트는 CloudTrail 이벤트 기록에 로그되지 않습니다. 자세한 내용은 [AWS CloudTrail을 사용하여 Amazon CloudFront API 직접 호출 로깅](logging_using_cloudtrail.md) 섹션을 참조하세요.

이 섹션은 생성한 함수에 [CloudFront 키 값 저장소](kvs-with-functions.md)를 사용하여 키 값을 포함하는 경우에 적용됩니다. CloudFront Functions에는 키 값 저장소에서 값을 읽을 수 있는 세 가지 도우미 메서드를 제공하는 모듈이 있습니다.

함수 코드에서 이 모듈을 사용하려면 [키 값 저장소를 함수와 연결](kvs-with-functions-associate.md)했는지 확인합니다.

그런 다음 함수 코드의 첫 줄에 다음 명령문을 포함시킵니다.

```
import cf from 'cloudfront';
const kvsHandle = cf.kvs();
```



## `get()` 메서드
<a name="functions-custom-methods-get"></a>

이 메서드를 사용하여 지정한 키 이름의 키 값을 반환합니다.

**요청**

```
get("key", options);
```
+ `key`: 값을 가져와야 하는 키의 이름입니다.
+ `options`: 한 가지 옵션으로 `format`이 있습니다. 이 옵션을 사용하면 함수가 데이터를 올바르게 파싱합니다. 가능한 값은 다음과 같습니다.
  + `string`: (기본값) UTF8 인코딩
  + `json` 
  + `bytes`: 원시 바이너리 데이터 버퍼

**요청 예제**

```
const value = await kvsHandle.get("myFunctionKey", { format: "string"});
```

**응답**

응답은 `options`를 사용하여 요청한 형식의 값으로 해석되는 `promise`입니다. 기본적으로 값은 문자열로 반환됩니다.

### 오류 처리
<a name="error-handling-exists-method"></a>

요청된 키가 관련 키 값 저장소에 존재하지 않는 경우 `get()` 메서드는 오류를 반환합니다. 이 사용 사례를 관리하기 위해 코드에 `try` 및 `catch` 블록을 추가할 수 있습니다.

**주의**  
promise 결합자(예: `Promise.all`, `Promise.any`) 및 promise 체인 메서드(예: `then` 및 `catch`)를 사용하려면 많은 함수 메모리 사용량이 필요할 수 있습니다. 함수가 [최대 함수 메모리](cloudfront-limits.md#limits-functions) 할당량을 초과하면 실행에 실패합니다. 이 오류를 방지하려면 `await` 구문을 순차적으로 사용하거나 루프에서 여러 값을 요청하는 것이 좋습니다.  
**예제**  

```
var value1 = await kvs.get('key1');
var value2 = await kvs.get('key2');
```
현재 다음 예제와 같이 promise 결합자를 사용하여 여러 값을 가져오더라도 성능이 향상되지 않습니다.  

```
var values = await Promise.all([kvs.get('key1'), kvs.get('key2'),]);
```

## `exists()` 메서드
<a name="functions-custom-methods-exists"></a>

키가 키 값 저장소에 존재하는지 여부를 지정하려면 이 메서드를 사용합니다.

**요청**

```
exists("key");
```

**요청 예제**

```
const exist = await kvsHandle.exists("myFunctionkey");
```

**응답**

응답은 부울(`true` 또는 `false`)을 반환하는 `promise`입니다. 이 값은 키가 키 값 저장소에 존재하는지 여부를 지정합니다.

## `meta()` 메서드
<a name="functions-custom-methods-meta"></a>

이 메서드를 사용하여 키 값 저장소에 대한 메타데이터를 반환합니다.

**요청**

```
meta();
```

**요청 예제**

```
const meta = await kvsHandle.meta();
```

**응답**

응답은 다음과 같은 속성을 가진 객체로 확인되는 `promise`입니다.
+ `creationDateTime`: 키 값 저장소가 생성된 ISO 8601 형식의 날짜 및 시간입니다.
+ `lastUpdatedDateTime`: 키 값 저장소가 소스에서 마지막으로 동기화된 ISO 8601 형식의 날짜 및 시간입니다. 엣지로의 전파 시간은 값에 포함되지 않습니다.
+ `keyCount`: 소스와의 마지막 동기화 이후 KVS에 있는 키의 총 개수입니다.

**응답 예제**

```
{keyCount:3,creationDateTime:2023-11-30T23:07:55.765Z,lastUpdatedDateTime:2023-12-15T03:57:52.411Z}
```

# 오리진 수정용 헬퍼 메서드
<a name="helper-functions-origin-modification"></a>

이 섹션은 CloudFront Functions 코드 내에서 요청에 사용되는 오리진을 동적으로 업데이트하거나 변경하는 경우에 적용됩니다. *뷰어 요청* CloudFront Functions에서만 오리진을 업데이트할 수 있습니다. CloudFront Functions에는 오리진을 동적으로 업데이트하거나 변경하는 헬퍼 메서드를 제공하는 모듈이 있습니다.

이 모듈을 사용하려면 JavaScript 런타임 2.0을 사용하여 CloudFront Functions을 만들고 함수 코드의 첫 번째 줄에 다음 스테이트먼트를 포함합니다.

```
import cf from 'cloudfront';
```

자세한 내용은 [CloudFront Functions를 위한 JavaScript 런타임 2.0 기능](functions-javascript-runtime-20.md) 섹션을 참조하세요.

**참고**  
테스트 API 및 테스트 콘솔 페이지에서는 오리진 수정이 발생했는지 여부를 테스트하지 않습니다. 그러나 테스트는 함수 코드가 오류 없이 실행되도록 합니다.

## CloudFront Functions과 Lambda@Edge 중에서 선택
<a name="origin-modification-considerations"></a>

CloudFront Functions 또는 Lambda@Edge를 사용하여 오리진을 업데이트할 수 있습니다.

CloudFront Functions을 사용하여 오리진을 업데이트할 때 *뷰어 요청* 이벤트 트리거를 사용합니다. 즉, 이 함수가 사용될 때 해당 로직이 모든 요청에서 실행됩니다. Lambda@Edge를 사용하는 경우 오리진 업데이트 기능은 *오리진 요청* 이벤트 트리거에 존재합니다. 즉, 이 로직은 캐시 누락에서만 실행됩니다.

주로 워크로드와 배포에서 CloudFront Functions 및 Lambda@Edge의 기존 사용량에 따라 선택이 달라집니다. 다음 고려 사항을 통해 CloudFront Functions 또는 Lambda@Edge를 사용하여 오리진을 업데이트할지 여부를 결정할 수 있습니다.

CloudFront Functions은 다음과 같은 상황에서 가장 유용합니다.
+ 요청이 동적(즉, 캐싱할 수 없음)이고 항상 오리진으로 이동하는 경우입니다. CloudFront Functions은 더 나은 성능과 더 낮은 전체 비용을 제공합니다.
+ 각 요청에서 실행되는 기존 뷰어 요청 CloudFront Functions이 이미 있는 경우 기존 함수에 오리진 업데이트 로직을 추가할 수 있습니다.

CloudFront Functions을 사용하여 오리진을 업데이트하려면 다음 주제의 헬퍼 메서드를 참조하시기 바랍니다.

Lambda@Edge는 다음과 같은 상황에서 가장 유용합니다.
+ 캐싱 가능성이 높은 콘텐츠가 있으면 Lambda@Edge는 캐시 누락 시에만 실행되고 CloudFront Functions은 모든 요청 시 실행되므로 더 비용 효율적일 수 있습니다.
+ 기존 오리진 요청 Lambda@Edge 함수가 이미 있는 경우 오리진 업데이트 로직을 기존 함수에 추가할 수 있습니다.
+ 오리진 업데이트 로직에서 Amazon DynamoDB 또는 Amazon S3와 같은 서드 파티 데이터 소스에서 데이터를 가져와야 하는 경우입니다.

Lambda@Edge에 대한 자세한 내용은 [Lambda@Edge를 사용하여 엣지에서 사용자 지정](lambda-at-the-edge.md) 섹션을 참조하시기 바랍니다.

## updateRequestOrigin() 메서드
<a name="update-request-origin-helper-function"></a>

`updateRequestOrigin()` 메서드를 사용하여 요청의 오리진 설정을 업데이트합니다. 이 메서드를 사용하여 배포에 이미 정의된 오리진의 기존 오리진 속성을 업데이트하거나 요청에 대한 새 오리진을 정의할 수 있습니다. 이렇게 하려면 변경하려는 속성을 지정합니다.

**중요**  
`updateRequestOrigin()`에서 지정하지 않은 설정은 기존 오리진의 구성에서 *동일한 설정*을 상속합니다.

`updateRequestOrigin()` 메서드에 따라 설정된 오리진은 HTTP 엔드포인트일 수 있으며 CloudFront 배포 내의 기존 오리진일 필요는 없습니다.

**참고**  
오리진 그룹의 일부인 오리진을 업데이트하는 경우 오리진 그룹의 *프라이머리 오리진*만 업데이트됩니다. 보조 오리진은 변경되지 않습니다. 장애 조치 기준과 일치하는 수정된 오리진의 모든 응답 코드는 보조 오리진으로 장애 조치를 트리거합니다.
오리진 유형을 변경하고 OAC를 사용 설정한 경우 `originAccessControlConfig`의 오리진 유형이 새 오리진 유형과 일치하는지 확인합니다.
`updateRequestOrigin()` 메서드를 사용하여 [VPC 오리진](private-content-vpc-origins.md)을 업데이트할 수 없습니다. 요청이 완료되지 않습니다.

**요청**

```
updateRequestOrigin({origin properties})
```

`origin properties`에는 다음 사항이 포함될 수 있습니다.

**domainName(선택 사항)**  
오리진의 도메인 이름입니다. 이를 제공하지 않으면 대신 할당된 오리진의 도메인 이름이 사용됩니다.    
**사용자 지정 오리진의 경우**  
DNS 도메인 이름(예: `www.example.com`)을 지정합니다. 도메인 이름에는 콜론(`:`)이 포함될 수 없으며 IP 주소가 될 수 없습니다. 도메인 이름은 최대 253자일 수 있습니다.  
**S3 오리진의 경우**  
Amazon S3 버킷의 DNS 도메인 이름(예: `amzn-s3-demo-bucket.s3.eu-west-1.amazonaws.com`)을 지정합니다. 이름은 최대 128자여야 하며, 모두 소문자여야 합니다.

**hostHeader(선택 사항, S3가 아닌 사용자 지정 오리진의 경우)**  
오리진에 요청할 때 사용할 호스트 헤더입니다. 제공하지 않으면 domainName 파라미터의 값이 사용됩니다. 호스트 헤더 또는 도메인 이름 파라미터가 제공되지 않은 경우 할당된 오리진의 도메인 이름이 사용되고, 오리진으로 전달(FTO) 정책에 호스트가 포함된 경우 수신 요청의 호스트 헤더가 사용됩니다. 호스트 헤더에는 콜론(`:`)이 포함될 수 없으며 IP 주소가 될 수 없습니다. 호스트 헤더는 최대 253자까지 작성할 수 있습니다.

**originPath(선택 사항)**  
요청이 콘텐츠를 찾아야 하는 오리진의 디렉터리 경로입니다. 경로는 슬래시(/)로 시작해야 하지만 슬래시 하나로 끝나지 않아야 합니다. 예를 들어 `example-path/`로 끝나지 않아야 합니다. 이를 제공하지 않으면 할당된 오리진의 오리진 경로가 사용됩니다.    
**사용자 지정 오리진의 경우**  
경로는 URL 인코딩되어야 하고 최대 255자여야 합니다.

**customHeaders(선택 사항)**  
각 사용자 지정 헤더에 대한 헤더 이름 및 값 페어를 지정하여 요청을 포함한 사용자 지정 헤더를 포함할 수 있습니다. 형식은 이벤트 구조에서 요청 및 응답 헤더의 형식과 다릅니다. 다음의 키/값 쌍 구문을 사용합니다.  

```
{"key1": "value1", "key2": "value2", ...}
```
허용되지 않는 헤더는 추가할 수 없으며 동일한 이름의 헤더가 수신되는 요청 `headers`에 존재할 수 없습니다. 헤더 이름은 함수 코드에서 소문자여야 합니다. CloudFront Functions이 이벤트 객체를 HTTP 요청으로 다시 변환하는 경우 헤더 이름에 있는 각 단어의 첫 글자가 대문자로 표시됩니다. 단어는 하이픈으로 구분됩니다.  
예를 들어 함수 코드가 `example-header-name`이라는 이름의 헤더를 추가하는 경우, CloudFront는 이 헤더를 HTTP 요청에서 `Example-Header-Name`으로 변환합니다. 자세한 내용은 [CloudFront에서 오리진 요청에 추가할 수 없는 사용자 지정 헤더](add-origin-custom-headers.md#add-origin-custom-headers-denylist) 및 [엣지 함수에 대한 제한 사항](edge-functions-restrictions.md)(을)를 참조하세요.  
이를 제공하지 않으면 할당된 오리진의 사용자 지정 헤더가 사용됩니다.

**connectionAttempts(선택 사항)**  
CloudFront가 오리진에 연결을 시도하는 횟수입니다. 최솟값은 1이고, 최댓값은 3입니다. 이를 제공하지 않으면 할당된 오리진을 통해 연결 시도가 사용됩니다.

**originShield(선택 사항)**  
이렇게 하면 CloudFront Origin Shield가 사용 설정되거나 업데이트됩니다. Origin Shield를 사용하면 오리진의 부하를 줄일 수 있습니다. 자세한 내용은 [Amazon CloudFront Origin Shield 사용](origin-shield.md) 섹션을 참조하세요. 이를 제공하지 않으면 할당된 오리진을 통해 Origin Shield 설정이 사용됩니다.    
**enabled(필수)**  
Origin Shield를 사용 또는 사용 해제하는 부울 표현식입니다. `true` 또는 `false` 값을 허용합니다.  
**region(사용 설정된 경우 필수)**  
Origin Shield의 AWS 리전입니다. 오리진에 대한 지연 시간이 가장 낮은 AWS 리전을 지정합니다. 리전 이름이 아닌 리전 코드를 사용합니다. 예를 들어 `us-east-2`를 사용하여 미국 동부(오하이오) 리전을 지정합니다.  
CloudFront Origin Shield를 사용하는 경우 이에 대한 AWS 리전을 지정해야 합니다. 사용 가능한 AWS 리전 목록과 오리진에 가장 적합한 리전을 선택하는 데 도움이 되는 목록은 [Origin Shield의 AWS 리전 선택](origin-shield.md#choose-origin-shield-region) 섹션을 참조하시기 바랍니다.

**originAccessControlConfig(선택 사항)**  
해당 오리진에 대한 원본 액세스 제어(OAC)의 고유한 식별자입니다. 이는 오리진이 Amazon S3, Lambda 함수 URL, MediaStore, MediaPackage V2 등 CloudFront OAC를 지원하는 경우에만 사용됩니다. 이를 제공하지 않으면 할당된 오리진의 OAC 설정이 사용됩니다.  
이는 레거시 오리진 액세스 ID(OAI)를 지원하지 않습니다. 자세한 내용은 [AWS 오리진에 대한 액세스 제한](private-content-restricting-access-to-origin.md) 섹션을 참조하세요.    
**enabled(필수)**  
OAC를 사용 또는 사용 해제하는 부울 표현식입니다. `true` 또는 `false` 값을 허용합니다.  
**signingBehavior(사용 설정된 경우 필수)**  
CloudFront가 서명(인증 정보 추가)하는 요청을 지정합니다. 대부분의 사용 사례에서 `always`를 지정합니다.. 자세한 내용은 [오리진 액세스 제어를 위한 고급 설정](private-content-restricting-access-to-s3.md#oac-advanced-settings-s3) 섹션을 참조하세요.  
이 필드는 다음 값 중 하나를 가질 수 있습니다.  
+ `always` - CloudFront가 모든 오리진 요청을 서명하고, 최종 사용자 요청으로부터 `Authorization` 헤더를 덮어씁니다(있는 경우).
+ `never` - CloudFront가 오리진 요청을 서명하지 않습니다. 이 값은 오리진에 대한 오리진 액세스 제어를 끕니다.
+ `no-override` - 뷰어 요청에 `Authorization` 헤더가 포함되지 않은 경우 CloudFront가 오리진 요청을 서명합니다. 뷰어 요청에 `Authorization` 헤더가 포함된 경우 CloudFront가 오리진 요청에 서명하지 않고 최종 사용자 요청의 `Authorization` 헤더와 함께 전달합니다.
**주의**  
뷰어 요청에서 `Authorization` 헤더를 전달하려면 이 오리진 액세스 제어와 연결된 오리진을 사용하는 모든 캐시 동작에 대한 해당 헤더를 오리진 요청 정책에 추가해야 합니다. 자세한 내용은 [정책을 통한 오리진 요청 제어](controlling-origin-requests.md) 섹션을 참조하세요.  
**signingProtocol(사용 설정된 경우 필수)**  
CloudFront가 요청을 서명(인증)하는 방법을 결정하는 OAC의 서명 프로토콜입니다. 유일한 유효 값은 `sigv4`입니다.  
**originType(사용 설정된 경우 필수)**  
이 OAC의 오리진 유형입니다. 유효한 값에는 `s3`, `mediapackagev2`, `mediastore` 및 `lambda` 등이 있습니다.

**timeouts(선택 사항)**  
CloudFront가 오리진이 응답하거나 데이터를 전송할 때까지 대기해야 하는 기간에 대해 지정할 수 있는 제한 시간입니다. 이를 제공하지 않으면 할당된 오리진의 제한 시간 설정이 사용됩니다.  
달리 명시되지 않은 한, 이러한 제한 시간은 사용자 지정 오리진과 Amazon S3 오리진을 모두 지원합니다.  
**readTimeout(선택 사항)**  
`readTimeout`은 다음 두 값 모두에 적용됩니다.  
+ CloudFront가 오리진에 요청을 전달한 후 응답을 기다리는 시간(초).
+ CloudFront가 오리진으로부터 응답 패킷을 수신한 후 다음 패킷을 수신할 때까지 대기하는 시간(초).
최소 제한 시간은 1초이고, 최대 제한 시간은 120초입니다. 자세한 내용은 [응답 제한 시간](DownloadDistValuesOrigin.md#DownloadDistValuesOriginResponseTimeout) 섹션을 참조하세요.  
**responseCompletionTimeout(선택 사항)**  
CloudFront에서 오리진으로의 요청이 열려 있고 응답을 기다릴 수 있는 시간(초). 이 시간까지 오리진에서 완전한 응답을 받지 못하면 CloudFront는 연결을 종료합니다.  
`responseCompletionTimeout` 값은 `readTimeout` 값과 같거나 이보다 커야 합니다. 자세한 내용은 [응답 완료 제한 시간](DownloadDistValuesOrigin.md#response-completion-timeout) 섹션을 참조하세요.  
**keepAliveTimeout(선택 사항)**  
이 제한 시간은 Amazon S3 오리진이 아닌 사용자 지정 오리진에만 적용됩니다. (S3 오리진 구성은 이러한 설정을 무시합니다.)   
`keepAliveTimeout`은 응답의 마지막 패킷을 수신한 후 CloudFront가 오리진에 대한 연결을 유지하려고 시도하는 시간을 지정합니다. 최소 제한 시간은 1초이고, 최대 제한 시간은 120초입니다. 자세한 내용은 [연결 유지 제한 시간(사용자 지정 및 VPC 오리진만 해당)](DownloadDistValuesOrigin.md#DownloadDistValuesOriginKeepaliveTimeout) 섹션을 참조하세요.  
**connectionTimeout(선택 사항)**  
오리진에 대한 연결을 설정하려고 할 때 CloudFront가 대기하는 시간(초)입니다. 최소 제한 시간은 1초이고, 최대 제한 시간은 10초입니다. 자세한 내용은 [연결 제한 시간](DownloadDistValuesOrigin.md#origin-connection-timeout) 섹션을 참조하세요.

**customOriginConfig(선택 사항)**  
`customOriginConfig`를 사용하여 Amazon S3 버킷이 *아닌* 오리진에 대한 연결 설정을 지정합니다. 한 가지 예외는 다음과 같습니다. S3 버킷이 고정 웹 사이트 호스팅으로 구성된 경우 이러한 설정을 지정할 수 있습니다. (다른 유형의 S3 버킷 구성은 이러한 설정을 무시합니다.) `customOriginConfig`가 제공되지 않으면 할당된 오리진의 설정이 사용됩니다.    
**port(필수)**  
CloudFront가 오리진에 연결하는 데 사용하는 HTTP 포트입니다. 오리진에서 수신 대기하는 HTTP 포트를 지정하십시오.  
**protocol(필수)**  
CloudFront가 오리진에 연결하는 데 사용하는 프로토콜(HTTP 또는 HTTPS)을 지정합니다. 유효한 값은 다음과 같습니다.  
+ `http` - CloudFront는 항상 HTTP를 사용하여 오리진에 연결합니다.
+ `https` - CloudFront는 항상 HTTPS를 사용하여 오리진에 연결합니다.  
**sslProtocols(필수)**  
HTTPS를 통해 오리진에 연결할 때 CloudFront에서 사용하는 최소 SSL/TLS 프로토콜을 지정하는 목록입니다. 유효한 값에는 `SSLv3`, `TLSv1`, `TLSv1.1` 및 `TLSv1.2` 등이 있습니다. 자세한 내용은 [최소 오리진 SSL 프로토콜](DownloadDistValuesOrigin.md#DownloadDistValuesOriginSSLProtocols) 섹션을 참조하세요.  
**ipAddressType(선택 사항)**  
CloudFront가 오리진에 연결하는 데 사용하는 IP 주소 유형을 지정합니다. 유효값에는 `ipv4`, `ipv6` 및 `dualstack`이 있습니다. `ipAddressType` 변경은 `domainName` 속성도 변경 중인 경우에만 지원됩니다.

**sni(선택 사항, S3가 아닌 사용자 지정 오리진의 경우)**  
서버 이름 표시(SNI)는 Transport Layer Security(TLS) 프로토콜의 확장으로, 클라이언트가 TLS 핸드셰이크 프로세스를 시작할 때 연결을 시도하는 호스트 이름을 나타냅니다. 이 값은 오리진 서버의 TLS 인증서에 있는 일반 이름과 일치해야 합니다. 그렇지 않으면 오리진 서버에서 오류가 발생할 수 있습니다.  
제공하지 않으면 `hostHeader` 파라미터의 값이 사용됩니다. 호스트 헤더가 제공되지 않으면 `domainName` 파라미터의 값이 사용됩니다.  
호스트 헤더 또는 도메인 이름 파라미터가 제공되지 않은 경우 할당된 오리진의 도메인 이름이 사용되고, 오리진으로 전달(FTO) 정책에 호스트가 포함된 경우 수신 요청의 호스트 헤더가 사용됩니다. SNI에는 콜론(`:`)이 포함될 수 없으며 IP 주소가 될 수 없습니다. SNI는 최대 253자까지 작성할 수 있습니다.

**allowedCertificateNames(선택 사항, S3가 아닌 사용자 지정 오리진의 경우)**  
CloudFront에서 오리진 서버와의 TLS 핸드셰이크 중에 오리진 서버 TLS 인증서와 일치하는 도메인의 유효성을 검사하는 데 사용할 유효한 인증서 이름 목록을 포함할 수 있습니다. 이 필드에는 유효한 도메인 이름 배열이 필요하며 `*.example.com`과 같은 와일드카드 도메인이 포함될 수 있습니다.  
허용되는 인증서 이름은 최대 20개까지 지정할 수 있습니다. 각 인증서의 이름은 최대 64자까지 가능합니다.

**Example - Amazon S3 요청 오리진 업데이트**  
다음 예제에서는 뷰어 요청의 오리진을 S3 버킷으로 변경하고 OAC를 사용 설정하며 오리진으로 전송된 사용자 지정 헤더를 재설정합니다.  

```
cf.updateRequestOrigin({
    "domainName" : "amzn-s3-demo-bucket-in-us-east-1.s3.us-east-1.amazonaws.com",
    "originAccessControlConfig": {
        "enabled": true,
        "signingBehavior": "always",
        "signingProtocol": "sigv4",
        "originType": "s3"
    },
    // Empty object resets any header configured on the assigned origin
    "customHeaders": {}
});
```

**Example - Application Load Balancer 요청 오리진 업데이트**  
다음 예제에서는 뷰어 요청의 오리진을 Application Load Balancer 오리진으로 변경하고 사용자 지정 헤더와 제한 시간을 설정합니다.  

```
cf.updateRequestOrigin({
    "domainName" : "example-1234567890.us-east-1.elb.amazonaws.com",
    "timeouts": {
        "readTimeout": 30,
        "connectionTimeout": 5
    },
    "customHeaders": {
        "x-stage": "production",
        "x-region": "us-east-1"
    }
});
```

**Example - Origin Shield가 사용 설정된 오리진으로 업데이트**  
다음 예제에서는 배포의 오리진에 Origin Shield가 사용 설정되어 있습니다. 함수 코드는 오리진에 사용되는 도메인 이름만 업데이트하고 다른 모든 선택 사항 파라미터를 생략합니다. 이 경우 Origin Shield 파라미터가 업데이트되지 않았으므로 Origin Shield는 수정된 오리진 도메인 이름과 함께 계속 사용됩니다.  

```
cf.updateRequestOrigin({
    "domainName" : "www.example.com"
});
```

**Example - 호스트 헤더, SNI 및 허용된 인증서 이름 업데이트**  
대부분의 사용 사례에서는 오리진으로 이동하는 요청에 이러한 유형의 수정을 사용할 필요가 없습니다. 이러한 값 변경의 영향을 이해하지 못한다면 이러한 파라미터를 사용해서는 안 됩니다.
다음 예시에서는 요청에 대한 도메인 이름, 호스트 헤더, SNI 및 허용된 인증서를 오리진으로 변경합니다.  

```
cf.updateRequestOrigin({ 
    "domainName": "www.example.com", 
    "hostHeader": "test.example.com", 
    "sni": "test.example.net", 
    "allowedCertificateNames": ["*.example.com", "*.example.net"],
});
```

## selectRequestOriginById() 메서드
<a name="select-request-origin-id-helper-function"></a>

`selectRequestOriginById()`를 사용해 배포에 이미 구성된 다른 오리진을 선택하여 기존 오리진을 업데이트합니다. 이 메서드는 업데이트된 오리진에서 정의한 것과 동일한 설정을 모두 사용합니다.

이 메서드는 함수를 실행할 때 사용된 것과 동일한 배포에 이미 정의된 오리진만 허용합니다. 오리진은 오리진을 설정할 때 정의한 오리진 이름인 오리진 ID로 참조됩니다.

배포에 VPC 오리진이 구성된 경우 이 메서드를 사용하여 오리진을 VPC 오리진으로 업데이트할 수 있습니다. 자세한 내용은 [VPC 오리진으로 액세스 제한](private-content-vpc-origins.md) 섹션을 참조하세요.

**참고**  
`selectRequestOriginById()` 함수는 상호 TLS(오리진)가 활성화된 오리진을 선택할 수 없습니다. 이 함수를 사용하여 상호 TLS(오리진)가 활성화된 오리진을 선택하려고 하면 검증 오류가 발생합니다.
사용 사례에 따라 상호 TLS(오리진)를 사용한 동적 오리진 선택이 필요한 경우, 모든 대상 오리진이 동일한 클라이언트 인증서를 사용하도록 `updateRequestOrigin()`을 대신 사용하세요.

**요청**

```
cf.selectRequestOriginById(origin_id, {origin_overrides})
```

이전 예시에서 `origin_id`는 함수를 실행하는 배포에서 오리진의 오리진 이름을 가리키는 문자열입니다. `origin_overrides `파라미터에는 다음이 포함될 수 있습니다.

**hostHeader(선택 사항, S3가 아닌 사용자 지정 오리진의 경우)**  
오리진에 요청할 때 사용할 호스트 헤더입니다. 제공하지 않으면 `domainName` 파라미터의 값이 사용됩니다.  
호스트 헤더 또는 도메인 이름 파라미터가 제공되지 않은 경우 할당된 오리진의 도메인 이름이 사용되고, 오리진으로 전달(FTO) 정책에 호스트가 포함된 경우 수신 요청의 호스트 헤더가 사용됩니다. 호스트 헤더에는 콜론(`:`)이 포함될 수 없으며 IP 주소가 될 수 없습니다. 호스트 헤더는 최대 253자까지 작성할 수 있습니다.

**sni(선택 사항, S3가 아닌 사용자 지정 오리진의 경우)**  
서버 이름 표시(SNI)는 Transport Layer Security(TLS) 프로토콜의 확장으로, 클라이언트가 TLS 핸드셰이크 프로세스를 시작할 때 연결을 시도하는 호스트 이름을 나타냅니다. 이 값은 오리진 서버의 TLS 인증서에 있는 일반 이름과 일치해야 합니다. 그렇지 않으면 오리진 서버에서 오류가 발생할 수 있습니다.  
제공하지 않으면 `hostHeader` 파라미터의 값이 사용됩니다. 호스트 헤더가 제공되지 않으면 `domainName` 파라미터의 값이 사용됩니다.  
호스트 헤더 또는 도메인 이름 파라미터가 제공되지 않은 경우 할당된 오리진의 도메인 이름이 사용되고, 오리진으로 전달(FTO) 정책에 호스트가 포함된 경우 수신 요청의 호스트 헤더가 사용됩니다. SNI에는 콜론(`:`)이 포함될 수 없으며 IP 주소가 될 수 없습니다. SNI는 최대 253자까지 작성할 수 있습니다.

**allowedCertificateNames(선택 사항, S3가 아닌 사용자 지정 오리진의 경우)**  
CloudFront에서 오리진 서버와의 TLS 핸드셰이크 중에 오리진 서버 TLS 인증서와 일치하는 도메인의 유효성을 검사하는 데 사용할 유효한 인증서 이름 목록을 포함할 수 있습니다. 이 필드에는 유효한 도메인 이름 배열이 필요하며 `*.example.com`과 같은 와일드카드 도메인이 포함될 수 있습니다.  
허용되는 인증서 이름은 최대 20개까지 지정할 수 있습니다. 각 인증서의 이름은 최대 64자까지 가능합니다.

**요청**

```
selectRequestOriginById(origin_id)
```

앞의 예시에서 `origin_id`는 함수를 실행하는 배포에서 오리진의 오리진 이름을 가리키는 문자열입니다.

**Example - Amazon S3 요청 오리진 선택**  
다음 예시에서는 배포와 연결된 오리진 목록에서 `amzn-s3-demo-bucket-in-us-east-1`라는 오리진을 선택하고 `amzn-s3-demo-bucket-in-us-east-1` 오리진의 구성 설정을 요청에 적용합니다.  

```
cf.selectRequestOriginById("amzn-s3-demo-bucket-in-us-east-1");
```

**Example - Application Load Balancer 요청 오리진 선택**  
다음 예시에서는 배포와 연결된 오리진 목록에서 `myALB-prod`라는 Application Load Balancer 오리진을 선택하고 `myALB-prod`의 구성 설정을 요청에 적용합니다.  

```
cf.selectRequestOriginById("myALB-prod");
```

**Example - Application Load Balancer 요청 오리진을 선택하고 호스트 헤더를 재정의합니다.**  
이전 예시와 같이 다음 예시에서는 배포와 연결된 오리진 목록에서 `myALB-prod`라는 Application Load Balancer 오리진을 선택하고 `myALB-prod`의 구성 설정을 요청에 적용합니다. 그러나 이 예제에서는 `origin_overrides`를 사용하여 호스트 헤더 값을 재정의합니다.  

```
cf.overrideRequestOrigin("myALB-prod",{ 
        "hostHeader" : "test.example.com"
});
```

## createRequestOriginGroup() 메서드
<a name="create-request-origin-group-helper-function"></a>

`createRequestOriginGroup()`를 사용하여 고가용성이 필요한 시나리오에서 장애 조치용 [오리진 그룹](high_availability_origin_failover.md#concept_origin_groups.creating)으로 사용할 두 개의 오리진을 정의합니다.

오리진 그룹에는 두 개의 오리진(프라이머리 및 보조)과 사용자가 지정하는 장애 조치 기준이 포함됩니다. CloudFront에서 오리진 장애 조치를 지원할 오리진 그룹을 생성합니다. 이 메서드를 사용하여 오리진 그룹을 생성하거나 업데이트할 때 단일 오리진 대신 오리진 그룹을 지정할 수 있습니다. CloudFront는 장애 조치 기준을 사용하여 프라이머리 오리진에서 보조 오리진으로 장애 조치를 수행합니다.

배포에 VPC 오리진이 구성된 경우 이 메서드를 통해 VPC 오리진을 사용하여 오리진 그룹을 생성할 수 있습니다. 자세한 내용은 [VPC 오리진으로 액세스 제한](private-content-vpc-origins.md) 섹션을 참조하세요.

**참고**  
`createRequestOriginGroup()` 함수는 상호 TLS(오리진)가 활성화된 오리진을 포함하는 오리진 그룹 생성을 지원하지 않습니다. 상호 TLS(오리진) 오리진이 있는 오리진 그룹은 CloudFront Functions를 통해 동적으로 생성할 수 없습니다.
상호 TLS(오리진)를 사용한 오리진 장애 조치 기능이 필요한 경우 함수에서 동적으로 생성하는 대신 CloudFront 배포 설정에서 오리진 그룹을 직접 구성하세요.

### 요청
<a name="create-origin-group-request"></a>

```
createRequestOriginGroup({origin_group_properties})
```

앞의 예시에서 `origin_group_properties`에는 다음이 포함될 수 있습니다.

**originIds(필수)**  
`origin_ids` 배열이며, 여기서 `origin_id`는 함수를 실행하는 배포에서 오리진의 오리진 이름을 가리키는 문자열입니다. 배열의 일부로 두 개의 오리진을 제공해야 합니다. 목록의 첫 번째 오리진은 프라이머리 오리진이고 두 번째 오리진은 장애 조치를 위한 보조 오리진 역할을 합니다.

**originOverrides(선택 사항)**  
 `{origin_overrides}` 파라미터를 사용하여 몇 가지 고급 설정을 덮어쓸 수 있습니다. `origin overrides`에는 다음 사항이 포함될 수 있습니다.    
**hostHeader(선택 사항, S3가 아닌 사용자 지정 오리진의 경우)**  
오리진에 요청할 때 사용할 호스트 헤더입니다. 제공하지 않으면 `domainName` 파라미터의 값이 사용됩니다.  
호스트 헤더 또는 도메인 이름 파라미터가 제공되지 않은 경우 할당된 오리진의 도메인 이름이 사용되고, 오리진으로 전달(FTO) 정책에 호스트가 포함된 경우 수신 요청의 호스트 헤더가 사용됩니다. 호스트 헤더에는 콜론(`:`)이 포함될 수 없으며 IP 주소가 될 수 없습니다. 호스트 헤더는 최대 253자까지 작성할 수 있습니다.  
**sni(선택 사항, S3가 아닌 사용자 지정 오리진의 경우)**  
서버 이름 표시(SNI)는 클라이언트가 TLS 핸드셰이크 프로세스를 시작할 때 연결을 시도하는 호스트 이름을 나타내는 Transport Layer Security(TLS) 프로토콜의 확장입니다. 이 값은 오리진 서버의 TLS 인증서에 있는 일반 이름과 일치해야 합니다. 그렇지 않으면 오리진 서버에서 오류가 발생할 수 있습니다.  
제공하지 않으면 `hostHeader` 파라미터의 값이 사용됩니다. 호스트 헤더가 제공되지 않으면 `domainName` 파라미터의 값이 사용됩니다.  
호스트 헤더 또는 도메인 이름 파라미터가 제공되지 않은 경우 할당된 오리진의 도메인 이름이 사용되고, 오리진으로 전달(FTO) 정책에 호스트가 포함된 경우 수신 요청의 호스트 헤더가 사용됩니다. SNI에는 콜론(`:`)이 포함될 수 없으며 IP 주소가 될 수 없습니다. SNI는 최대 253자까지 작성할 수 있습니다.  
**allowedCertificateNames(선택 사항, S3가 아닌 사용자 지정 오리진의 경우)**  
CloudFront에서 오리진 서버와의 TLS 핸드셰이크 중에 오리진 서버 TLS 인증서와 일치하는 도메인의 유효성을 검사하는 데 사용할 유효한 인증서 이름 목록을 포함할 수 있습니다. 이 필드에는 유효한 도메인 이름 배열이 필요하며 `*.example.com`과 같은 와일드카드 도메인이 포함될 수 있습니다.  
허용되는 인증서 이름은 최대 20개까지 지정할 수 있습니다. 각 인증서의 이름은 최대 64자까지 가능합니다.

**selectionCriteria(선택 사항)**  
`default` 오리진 장애 조치 기준을 사용할지 아니면 `media-quality-score` 기반 장애 조치 로직을 사용할지 선택합니다. 유효한 값은 다음과 같습니다.  
+ `default`는 `failoverCriteria`에 지정된 상태 코드를 기반으로 장애 조치 기준을 사용합니다. 함수에서 `selectionCriteria`를 설정하지 않으면 `default`가 사용됩니다.
+ `media-quality-score`는 미디어 인식 라우팅 기능을 사용할 때 사용됩니다.

**failoverCriteria(필수)**  
프라이머리 오리진에서 반환될 때 CloudFront가 보조 오리진으로 장애 조치하도록 트리거하는 상태 코드 배열입니다. 기존 오리진 그룹을 덮어쓰면 이 배열은 오리진 그룹의 원래 구성에 설정된 모든 장애 조치 상태 코드를 덮어씁니다.  
`media-quality-score` `selectionCriteria`를 사용하는 경우 CloudFront는 미디어 품질 점수를 기반으로 요청을 라우팅하려고 시도합니다. 선택한 오리진이 이 배열에 설정된 오류 코드를 반환하면 CloudFront는 다른 오리진으로 장애 조치를 수행합니다.

**Example - 요청 오리진 그룹 생성**  
다음 예시에서는 오리진 ID를 사용하여 요청에 대한 오리진 그룹을 생성합니다. 이러한 오리진 ID는 이 함수를 실행하는 데 사용되는 배포의 오리진 그룹 구성에서 가져옵니다.  
선택적으로 `originOverrides`를 사용하여 `sni`, `hostHeader` 및 `allowedCertificateNames`에 대한 오리진 그룹 구성을 재정의할 수 있습니다.  

```
import cf from 'cloudfront';

function handler(event) {
    cf.createRequestOriginGroup({
        "originIds": [
            {
                "originId": "origin-1",
                "originOverrides": {
                    "hostHeader": "hostHeader.example.com",
                    "sni": "sni.example.com",
                    "allowedCertificateNames": ["cert1.example.com", "cert2.example.com", "cert3.example.com"]
                }
            },
            {
                "originId": "origin-2",
                "originOverrides": {
                    "hostHeader": "hostHeader2.example.com",
                    "sni": "sni2.example.com",
                    "allowedCertificateNames": ["cert4.example.com", "cert5.example.com"]
                }
            }
        ],
        "failoverCriteria": {
            "statusCodes": [500]
        }
    });
    
    event.request.headers['x-hookx'] = { value: 'origin-overrides' };
    return event.request;
}
```

# CloudFront SaaS Manager 속성에 대한 헬퍼 메서드
<a name="saas-specific-logic-function-code"></a>

CloudFront SaaS Manager에서 다음 헬퍼 함수를 사용하여 직접 만든 함수에서 다중 테넌트 배포의 값을 검색합니다. 이 페이지의 예제를 사용하려면 먼저 JavaScript 런타임 2.0을 사용하여 CloudFront 함수를 만들어야 합니다. 자세한 설명은 [CloudFront Functions를 위한 JavaScript 런타임 2.0 기능](functions-javascript-runtime-20.md) 섹션을 참조하세요.

**Topics**
+ [연결 그룹](#connection-groups-helper-function)
+ [배포 테넌트](#distribution-tenants-helper-functions)

## 연결 그룹
<a name="connection-groups-helper-function"></a>

배포 테넌트와 연결된 연결 그룹에는 도메인 이름이 있습니다.

이 값을 가져오려면 이벤트 객체의 `context` 하위 객체에서 `endpoint` 필드를 사용합니다.

**요청**

```
const value = event.context.endpoint;
```

**응답**

응답은 연결 그룹의 도메인 이름이 포함된 `string`(예: d111111abcdef8.cloudfront.net)입니다. `endpoint` 필드는 연결된 연결 그룹이 있는 다중 테넌트 배포에 대해 함수가 호출되는 경우에만 나타납니다. 자세한 내용은 [컨텍스트 객체](functions-event-structure.md#functions-event-structure-context) 섹션을 참조하세요.

## 배포 테넌트
<a name="distribution-tenants-helper-functions"></a>

CloudFront Functions에는 특정 배포 테넌트 값에 대한 액세스를 제공하는 모듈이 있습니다.

이 모듈을 사용하려면 다음 함수 코드의 첫 줄에 다음 스테이트먼트를 포함합니다.

```
import cf from 'cloudfront';
```

다음 예제는 `handler` 함수에서만 직접 또는 중첩 호출 함수를 통해 사용할 수 있습니다.

### `distributionTenant.id` 필드
<a name="distribution-tenants-field"></a>

이 필드를 사용하여 배포 테넌트 ID의 값을 가져옵니다.

**요청**

```
const value = cf.distributionTenant.id;
```

**응답**

응답은 배포 테넌트 ID를 포함하는 `string`(예: `dt_1a2b3c4d5e6f7`)입니다.

**오류 처리**.

함수가 표준 배포에서 호출되는 경우 `distributionTenant.id` 필드를 지정하면 `distributionTenant module is not available` 유형 오류가 반환됩니다. 이 사용 사례를 처리하기 위해 코드에 `try` 및 `catch` 블록을 추가할 수 있습니다.

### `distributionTenant.parameters.get()` 메서드
<a name="distribution-tenant-parameters-get-method"></a>

이 메서드를 사용하여 지정한 배포 테넌트 파라미터 이름의 값을 반환합니다.

```
distributionTenant.parameters.get("key");
```

`key`: 값을 가져오려는 배포 테넌트 파라미터 이름입니다.

**요청**

```
const value = distributionTenant.parameters.get("key");
```

**응답**

응답은 배포 테넌트 파라미터의 값을 포함하는 `string`입니다. 예를 들어 키 이름이 `TenantPath`인 경우 이 파라미터의 값은 `tenant1`일 수 있습니다.

**오류 처리**.

다음 오류가 표시될 수 있습니다.
+ 함수가 표준 배포에서 호출되는 경우 `distributionTenant.parameters.get()` 메서드는 `distributionTenant module is not available` 유형 오류를 반환합니다.
+ 지정한 배포 테넌트 파라미터가 존재하지 않으면 `DistributionTenantParameterKeyNotFound` 오류가 반환됩니다.

이 사용 사례를 관리하기 위해 코드에 `try` 및 `catch` 블록을 추가할 수 있습니다.

# async 및 await 사용
<a name="async-await-syntax"></a>

CloudFront Functions JavaScript 런타임 함수 2.0은 `Promise` 객체를 처리하기 위한 `async` 및 `await` 구문을 제공합니다. 프로미스는 `async`로 표시된 함수의 `await` 키워드를 통해 액세스할 수 있는 지연된 결과를 나타냅니다. 다양한 새 WebCrypto 함수가 프로미스를 사용합니다.

`Promise` 객체에 대한 자세한 내용은 [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)를 참조하세요.

**참고**  
다음 코드 샘플에는 JavaScript 런타임 2.0을 사용해야 합니다.  
`await`는 `async` 함수 내에서만 사용할 수 있습니다. `async` 인수 및 종료는 지원되지 않습니다.

```
async function answer() {
    return 42;
}

// Note: async, await can be used only inside an async function. async arguments and closures are not supported.

async function handler(event) {
    // var answer_value = answer(); // returns Promise, not a 42 value
    let answer_value = await answer(); // resolves Promise, 42
    console.log("Answer"+answer_value);
    event.request.headers['answer'] = { value : ""+answer_value };
    return event.request;
}
```

다음 예제 JavaScript 코드는 `then` 체인 메서드로 프로미스를 보는 방법을 보여줍니다. `catch`를 사용하여 오류를 확인할 수 있습니다.

**주의**  
promise 결합자(예: `Promise.all`, `Promise.any`) 및 promise 체인 메서드(예: `then` 및 `catch`)를 사용하려면 많은 함수 메모리 사용량이 필요할 수 있습니다. 함수가 [최대 함수 메모리](cloudfront-limits.md#limits-functions) 할당량을 초과하면 실행에 실패합니다. 이 오류를 방지하도록 `promise` 메서드 대신 `await` 구문을 사용하는 것이 좋습니다.

```
async function answer() {
    return 42;
}

async function squared_answer() {
   return answer().then(value => value * value)
} 
// Note: async, await can be used only inside an async function. async arguments and closures are not supported.
async function handler(event) {
    // var answer_value = answer(); // returns Promise, not a 42 value
    let answer_value = await squared_answer(); // resolves Promise, 42
    console.log("Answer"+answer_value);
    event.request.headers['answer'] = { value : ""+answer_value };
    return event.request;
}
```

# CloudFront Functions에 대한 CWT 지원
<a name="cwt-support-cloudfront-functions"></a>

이 섹션에서는 CloudFront 엣지 로케이션에서 보안 토큰 기반 인증 및 권한 부여를 활성화하는 CloudFront Functions의 CBOR 웹 토큰(CWT) 지원에 대한 세부 정보를 제공합니다. 이 지원은 CloudFront Functions에서 액세스할 수 있는 모듈로 제공됩니다.

이 모듈을 사용하려면 JavaScript 런타임 2.0을 사용하여 CloudFront Functions을 만들고 함수 코드의 첫 번째 줄에 다음 스테이트먼트를 포함합니다.

```
import cf from 'cloudfront';
```

이 모듈과 연결된 메서드는 다음을 통해 액세스할 수 있습니다(여기서 \$1는 모듈에 있는 다양한 함수를 나타내는 와일드카드).

```
cf.cwt.*
```

자세한 내용은 [CloudFront Functions를 위한 JavaScript 런타임 2.0 기능](functions-javascript-runtime-20.md) 섹션을 참조하세요.

현재 모듈은 최대 토큰 크기에 대해 한도가 1KB인 HS256(HMAC-SHA256) 알고리즘을 사용하는 MAC0 구조만 지원합니다.

## 토큰 구조
<a name="token-structure"></a>

이 섹션에서는 CWT 모듈에서 예상되는 토큰 구조를 다룹니다. 모듈은 토큰에 태그를 올바르게 지정하고 식별할 수 있어야 합니다(예: COSE MAC0). 또한 토큰의 구조와 마찬가지로 모듈은 [CBOR 객체 서명 및 암호화(COSE)[RFC 8152]](https://datatracker.ietf.org/doc/html/rfc8152)에서 설정한 표준을 따릅니다.

```
( // CWT Tag (Tag value: 61) --- optional    
    ( // COSE MAC0 Structure Tag (Tag value: 17) --- required        
        [            
            protectedHeaders,            
            unprotectedHeaders,            
            payload,            
            tag,        
        ]    
    )
)
```

**Example : COSE MAC0 구조를 사용한 CWT**  

```
61( // CWT tag     
    17( // COSE_MAC0 tag       
        [         
            { // Protected Headers           
                1: 4  // algorithm : HMAC-256-64         
            },         
            { // Unprotected Headers           
                4: h'53796d6d6574726963323536' // kid : Symmetric key id          
            },         
            { // Payload           
                1: "https://iss.example.com", // iss           
                2: "exampleUser", // sub           
                3: "https://aud.example.com", // aud           
                4: 1444064944, // exp           
                5: 1443944944, // nbf           
                6: 1443944944, // iat         
            },         
            h'093101ef6d789200' // tag       
        ]     
    )   
)
```
CWT 태그는 토큰을 생성할 때 선택 사항입니다. 그러나 COSE 구조 태그는 필수입니다.

## validateToken() 메서드
<a name="validatetoken-method"></a>

함수는 지정된 키를 사용하여 CWT 토큰을 디코딩하고 검증합니다. 검증에 성공하면 디코딩된 CWT 토큰을 반환합니다. 그렇지 않으면 오류가 발생합니다. 이 함수는 클레임 세트에 대한 검증을 수행하지 않습니다.

### 요청
<a name="validatetoken-request"></a>

```
cf.cwt.validateToken(token, handlerContext{key})
```Parameters

**토큰(필수)**  
검증을 위한 인코딩된 토큰입니다. JavaScript 버퍼여야 합니다.

**handlerContext(필수)**  
validateToken 직접 호출에 대한 컨텍스트를 저장하는 JavaScript 객체입니다. 현재 키 속성만 지원됩니다.

**키(필수)**  
메시지 다이제스트 계산을 위한 비밀 키입니다. 문자열 또는 JavaScript 버퍼로 제공할 수 있습니다.

### 응답
<a name="validatetoken-response"></a>

`validateToken()` 메서드가 성공적으로 검증된 토큰을 반환하면 함수의 응답은 다음 형식의 `CWTObject`입니다. 디코딩되면 모든 클레임 키가 문자열로 표시됩니다.

```
CWTObject {    
    protectedHeaders,    
    unprotectedHeaders,    
    payload
}
```

### 예제 - 토큰의 일부로 전송된 KID로 토큰 검증
<a name="validatetoken-example"></a>

이 예제는 키드가 헤더에서 추출되는 CWT 토큰 검증을 보여줍니다. 그런 다음 키드가 CloudFront Functions KeyValueStore로 전달되어 토큰을 검증하는 데 사용되는 보안 키를 가져옵니다.

```
import cf from 'cloudfront'

const CwtClaims = {
   iss: 1,
   aud: 3,
   exp: 4
}

async function handler(event) {
    try {
        let request = event.request;
        let encodedToken = request.headers['x-cwt-token'].value;
        let kid = request.headers['x-cwt-kid'].value;
                
        // Retrieve the secret key from the kvs
        let secretKey = await cf.kvs().get(kid);
                 
        // Now you can use the secretKey to decode & validate the token.
        let tokenBuffer = Buffer.from(encodedToken, 'base64url');
                
        let handlerContext = {
           key: secretKey,
        }
                
        try {
            let cwtObj = cf.cwt.validateToken(tokenBuffer, handlerContext);
                        
            // Check if token is expired
            const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
            if (cwtObj[CwtClaims.exp] && cwtObj[CwtClaims.exp] < currentTime) {
                return {
                    statusCode: 401,
                    statusDescription: 'Token expired'
                };
            }
        } catch (error) {
            return {
               statusCode: 401,
               statusDescription: 'Invalid token'
            };
         }
    } catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
     }
    return request;
}
```

## generateToken() 메서드
<a name="generatetoken-method"></a>

이 함수는 제공된 페이로드 및 컨텍스트 설정을 사용하여 새 CWT 토큰을 생성합니다.

### 요청
<a name="generatetoken-request"></a>

```
cf.cwt.generateToken(generatorContext, payload)
```Parameters

**generatorContext(필수)**  
이 JavaScript 객체는 토큰을 생성하기 위한 컨텍스트로 사용되며 다음 키 값 페어를 포함합니다.    
**cwtTag(선택 사항)**  
이 값은 부울로, `true`인 경우 `cwtTag`를 추가해야 함을 지정합니다.  
**coseTag(필수)**  
COSE 태그 유형을 지정합니다. 현재 `MAC0`만 지원됩니다.  
**키(필수)**  
메시지 다이제스트를 계산하는 비밀 키입니다. 이 값은 문자열 또는 JavaScript `Buffer`일 수 있습니다.

**페이로드(필수)**  
인코딩을 위한 토큰 페이로드입니다. 페이로드는 `CWTObject` 형식이어야 합니다.

### 응답
<a name="generatetoken-response"></a>

인코딩된 토큰이 포함된 JavaScript 버퍼를 반환합니다.

**Example : CWT 토큰 생성**  

```
import cf from 'cloudfront';

const CwtClaims = {
    iss: 1,
    sub: 2,
    exp: 4
};

const CatClaims = {
    catu: 401,
    catnip: 402,
    catm: 403,
    catr: 404
};

const Catu = {
    host: 1,
    path: 2,
    ext: 3
};

const CatuMatchTypes = {
    prefix_match: 1,
    suffix_match: 2,
    exact_match: 3
};

const Catr = {
    renewal_method: 1,
    next_renewal_time: 2,
    max_uses: 3
};

async function handler(event) {
    try {
        const response = {
            statusCode: 200,
            statusDescription: 'OK',
            headers: {}
        };
        
        const commonAccessToken = {
            protected: {
                1: "5",
            },
            unprotected: {},
            payload: {
                [CwtClaims.iss]: "cloudfront-documentation",
                [CwtClaims.sub]: "cwt-support-on-cloudfront-functions",
                [CwtClaims.exp]: 1740000000,
                [CatClaims.catu]: {
                    [Catu.host]: {
                        [CatuMatchTypes.suffix_match]: ".cloudfront.net"
                    },
                    [Catu.path]: {
                        [CatuMatchTypes.prefix_match]: "/media/live-stream/cf-4k/"
                    },
                    [Catu.ext]: {
                        [CatuMatchTypes.exact_match]: [
                            ".m3u8",
                            ".ts",
                            ".mpd"
                        ]
                    }
                },
                [CatClaims.catnip]: [
                    "[IP_ADDRESS]",
                    "[IP_ADDRESS]"
                ],
                [CatClaims.catm]: [
                    "GET",
                    "HEAD"
                ],
                [CatClaims.catr]: {
                    [Catr.renewal_method]: "header_renewal",
                    [Catr.next_renewal_time]: 1750000000,
                    [Catr.max_uses]: 5
                }
            }
        };
        
        if (!request.headers['x-cwt-kid']) {
            throw new Error('Missing x-cwt-kid header');
        }
        
        const kid = request.headers['x-cwt-kid'].value;
        const secretKey = await cf.kvs().get(kid);
        
        if (!secretKey) {
            throw new Error('Secret key not found for provided kid');
        }
        
        try {
            const genContext = {
                cwtTag: true,
                coseTag: "MAC0",
                key: secretKey
            };
            
            const tokenBuffer = cf.cwt.generateToken(commonAccessToken, genContext);
            response.headers['x-generated-cwt-token'] = { value: tokenBuffer.toString('base64url') };
                        
            return response;
        } catch (tokenError) {
            return {
                statusCode: 401,
                statusDescription: 'Could not generate the token'
            };
        }
    } catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
    }
}
```

**Example : 일부 로직을 기반으로 토큰 새로 고침**  

```
import cf from 'cloudfront'

const CwtClaims = {
   iss: 1,
   aud: 3,
   exp: 4
}

async function handler(event) {
    try {
        let request = event.request;
        let encodedToken = request.headers['x-cwt-token'].value;
        let kid = request.headers['x-cwt-kid'].value;
        let secretKey = await cf.kvs().get(kid); // Retrieve the secret key from the kvs
                
        // Now you can use the secretKey to decode & validate the token.
        let tokenBuffer = Buffer.from(encodedToken, 'base64url');
                
        let handlerContext = {
           key: secretKey,
        }
                
        try {
            let cwtJSON = cf.cwt.validateToken(tokenBuffer, handlerContext);
                        
            // Check if token is expired
            const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
            if (cwtJSON[CwtClaims.exp] && cwtJSON[CwtClaims.exp] < currentTime) {
                // We can regnerate the token and add 8 hours to the expiry time
                cwtJSON[CwtClaims.exp] = Math.floor(Date.now() / 1000) + (8 * 60 * 60);
                                
                let genContext = {
                  coseTag: "MAC0",
                  key: secretKey
                }
                                
                let newTokenBuffer = cf.cwt.generateToken(cwtJSON, genContext);
                 request.headers['x-cwt-regenerated-token'] = newTokenBuffer.toString('base64url');
            }
        } catch (error) {
            return {
               statusCode: 401,
               statusDescription: 'Invalid token'
            };
         }
    }
    catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
     }
    return request;
}
```

# 일반 헬퍼 메서드
<a name="general-helper-methods"></a>

이 페이지에서는 CloudFront Functions 내의 추가 헬퍼 메서드를 제공합니다. 이러한 메서드를 사용하려면 JavaScript 런타임 2.0을 사용하여 CloudFront Functions를 생성합니다.

```
import cf from 'cloudfront';
```

자세한 내용은 [CloudFront Functions를 위한 JavaScript 런타임 2.0 기능](functions-javascript-runtime-20.md) 섹션을 참조하세요.

## `edgeLocation` 메타데이터
<a name="edge-location-metadata"></a>

이 메서드를 사용하려면 `cloudfront` 모듈을 사용해야 합니다.

**참고**  
뷰어 요청 함수에만 이 방법을 사용할 수 있습니다. 뷰어 응답 함수의 경우 이 메서드는 비어 있습니다.

이 JavaScript 객체를 사용하여 요청을 처리하는 데 사용되는 엣지 로케이션 공항 코드, 예상 [리전 엣지 캐시](HowCloudFrontWorks.md#CloudFrontRegionaledgecaches) 리전 또는 CloudFront 서버 IP 주소를 가져옵니다. 이 메타데이터는 뷰어 요청 이벤트 트리거만 사용할 수 있습니다.

```
cf.edgeLocation = {
    name: SEA
    serverIp: 1.2.3.4
    region: us-west-2
}
```

`cf.edgeLocation` 객체에는 다음 사항이 포함될 수 있습니다.

**이름**  
요청을 처리한 엣지 로케이션의 세 글자 [IATA 코드](https://en.wikipedia.org/wiki/IATA_airport_code)입니다.

**serverIp**  
요청을 처리한 서버의 IPv4 또는 IPv6 주소입니다.

**region**  
캐시 누락이 있는 경우 요청이 사용할 것으로 *예상되는* CloudFront 리전 엣지 캐시(REC)입니다. 이 값은 예상 REC를 사용할 수 없고 백업 REC가 요청에 사용되는 경우 업데이트되지 않습니다. 여기에는 사용 중인 Origin Shield 위치가 포함되지 않습니다. 단, 기본 REC와 Origin Shield가 동일한 위치인 경우는 예외입니다.

**참고**  
CloudFront가 오리진 장애 조치를 사용하도록 구성된 경우 CloudFront Functions는 두 번째로 간접 호출되지 않습니다. 자세한 내용은 [CloudFront 오리진 장애 조치를 통한 고가용성 최적화](high_availability_origin_failover.md) 섹션을 참조하세요.

## `rawQueryString()` 메서드
<a name="raw-query-string-method"></a>

이 메서드에는 `cloudFront` 모듈이 필요하지 않습니다.

`rawQueryString()` 메서드를 사용하여 구문 분석되지 않은 쿼리 문자열과 변경되지 않은 쿼리 문자열을 문자열로 검색합니다.

**요청**

```
function handler(event) {
    var request = event.request;
    const qs = request.rawQueryString();
}
```

**응답**

수신 요청의 전체 쿼리 문자열을 선행 `?` 없이 문자열 값으로 반환합니다.
+ 쿼리 문자열이 없지만 `?`가 있는 경우 함수는 빈 문자열을 반환합니다.
+ 쿼리 문자열이 없고 `?`가 없는 경우 함수는 `undefined`를 반환합니다.

**사례 1: 반환된 전체 쿼리 문자열(선행 `?` 없음)**  
수신 요청 URL: `https://example.com/page?name=John&age=25&city=Boston`  
`rawQueryString()`에서 를 반환합니다.`"name=John&age=25&city=Boston"`

**사례 2: 빈 문자열 반환됨(`?`가 있지만 파라미터가 없는 경우)**  
수신 요청 URL: `https://example.com/page?`  
`rawQueryString()`에서 를 반환합니다.`""`

**사례 3: `undefined` 반환됨(쿼리 문자열 및 `?` 없음)**  
수신 요청 URL: `https://example.com/page`  
`rawQueryString()`에서 를 반환합니다.`undefined`