

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

# 에서 AWS Lambda 해석기 사용 AWS AppSync
<a name="tutorial-lambda-resolvers-js"></a>

를 AWS AppSync AWS Lambda 와 함께 사용하여 모든 GraphQL 필드를 확인할 수 있습니다. 예를 들어, GraphQL 쿼리는 Amazon Relational Database Service(Amazon RDS) 인스턴스로 호출을 보내고, GraphQL 뮤테이션은 Amazon Kinesis 스트림에 쓸 수 있습니다. 이 단원에서는 GraphQL 필드 작업의 호출에 따라 비즈니스 로직을 수행하는 Lambda 함수의 작성 방법을 설명합니다.

## 용 Powertools AWS Lambda
<a name="powertools-graphql"></a>

Powertools for AWS Lambda GraphQL 이벤트 핸들러는 Lambda 함수에서 GraphQL 이벤트의 라우팅 및 처리를 간소화합니다. 이는 Python 및 Typescript에서 사용할 수 있습니다. AWS Lambda 설명서용 Powertools의 GraphQL API 이벤트 핸들러에 대한 자세한 내용은 다음 참조를 참조하세요.
+ [Powertools for AWS Lambda GraphQL 이벤트 핸들러(Python) ](https://docs.aws.amazon.com/powertools/python/latest/core/event_handler/appsync/)
+ [Powertools for AWS Lambda GraphQL 이벤트 핸들러(Typescript)](https://docs.aws.amazon.com/powertools/typescript/latest/features/event-handler/appsync-graphql/) 

## Lambda 함수 생성
<a name="create-a-lam-function-js"></a>

다음 예는 블로그 게시물 애플리케이션의 일부로 블로그 게시물에 대해 다양한 연산을 수행하는 `Node.js`(런타임: Node.js 18.x)로 작성된 Lambda 함수를 보여줍니다. 단, 코드는 확장명이.mis인 파일 이름에 저장해야 합니다.

```
export const handler = async (event) => {
console.log('Received event {}', JSON.stringify(event, 3))

  const posts = {
1: { id: '1', title: 'First book', author: 'Author1', url: 'https://amazon.com/', content: 'SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1', ups: '100', downs: '10', },
    2: { id: '2', title: 'Second book', author: 'Author2', url: 'https://amazon.com', content: 'SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT', ups: '100', downs: '10', },
    3: { id: '3', title: 'Third book', author: 'Author3', url: null, content: null, ups: null, downs: null },
    4: { id: '4', title: 'Fourth book', author: 'Author4', url: 'https://www.amazon.com/', content: 'SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4', ups: '1000', downs: '0', },
    5: { id: '5', title: 'Fifth book', author: 'Author5', url: 'https://www.amazon.com/', content: 'SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT', ups: '50', downs: '0', },
  }

  const relatedPosts = {
1: [posts['4']],
    2: [posts['3'], posts['5']],
    3: [posts['2'], posts['1']],
    4: [posts['2'], posts['1']],
    5: [],
  }

  console.log('Got an Invoke Request.')
  let result
  switch (event.field) {
case 'getPost':
      return posts[event.arguments.id]
    case 'allPosts':
      return Object.values(posts)
    case 'addPost':
      // return the arguments back
return event.arguments
    case 'addPostErrorWithData':
      result = posts[event.arguments.id]
      // attached additional error information to the post
      result.errorMessage = 'Error with the mutation, data has changed'
      result.errorType = 'MUTATION_ERROR'
return result
    case 'relatedPosts':
      return relatedPosts[event.source.id]
    default:
      throw new Error('Unknown field, unable to resolve ' + event.field)
  }
}
```

Lambda 함수는 ID별로 게시물을 검색하고, 게시물을 추가하고, 게시물 목록을 가져오고, 지정된 게시물에 대해 관련 게시물을 가져오는 작업을 처리합니다.

**참고**  
참고: `event.field`에 대해 `switch` 명령문을 사용하면 Lambda 함수가 현재 해석 중인 필드를 확인할 수 있습니다.

 AWS 관리 콘솔을 사용하여이 Lambda 함수를 생성합니다.

## Lambda용 데이터 소스 구성
<a name="configure-data-source-for-lamlong-js"></a>

Lambda 함수를 만든 후 AWS AppSync 콘솔에서 GraphQL API로 이동한 다음 **데이터 소스** 탭을 선택합니다.

**데이터 소스 생성**을 선택하고 친숙한 **데이터 소스 이름**(예: **Lambda**)을 입력한 다음 **데이터 소스 유형**에서 **AWS Lambda 함수**를 선택합니다. **리전**에서 함수와 동일한 리전을 선택합니다. **함수 ARN**의 경우, Lambda 함수의 Amazon Resource Name(ARN)을 선택합니다.

Lambda 함수를 선택한 후 새 AWS Identity and Access Management (IAM) 역할( AWS AppSync가 적절한 권한을 할당하는 역할)을 생성하거나 다음 인라인 정책이 있는 기존 역할을 선택할 수 있습니다.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": "arn:aws:lambda:us-east-1:111122223333:function:LAMBDA_FUNCTION"
        }
    ]
}
```

------

또한 다음과 같이 IAM 역할에 대해 AWS AppSync와의 신뢰 관계를 설정해야 합니다.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "appsync.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

------

## GraphQL 스키마 생성
<a name="creating-a-graphql-schema-js"></a>

이제 데이터 소스가 Lambda 함수에 연결되었으며 GraphQL 스키마를 생성해 보겠습니다.

 AWS AppSync 콘솔의 스키마 편집기에서 스키마가 다음 스키마와 일치하는지 확인합니다.

```
schema {
    query: Query
    mutation: Mutation
}
type Query {
    getPost(id:ID!): Post
    allPosts: [Post]
}
type Mutation {
    addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!
}
type Post {
    id: ID!
    author: String!
    title: String
    content: String
    url: String
    ups: Int
    downs: Int
    relatedPosts: [Post]
}
```

## 해석기 구성
<a name="configuring-resolvers-js"></a>

이제 Lambda 데이터 소스와 유효한 GraphQL 스키마를 등록했으며, 해석기를 사용하여 GraphQL 필드를 Lambda 데이터 소스에 연결할 수 있습니다.

 AWS AppSync JavaScript(`APPSYNC_JS`) 런타임을 사용하고 Lambda 함수와 상호 작용하는 해석기를 생성합니다. JavaScript를 사용하여 AWS AppSync 해석기 및 함수를 작성하는 방법에 대한 자세한 내용은 [해석기 및 함수에 대한 JavaScript 런타임 기능을](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html) 참조하세요.

Lambda 매핑 템플릿에 대한 자세한 내용은 [Lambda용 JavaScript 해석기 함수 참조](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-lambda-js.html)를 참조하세요.

이 단계에서는 `getPost(id:ID!): Post`, `allPosts: [Post]`, `addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!`, `Post.relatedPosts: [Post]` 필드에 대한 해석기를 Lambda 함수에 연결합니다. AWS AppSync 콘솔의 **스키마** 편집기의 **해석기** 창에서 `getPost(id:ID!): Post` 필드 옆에 있는 **연결을** 선택합니다. Lambda 데이터 소스를 선택합니다. 그런 다음, 다음 코드를 제공합니다.

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const {source, args} = ctx
  return {
    operation: 'Invoke',
    payload: { field: ctx.info.fieldName, arguments: args, source },
  };
}

export function response(ctx) {
  return ctx.result;
}
```

