

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# AWS AppSync 해석기 매핑 템플릿 컨텍스트 참조
<a name="resolver-context-reference"></a>

**참고**  
이제 우리는 주로 APPSYNC\$1JS 런타임과 해당 문서를 지원합니다. [여기](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html)에서 APPSYNC\$1JS 런타임과 해당 안내서를 사용해 보세요.

AWS AppSync 는 해석기 매핑 템플릿 작업을 위한 변수 및 함수 집합을 정의합니다. 이렇게 하면 GraphQL을 사용하는 데이터에 대한 논리적 조작이 더 쉬워집니다. 이 문서에서는 이러한 함수를 설명하고 템플릿을 사용하는 예를 제공합니다.

## `$context`에 액세스
<a name="accessing-the-context"></a>

`$context` 변수는 해석기 간접 호출에 대한 모든 컨텍스트 정보를 보관하는 맵입니다. 이 변수의 구조는 다음과 같습니다.

```
{
   "arguments" : { ... },
   "source" : { ... },
   "result" : { ... },
   "identity" : { ... },
   "request" : { ... },
   "info": { ... }
}
```

**참고**  
값을 검색하기 위해 키로 사전/맵 항목(예: `context`의 항목)에 액세스하려는 경우 Velocity Template Language(VTL)를 통해 `<dictionary-element>.<key-name>` 표기법을 직접 사용할 수 있습니다. 하지만 이는 키 이름이 특수 문자인 경우(예: 밑줄(\$1))와 같이 모든 경우에서 작동하지 않을 수 있습니다. 항상 `<dictionary-element>.get("<key-name>")` 주석을 사용하는 것이 좋습니다.

`$context` 맵의 각 필드는 다음과 같이 정의됩니다.

### `$context` 필드
<a name="accessing-the-context-list"></a>

** `arguments` **  
이 필드에 대한 모든 GraphQL 인수를 포함하는 맵입니다.