이 해석기 코드는 Lambda 함수를 호출할 때 필드 이름, 인수 목록, 소스 객체에 대한 컨텍스트를 Lambda 함수에 전달합니다. **저장**을 선택합니다.

이제 첫 번째 해석기를 성공적으로 연결했습니다. 나머지 필드에 대해 이 작업을 반복합니다.

## GraphQL API 테스트
<a name="testing-your-graphql-api-js"></a>

Lambda 함수가 GraphQL 해석기에 연결되었으므로 콘솔이나 클라이언트 애플리케이션을 사용하여 뮤테이션 및 쿼리를 실행할 수 있습니다.

 AWS AppSync 콘솔 왼쪽에서 **쿼리**를 선택한 다음 다음 코드를 붙여 넣습니다.

### addPost 변형
<a name="addpost-mutation-js"></a>

```
mutation AddPost {
    addPost(
        id: 6
        author: "Author6"
        title: "Sixth book"
        url: "https://www.amazon.com/"
        content: "This is the book is a tutorial for using GraphQL with AWS AppSync."
    ) {
        id
        author
        title
        content
        url
        ups
        downs
    }
}
```

### getPost 쿼리
<a name="getpost-query-js"></a>

```
query GetPost {
    getPost(id: "2") {
        id
        author
        title
        content
        url
        ups
        downs
    }
}
```

### allPosts 쿼리
<a name="allposts-query-js"></a>

```
query AllPosts {
    allPosts {
        id
        author
        title
        content
        url
        ups
        downs
        relatedPosts {
            id
            title
        }
    }
}
```

## 오류 반환
<a name="returning-errors-js"></a>

필드 해상도를 지정하면 오류가 발생할 수 있습니다. AWS AppSync를 사용하면 다음 소스에서 오류가 발생할 수 있습니다.
+ 해석기 응답 핸들러
+ Lambda 함수

### 해석기 응답 핸들러에서
<a name="from-the-resolver-response-handler-js"></a>

의도적인 오류를 발생시키려면 `util.error` 유틸리티 메서드를 사용하면 됩니다. `errorMessage`, `errorType` 및 선택적 `data` 값을 인수로 사용합니다. `data`는 오류가 발생한 경우 외부 데이터를 클라이언트로 반환할 때 유용합니다. GraphQL 최종 응답에서 `errors`에 `data` 객체가 추가됩니다.

다음 예시는 `Post.relatedPosts: [Post]` 해석기 응답 핸들러에서 이를 사용하는 방법을 보여줍니다.

```
// the Post.relatedPosts response handler
export function response(ctx) {
    util.error("Failed to fetch relatedPosts", "LambdaFailure", ctx.result)
    return ctx.result;
}
```

다음과 유사한 GraphQL 응답이 산출됩니다.

```
{
    "data": {
        "allPosts": [
            {
                "id": "2",
                "title": "Second book",
                "relatedPosts": null
            },
            ...
        ]
    },
    "errors": [
        {
            "path": [
                "allPosts",
                0,
                "relatedPosts"
            ],
            "errorType": "LambdaFailure",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ],
            "message": "Failed to fetch relatedPosts",
            "data": [
                {
                  "id": "2",
                  "title": "Second book"
                },
                {
                  "id": "1",
                  "title": "First book"
                }
            ]
        }
    ]
}
```

여기서 `allPosts[0].relatedPosts`는 오류로 인해 *null*이며 `errorMessage`, `errorType` 및 `data`가 `data.errors[0]` 객체 안에 있습니다.

### Lambda 함수에서
<a name="from-the-lam-function-js"></a>

AWS AppSync는 Lambda 함수에서 발생하는 오류도 이해합니다. Lambda 프로그래밍 모델은 *handled* 오류를 발생시킵니다. Lambda 함수에서 오류가 발생하는 경우 AWS AppSync에서 현재 필드가 해석되지 않습니다. Lambda에서 반환되는 오류 메시지만 응답에 설정됩니다. 현재는 Lambda 함수에서 오류를 발생시켜 관련 없는 데이터를 클라이언트에 다시 전달할 수 없습니다.

**참고**  
Lambda 함수가 *unhandled* 오류를 발생시키는 경우 AWS AppSync는 Lambda에서 설정한 오류 메시지를 사용합니다.

다음 Lambda 함수는 오류를 발생시킵니다.

```
export const handler = async (event) => {
  console.log('Received event {}', JSON.stringify(event, 3))
  throw new Error('I always fail.')
}
```

응답 핸들러에 오류가 수신되었습니다. `util.appendError`로 응답에 오류를 추가하여 GraphQL 응답으로 다시 보낼 수 있습니다. 이렇게 하려면 AWS AppSync 함수 응답 핸들러를 다음과 같이 변경합니다.

```
// the lambdaInvoke response handler
export function response(ctx) {
  const { error, result } = ctx;
  if (error) {
    util.appendError(error.message, error.type, result);
  }
  return result;
}
```

다음과 유사한 GraphQL 응답이 반환됩니다.

```
{
  "data": {
    "allPosts": null
  },
  "errors": [
    {
      "path": [
        "allPosts"
      ],
      "data": null,
      "errorType": "Lambda:Unhandled",
      "errorInfo": null,
      "locations": [
        {
          "line": 2,
          "column": 3,
          "sourceName": null
        }
      ],
      "message": "I fail. always"
    }
  ]
}
```