** `identity` **  
호출자에 대한 정보를 포함하는 객체입니다. 이 필드의 구조에 대한 자세한 내용은 [자격 증명](#aws-appsync-resolver-context-reference-identity)을 참조하십시오.

** `source` **  
상위 필드의 해결 방법을 포함하는 맵입니다.

** `stash` **  
stash는 각 해석기 및 함수 매핑 템플릿 내에서 사용할 수 있는 맵입니다. 단일 해석기가 실행되는 동안에는 동일한 stash 인스턴스가 사용됩니다. 이는 파이프라인 해석기 내에서 stash를 사용해 요청 및 응답 매핑 템플릿 간에 그리고 함수 간에 임의 데이터를 전달할 수 있다는 의미입니다. stash는 동일한 메서드를 [Java Map](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html) 데이터 구조로 노출합니다.

** `result` **  
해석기의 결과를 포함하고 있는 컨테이너입니다. 이 필드는 매핑 템플릿에 응답하는 경우에만 사용할 수 있습니다.  
예를 들어, 다음 쿼리의 `author` 필드를 해석하는 경우:  

```
query {
    getPost(id: 1234) {
        postId
        title
        content
        author {
            id
            name
        }
    }
}
```
응답 매핑 템플릿을 처리하는 경우 사용할 수 있는 전체 `$context` 변수는 다음과 같습니다.  

```
{
  "arguments" : {
    id: "1234"
  },
  "source": {},
  "result" : {
      "postId": "1234",
      "title": "Some title",
      "content": "Some content",
      "author": {
        "id": "5678",
        "name": "Author Name"
      }
  },
  "identity" : {
      "sourceIp" : ["x.x.x.x"],
      "userArn" : "arn:aws:iam::123456789012:user/appsync",
      "accountId" : "666666666666",
      "user" : "AIDAAAAAAAAAAAAAAAAAA"
  }
}
```

** `prev.result` **  
파이프라인 해석기에서 실행된 이전 작업의 결과입니다.  
이전 작업이 파이프라인 해석기 이전 매핑 템플릿이었으면 `$ctx.prev.result`는 템플릿의 평가 결과를 나타내고 파이프라인의 첫 번째 함수에 사용할 수 있습니다.  
이전 작업이 첫 번째 함수였으면 `$ctx.prev.result`는 첫 번째 함수의 결과를 나타내고, 파이프라인의 두 번째 함수에 사용할 수 있습니다.  
이전 작업이 마지막 함수였으면 `$ctx.prev.result`는 마지막 함수의 결과를 나타내고, 파이프라인 해석기 이후 매핑 템플릿에 사용할 수 있습니다.

** `info` **  
GraphQL 요청에 대한 정보가 포함된 객체입니다. 이 필드의 구조는 [정보](#aws-appsync-resolver-context-reference-info)를 참조하십시오.

### ID
<a name="aws-appsync-resolver-context-reference-identity"></a>

`identity` 섹션에는 호출자에 대한 정보가 포함되어 있습니다. 이 섹션의 모양은 AWS AppSync API의 권한 부여 유형에 따라 다릅니다.

 AWS AppSync 보안 옵션에 대한 자세한 내용은 [권한 부여 및 인증을](security-authz.md#aws-appsync-security) 참조하세요.

** `API_KEY` 권한 부여**  
`identity` 필드는 채워져 있지 않습니다.

**`AWS_LAMBDA` 권한 부여**  
`identity`에는 요청을 승인하는 Lambda 함수가 반환한 동일한 `resolverContext` 콘텐츠가 포함된 `resolverContext` 키가 포함되어 있습니다.

** `AWS_IAM` 권한 부여**  
`identity`의 형식은 다음과 같습니다.  

```
{
    "accountId" : "string",
    "cognitoIdentityPoolId" : "string",
    "cognitoIdentityId" : "string",
    "sourceIp" : ["string"],
    "username" : "string", // IAM user principal
    "userArn" : "string",
    "cognitoIdentityAuthType" : "string", // authenticated/unauthenticated based on the identity type
    "cognitoIdentityAuthProvider" : "string" // the auth provider that was used to obtain the credentials
}
```

** `AMAZON_COGNITO_USER_POOLS` 권한 부여**  
`identity`의 형식은 다음과 같습니다.  

```
{
    "sub" : "uuid",
    "issuer" : "string",
    "username" : "string"
    "claims" : { ... },
    "sourceIp" : ["x.x.x.x"],
    "defaultAuthStrategy" : "string"
}
```

각 필드는 다음과 같이 정의됩니다.

** `accountId` **  
호출자의 AWS 계정 ID입니다.

** `claims` **  
사용자의 클레임입니다.

** `cognitoIdentityAuthType` **  
자격 증명 유형을 기반으로 인증되거나 인증되지 않습니다.

** `cognitoIdentityAuthProvider` **  
요청에 서명하는 데 사용되는 보안 인증 정보를 얻는 데 사용되는 외부 자격 증명 공급자 정보를 쉼표로 구분한 목록입니다.

** `cognitoIdentityId` **  
호출자의 Amazon Cognito 자격 증명 ID입니다.

** `cognitoIdentityPoolId` **  
호출자와 연결된 Amazon Cognito 자격 증명 풀 ID입니다.

** `defaultAuthStrategy` **  
이 호출자의 기본 권한 부여 전략(`ALLOW` 또는 `DENY`)입니다.

** `issuer` **  
토큰 발행자입니다.

** `sourceIp` **  
가 AWS AppSync 수신하는 호출자의 소스 IP 주소입니다. 요청에 `x-forwarded-for` 헤더가 포함되어 있지 않으면 소스 IP 값에 TCP 연결의 단일 IP 주소만 포함됩니다. 요청에 `x-forwarded-for` 헤더가 포함되어 있으면 소스 IP는 TCP 연결의 IP 주소 이외에 `x-forwarded-for` 헤더의 IP 주소 목록입니다.

** `sub` **  
인증된 사용자의 UUID입니다.

** `user` **  
IAM 사용자입니다.

** `userArn` **  
IAM 사용자의 Amazon 리소스 이름(ARN)입니다.

** `username` **  
인증된 사용자의 사용자 이름입니다. `AMAZON_COGNITO_USER_POOLS` 권한 부여 시 *username*의 값은 *cognito:username* 속성의 값입니다. `AWS_IAM` 권한 부여의 경우 *사용자 이름*의 값은 AWS 사용자 보안 주체의 값입니다. Amazon Cognito 자격 증명 풀에서 판매된 자격 증명으로 IAM 인증을 사용하는 경우 `cognitoIdentityId`를 사용하는 것이 좋습니다.

### 요청 헤더에 액세스
<a name="aws-appsync-resolver-context-reference-util"></a>

AWS AppSync는 클라이언트에서 사용자 지정 헤더를 전달하고를 사용하여 GraphQL 해석기에서 액세스할 수 있도록 지원합니다`$context.request.headers`. 그런 다음 데이터 소스에 데이터 삽입 또는 권한 부여 검사 등과 같은 작업에 헤더 값을 사용할 수 있습니다. 다음 예에 표시된 것처럼 명령줄에서 API 키와 함께 `$curl`을 사용하여 단일 또는 다중 요청 헤더를 사용할 수 있습니다.

**단일 헤더의 예** 

다음과 같이 값이 `nadia`인 `custom`의 헤더를 설정한다고 가정해 보겠습니다.

```
curl -XPOST -H "Content-Type:application/graphql" -H "custom:nadia" -H "x-api-key:<API-KEY-VALUE>" -d '{"query":"mutation { createEvent(name: \"demo\", when: \"Next Friday!\", where: \"Here!\") {id name when where description}}"}' https://<ENDPOINT>/graphql
```

그러면 `$context.request.headers.custom`을 사용하여 이 헤더에 액세스할 수 있습니다. 예를 들어, DynamoDB에 대한 다음 VTL에 있을 수 있습니다.

```
"custom": $util.dynamodb.toDynamoDBJson($context.request.headers.custom)
```

**다중 헤더의 예** 

또한 단일 요청에서 여러 헤더를 전달하고 해석기 매핑 템플릿에서 이러한 헤더에 액세스할 수 있습니다. 예를 들어, `custom` 헤더가 다음 두 값으로 설정되어 있는 경우:

```
curl -XPOST -H "Content-Type:application/graphql" -H "custom:bailey" -H "custom:nadia" -H "x-api-key:<API-KEY-VALUE>" -d '{"query":"mutation { createEvent(name: \"demo\", when: \"Next Friday!\", where: \"Here!\") {id name when where description}}"}' https://<ENDPOINT>/graphql
```

이러한 두 값에는 배열(예: `$context.request.headers.custom[1]`)로 액세스할 수 있습니다.

**참고**  
AWS AppSync 는에 쿠키 헤더를 노출하지 않습니다`$context.request.headers`.

### 사용자 지정 도메인 이름 요청 액세스
<a name="aws-access-requested-custom-domain-names"></a>

AWS AppSync 는 APIs의 GraphQL 및 실시간 엔드포인트에 액세스하는 데 사용할 수 있는 사용자 지정 도메인 구성을 지원합니다. 사용자 지정 도메인 이름으로 요청하는 경우 `$context.request.domainName`을 사용하여 도메인 이름을 가져올 수 있습니다.

기본 GraphQL 엔드포인트 도메인 이름을 사용하는 경우 값은 `null`입니다.

### 정보
<a name="aws-appsync-resolver-context-reference-info"></a>

이 `info` 섹션에는 GraphQL 요청에 대한 정보가 포함되어 있습니다. 이 섹션은 다음과 같은 형식으로 되어 있습니다.

```
{
    "fieldName": "string",
    "parentTypeName": "string",
    "variables": { ... },
    "selectionSetList": ["string"],
    "selectionSetGraphQL": "string"
}
```

각 필드는 다음과 같이 정의됩니다.

** `fieldName` **  
현재 확인 중인 필드의 이름입니다.

** `parentTypeName` **  
현재 확인 중인 필드에 대한 상위 유형의 이름입니다.

** `variables` **  
GraphQL 요청에 전달된 모든 변수를 포함하는 맵입니다.

** `selectionSetList` **  
GraphQL 선택 세트에 있는 필드의 목록 표현입니다. 별칭이 있는 필드는 필드 이름이 아닌 별칭 이름으로만 참조됩니다. 다음 예제는 이 구조를 자세히 보여 줍니다.

** `selectionSetGraphQL` **  
GraphQL 스키마 정의 언어(SDL)로 형식이 지정된 선택 세트의 문자열 표현입니다. 조각이 선택 세트에 병합되지는 않지만 다음 예제와 같이 인라인 조각은 유지됩니다.

**참고**  
`context.info`에서 `$utils.toJson()`을 사용하는 경우 `selectionSetGraphQL` 및 `selectionSetList`가 반환하는 값은 기본적으로 직렬화되지 않습니다.

예를 들어, 다음 쿼리의 `getPost` 필드를 해석하는 경우:

```
query {
  getPost(id: $postId) {
    postId
    title
    secondTitle: title
    content
    author(id: $authorId) {
      authorId
      name
    }
    secondAuthor(id: "789") {
      authorId
    }
    ... on Post {
      inlineFrag: comments: {
        id
      }
    }
    ... postFrag
  }
}

fragment postFrag on Post {
  postFrag: comments: {
    id
  }
}
```

매핑 템플릿을 처리할 때 사용할 수 있는 전체 `$context.info` 변수는 다음과 같습니다.

```
{
  "fieldName": "getPost",
  "parentTypeName": "Query",
  "variables": {
    "postId": "123",
    "authorId": "456"
  },
  "selectionSetList": [
    "postId",
    "title",
    "secondTitle"
    "content",
    "author",
    "author/authorId",
    "author/name",
    "secondAuthor",
    "secondAuthor/authorId",
    "inlineFragComments",
    "inlineFragComments/id",
    "postFragComments",
    "postFragComments/id"
  ],
  "selectionSetGraphQL": "{\n  getPost(id: $postId) {\n    postId\n    title\n    secondTitle: title\n    content\n    author(id: $authorId) {\n      authorId\n      name\n    }\n    secondAuthor(id: \"789\") {\n      authorId\n    }\n    ... on Post {\n      inlineFrag: comments {\n        id\n      }\n    }\n    ... postFrag\n  }\n}"
}
```

`selectionSetList`는 현재 유형에 속하는 필드만 노출합니다. 현재 유형이 인터페이스 또는 집합인 경우 인터페이스에 속하는 선택된 필드만 노출됩니다. 예를 들어 다음과 같은 스키마가 있습니다.

```
type Query {
    node(id: ID!): Node
}

interface Node {
    id: ID
}

type Post implements Node {
    id: ID
    title: String
    author: String
}

type Blog implements Node {
    id: ID
    title: String
    category: String
}
```

그리고 다음과 같은 쿼리가 있습니다.

```
query {
    node(id: "post1") {
        id
        ... on Post {
            title
        }

        ... on Blog {
            title
        }
    }
}
```

`Query.node` 필드 해상도에서 `$ctx.info.selectionSetList`를 호출하면 `id`만 노출됩니다.

```
"selectionSetList": [
    "id"
]
```

## 입력 삭제
<a name="sanitizing-inputs"></a>

애플리케이션은 외부 대상이 원래 목적 외에 애플리케이션을 사용하지 못하도록 신뢰할 수 없는 입력을 삭제해야 합니다. `$context`에는 `$context.arguments`, `$context.identity`, `$context.result`, `$context.info.variables` 및 `$context.request.headers`와 같은 속성의 사용자 입력이 포함되어 있으므로 매핑 템플릿에서 해당 값을 삭제하는 데 주의를 기울여야 합니다.

매핑 템플릿은 JSON을 나타내므로, 입력 삭제는 사용자 입력을 나타내는 문자열에서 JSON 예약 문자를 이스케이프 처리하는 형식을 사용합니다. 매핑 템플릿에 배치할 때 민감한 문자열 값에서 JSON 예약 문자를 이스케이프 처리하는 데 `$util.toJson()` 유틸리티를 사용하는 것이 좋습니다.

예를 들어 다음의 Lambda 요청 매핑 템플릿에서 안전하지 않은 고객 입력 문자열(`$context.arguments.id`)에 액세스했기 때문에 이스케이프 처리되지 않은 JSON 문자가 JSON 템플릿을 손상시키지 않도록 `$util.toJson()`으로 이 문자열을 래핑했습니다.

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "postId": $util.toJson($context.arguments.id)
    }
}
```

아래의 매핑 템플릿과는 반대로, 삭제 없이 `$context.arguments.id`를 직접 삽입합니다. 이러한 작업은 이스케이프 처리되지 않은 따옴표 또는 다른 JSON 예약 문자가 포함되어 있는 문자열에는 사용할 수 없으며, 수행할 경우 템플릿을 열지 못할 수도 있습니다.

```
## DO NOT DO THIS
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "postId": "$context.arguments.id" ## Unsafe! Do not insert $context string values without escaping JSON characters.
    }
}
```