## 고급 사용 사례: 일괄 처리
<a name="advanced-use-case-batching-js"></a>

이 예제의 Lambda 함수에는 해당 게시물에 대한 관련 게시물 목록을 반환하는 `relatedPosts` 필드가 있습니다. 예제 쿼리에서 Lambda 함수의 `allPosts` 필드 호출은 5개 게시물을 반환합니다. 각각의 반환된 게시물에 대해 `relatedPosts`를 해석하도록 지정했으므로 `relatedPosts` 필드 작업이 5회 호출됩니다.

```
query {
    allPosts {   // 1 Lambda invocation - yields 5 Posts
        id
        author
        title
        content
        url
        ups
        downs
        relatedPosts {   // 5 Lambda invocations - each yields 5 posts
            id
            title
        }
    }
}
```

이 특정 예제에서는 큰 문제가 되지 않을 수 있지만, 이러한 복합적이고 과도한 가져오기로 인해 애플리케이션이 빠르게 손상될 수 있습니다.

동일한 쿼리에서 반환된 관련 `Posts`에 대해 `relatedPosts`를 다시 가져오려 할 경우 호출 횟수가 크게 증가할 것입니다.

```
query {
    allPosts {   // 1 Lambda invocation - yields 5 Posts
        id
        author
        title
        content
        url
        ups
        downs
        relatedPosts {   // 5 Lambda invocations - each yield 5 posts = 5 x 5 Posts
            id
            title
            relatedPosts {  // 5 x 5 Lambda invocations - each yield 5 posts = 25 x 5 Posts
                id
                title
                author
            }
        }
    }
}
```

이 비교적 간단한 쿼리에서 AWS AppSync는 Lambda 함수 1 \$1 5 \$1 25 = 31회를 호출합니다.

이는 상당히 일반적인 문제로 대개 N\$11 문제(이 경우에 N = 5)라고도 하며 이로 인해 애플리케이션의 지연 시간 및 비용이 증가될 수 있습니다.

이 문제를 해결하는 한 가지 방법은 유사한 필드 해석기 요청을 하나로 묶는 것입니다. 이 예제에서는 지정된 단일 게시물에 대한 관련 게시물 목록을 해석하는 Lambda 함수 하나 대신에, 해당 게시물 배치에 대한 관련 게시물 목록을 해석합니다.

이를 설명하기 위해 일괄 처리를 처리하도록 `relatedPosts`의 해석기를 업데이트해 보겠습니다.

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const {source, args} = ctx
  return {
    operation: ctx.info.fieldName === 'relatedPosts' ? 'BatchInvoke' : 'Invoke',
    payload: { field: ctx.info.fieldName, arguments: args, source },
  };
}

export function response(ctx) {
  const { error, result } = ctx;
  if (error) {
    util.appendError(error.message, error.type, result);
  }
  return result;
}
```

이제 이 코드는 해석 중인 `fieldName`이 `relatedPosts`일 때 작업을 `Invoke`에서 `BatchInvoke`로 변경합니다. 이제 **일괄 처리 구성** 섹션에서 함수에 대한 일괄 처리를 활성화합니다. 설정된 최대 일괄 처리 크기를 `5`로 설정합니다. **저장**을 선택합니다.

이 변경으로 Lambda 함수는 `relatedPosts` 해결 시 다음을 입력으로 받습니다.

```
[
    {
        "field": "relatedPosts",
        "source": {
            "id": 1
        }
    },
    {
        "field": "relatedPosts",
        "source": {
            "id": 2
        }
    },
    ...
]
```

`BatchInvoke`가 요청에 지정되었으면 Lambda 함수가 요청 목록을 수신하고 결과 목록을 반환합니다.

특히 결과 목록은 요청 페이로드 항목의 크기 및 순서와 일치해야 AWS AppSync가 그에 따라 결과를 일치시킬 수 있습니다.

이 일괄 처리 예제에서 Lambda 함수는 다음과 같이 결과의 배치를 반환합니다.

```
[
    [{"id":"2","title":"Second book"}, {"id":"3","title":"Third book"}],   // relatedPosts for id=1
    [{"id":"3","title":"Third book"}]                                     // relatedPosts for id=2
]
```

Lambda 코드를 업데이트하여 `relatedPosts`에 대한 일괄 처리를 처리할 수 있습니다.

```
export const handler = async (event) => {
  console.log('Received event {}', JSON.stringify(event, 3))
  //throw new Error('I fail. always')

  const posts = {
    1: { id: '1', title: 'First book', author: 'Author1', url: 'https://amazon.com/', content: 'SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1', ups: '100', downs: '10', },
    2: { id: '2', title: 'Second book', author: 'Author2', url: 'https://amazon.com', content: 'SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT', ups: '100', downs: '10', },
    3: { id: '3', title: 'Third book', author: 'Author3', url: null, content: null, ups: null, downs: null },
    4: { id: '4', title: 'Fourth book', author: 'Author4', url: 'https://www.amazon.com/', content: 'SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4', ups: '1000', downs: '0', },
    5: { id: '5', title: 'Fifth book', author: 'Author5', url: 'https://www.amazon.com/', content: 'SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT', ups: '50', downs: '0', },
  }

  const relatedPosts = {
    1: [posts['4']],
    2: [posts['3'], posts['5']],
    3: [posts['2'], posts['1']],
    4: [posts['2'], posts['1']],
    5: [],
  }
  
  if (!event.field && event.length){
    console.log(`Got a BatchInvoke Request. The payload has ${event.length} items to resolve.`);
    return event.map(e => relatedPosts[e.source.id])
  }

  console.log('Got an Invoke Request.')
  let result
  switch (event.field) {
    case 'getPost':
      return posts[event.arguments.id]
    case 'allPosts':
      return Object.values(posts)
    case 'addPost':
      // return the arguments back
      return event.arguments
    case 'addPostErrorWithData':
      result = posts[event.arguments.id]
      // attached additional error information to the post
      result.errorMessage = 'Error with the mutation, data has changed'
      result.errorType = 'MUTATION_ERROR'
      return result
    case 'relatedPosts':
      return relatedPosts[event.source.id]
    default:
      throw new Error('Unknown field, unable to resolve ' + event.field)
  }
}
```

### 개별 오류 반환
<a name="returning-individual-errors-js"></a>

앞의 예에서는 Lambda 함수에서 단일 오류가 반환되거나 응답 핸들러에서 오류를 일으킬 수 있음을 보았습니다. 일괄 처리된 호출의 경우, Lambda 함수에서 오류가 발생하면 전체 배치가 실패로 플래그 지정됩니다. 이는 데이터 스토어와의 연결 중단 같은 취소 불가능한 오류가 발생하는 특정 시나리오를 잘 설명할 수 있습니다. 하지만 배치의 일부 항목이 성공하고 다른 항목이 실패하는 경우, 오류 및 유효한 데이터를 모두 반환할 수 있습니다. AWS AppSync에서는 배치의 원래 크기와 일치하는 요소를 나열하기 위해 배치 응답이 필요하므로 유효한 데이터와 오류를 구분할 수 있는 데이터 구조를 사용자가 정의해야 합니다.

예를 들어 Lambda 함수가 관련 게시물의 일괄 처리를 반환해야 하는 경우 각 객체에 선택적 *data*, *errorMessage* 및 *errorType* 필드가 있는 `Response` 객체 목록을 반환하도록 선택할 수 있습니다. *errorMessage* 필드가 있는 경우 오류가 발생했음을 의미합니다.

다음 코드는 Lambda 함수를 업데이트하는 방법을 보여줍니다.

```
export const handler = async (event) => {
console.log('Received event {}', JSON.stringify(event, 3))
  // throw new Error('I fail. always')
const posts = {
1: { id: '1', title: 'First book', author: 'Author1', url: 'https://amazon.com/', content: 'SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1', ups: '100', downs: '10', },
    2: { id: '2', title: 'Second book', author: 'Author2', url: 'https://amazon.com', content: 'SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT', ups: '100', downs: '10', },
    3: { id: '3', title: 'Third book', author: 'Author3', url: null, content: null, ups: null, downs: null },
    4: { id: '4', title: 'Fourth book', author: 'Author4', url: 'https://www.amazon.com/', content: 'SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4', ups: '1000', downs: '0', },
    5: { id: '5', title: 'Fifth book', author: 'Author5', url: 'https://www.amazon.com/', content: 'SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT', ups: '50', downs: '0', },
  }

  const relatedPosts = {
1: [posts['4']],
    2: [posts['3'], posts['5']],
    3: [posts['2'], posts['1']],
    4: [posts['2'], posts['1']],
    5: [],
  }
  
  if (!event.field && event.length){
console.log(`Got a BatchInvoke Request. The payload has ${event.length} items to resolve.`);
    return event.map(e => {
// return an error for post 2
if (e.source.id === '2') {
return { 'data': null, 'errorMessage': 'Error Happened', 'errorType': 'ERROR' }
      }
      return {data: relatedPosts[e.source.id]}
      })
  }

  console.log('Got an Invoke Request.')
  let result
  switch (event.field) {
case 'getPost':
      return posts[event.arguments.id]
    case 'allPosts':
      return Object.values(posts)
    case 'addPost':
      // return the arguments back
return event.arguments
    case 'addPostErrorWithData':
      result = posts[event.arguments.id]
      // attached additional error information to the post
      result.errorMessage = 'Error with the mutation, data has changed'
      result.errorType = 'MUTATION_ERROR'
return result
    case 'relatedPosts':
      return relatedPosts[event.source.id]
    default:
      throw new Error('Unknown field, unable to resolve ' + event.field)
  }
}
```

`relatedPosts` 해석기 코드 업데이트:

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const {source, args} = ctx
  return {
    operation: ctx.info.fieldName === 'relatedPosts' ? 'BatchInvoke' : 'Invoke',
    payload: { field: ctx.info.fieldName, arguments: args, source },
  };
}

export function response(ctx) {
  const { error, result } = ctx;
  if (error) {
    util.appendError(error.message, error.type, result);
  } else if (result.errorMessage) {
    util.appendError(result.errorMessage, result.errorType, result.data)
  } else if (ctx.info.fieldName === 'relatedPosts') {
      return result.data
  } else {
      return result
  }
}
```

이제 응답 핸들러는 `Invoke` 작업에 대해 Lambda 함수가 반환한 오류를 확인하고, `BatchInvoke` 작업에서 개별 항목에 대해 반환한 오류를 확인한 다음, 마지막으로 `fieldName`을 확인합니다. `relatedPosts`의 경우 함수는 `result.data`를 반환합니다. 다른 모든 필드의 경우 함수가 `result`를 반환합니다. 그 예로, 아래 쿼리를 살펴보겠습니다.

```
query AllPosts {
  allPosts {
    id
    title
    content
    url
    ups
    downs
    relatedPosts {
      id
    }
    author
  }
}
```

이 쿼리는 다음과 유사한 GraphQL 응답을 반환합니다.

```
{
  "data": {
    "allPosts": [
      {
        "id": "1",
        "relatedPosts": [
          {
            "id": "4"
          }
        ]
      },
      {
        "id": "2",
        "relatedPosts": null
      },
      {
        "id": "3",
        "relatedPosts": [
          {
            "id": "2"
          },
          {
            "id": "1"
          }
        ]
      },
      {
        "id": "4",
        "relatedPosts": [
          {
            "id": "2"
          },
          {
            "id": "1"
          }
        ]
      },
      {
        "id": "5",
        "relatedPosts": []
      }
    ]
  },
  "errors": [
    {
      "path": [
        "allPosts",
        1,
        "relatedPosts"
      ],
      "data": null,
      "errorType": "ERROR",
      "errorInfo": null,
      "locations": [
        {
          "line": 4,
          "column": 5,
          "sourceName": null
        }
      ],
      "message": "Error Happened"
    }
  ]
}
```

### 최대 배치 크기 구성
<a name="configure-max-batch-size-js"></a>

해석기에서 최대 배치 크기를 구성하려면 AWS Command Line Interface (AWS CLI)에서 다음 명령을 사용합니다.

```
$ aws appsync create-resolver --api-id <api-id> --type-name Query --field-name relatedPosts \
 --code "<code-goes-here>" \
 --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
 --data-source-name "<lambda-datasource>" \ 
 --max-batch-size X
```

**참고**  
요청 매핑 템플릿을 제공할 때는 `BatchInvoke` 작업을 사용하여 일괄 처리를 사용해야 합니다.