

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

# AWS AppSync에서 파이프라인 해석기 사용
<a name="tutorial-pipeline-resolvers"></a>

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

AWS AppSync는 단위 해석기를 통해 GraphQL 필드를 단일 데이터 소스에 연결하는 간단한 방법을 제공합니다. 그러나 단일 작업을 실행하는 것만으로는 충분하지 않을 수 있습니다. 파이프라인 해석기는 데이터 원본에 대해 작업을 순차적으로 실행하는 기능을 제공합니다. API에서 함수를 생성하고 파이프라인 해석기에 해당 작업을 연결합니다. 각 함수 실행 결과는 실행할 함수가 없을 때까지 다음으로 전송됩니다. 파이프라인 해석기를 사용하면 이제 AWS AppSync에서 직접 더 복잡한 워크플로를 구축할 수 있습니다. 이 자습서에서는 사용자가 사진을 게시하고, 친구들이 공유한 사진을 볼 수 있는 간단한 사진 보기 앱을 빌드합니다.

## 원클릭 설치
<a name="one-click-setup"></a>

모든 해석기가 구성되고 필요한 AWS 리소스가 포함된 GraphQL 엔드포인트를 AWS AppSync에서 자동으로 설정하려면 다음 템플릿을 사용할 AWS CloudFormation 수 있습니다.

[https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/pipeline/pipeline-resolvers-full.yaml](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/pipeline/pipeline-resolvers-full.yaml)

이 스택은 계정에 다음 리소스를 생성합니다.
+ 계정의 리소스에 액세스하기 위한 AWS AppSync의 IAM 역할
+ DynamoDB 테이블 2개
+ Amazon Cognito 사용자 풀 1개
+ Amazon Cognito 사용자 풀 그룹 2개
+ Amazon Cognito 사용자 풀 사용자 3명
+ 1 AWS AppSync API

 AWS CloudFormation 스택 생성 프로세스가 끝나면 생성된 세 명의 Amazon Cognito 사용자 각각에 대해 하나의 이메일을 받게 됩니다. 각 이메일에는 AWS AppSync 콘솔에 Amazon Cognito 사용자로 로그인하는 데 사용하는 임시 암호가 포함되어 있습니다. 자습서의 나머지 부분에서 사용할 수 있도록 암호를 저장해 둡니다.

## 수동 설정
<a name="manual-setup"></a>

 AWS AppSync 콘솔을 통해 step-by-step 프로세스를 수동으로 진행하려면 아래 설정 프로세스를 따르세요.

### 비 AWS AppSync 리소스 설정
<a name="setting-up-your-non-aws-appsync-resources"></a>

API는 DynamoDB 테이블 2개 즉, 사진을 저장하는 **사진** 테이블과 사용자 간의 관계를 저장하는 **친구** 테이블과 통신합니다. API는 인증 유형으로 Amazon Cognito 사용자 풀을 사용하도록 구성되어 있습니다. 다음 CloudFormation 스택은 계정에서 이러한 리소스를 설정합니다.

[https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/pipeline/pipeline-resolvers-resources-only.yaml](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/pipeline/pipeline-resolvers-resources-only.yaml)

 AWS CloudFormation 스택 생성 프로세스가 끝나면 생성된 세 명의 Amazon Cognito 사용자 각각에 대해 하나의 이메일을 받게 됩니다. 각 이메일에는 AWS AppSync 콘솔에 Amazon Cognito 사용자로 로그인하는 데 사용하는 임시 암호가 포함되어 있습니다. 자습서의 나머지 부분에서 사용할 수 있도록 암호를 저장해 둡니다.

### GraphQL API 생성
<a name="creating-your-graphql-api"></a>

 AWS AppSync에서 GraphQL API를 생성하려면:

1.  AWS AppSync 콘솔을 열고 **스크래치에서 빌드**를 선택한 다음 **시작**을 선택합니다.

1. API의 이름을 `AppSyncTutorial-PicturesViewer`로 설정합니다.

1. **생성(Create)**을 선택합니다.

 AWS AppSync 콘솔은 API 키 인증 모드를 사용하여 새 GraphQL API를 생성합니다. 콘솔에서 GraphQL API의 나머지 부분을 설정하고 이 자습서의 나머지 부분에서 이 API에 대한 쿼리를 실행할 수 있습니다.

### GraphQL API 구성
<a name="configuring-the-graphql-api"></a>

방금 생성한 Amazon Cognito 사용자 풀로 AWS AppSync API를 구성해야 합니다.

1. **설정** 탭을 선택합니다.

1. **Authorization Type(권한 부여 유형)** 섹션에서 *Amazon Cognito User Pool(Amazon Cognito 사용자 풀)*을 선택합니다.

1. **사용자 풀 구성**에서 *AWS 리전*으로 **US-WEST-2**를 선택합니다.

1. **AppSyncTutorial-UserPool** 사용자 풀을 선택합니다.

1. *기본 작업*으로 **거부**를 선택합니다.

1. **AppId client regex** 필드는 비워둡니다.

1. **저장**을 선택합니다.

이제 API가 인증 유형으로 Amazon Cognito 사용자 풀을 사용하도록 설정되어 있습니다.

### DynamoDB 테이블에 대한 데이터 소스 구성
<a name="configuring-data-sources-for-the-ddb-tables"></a>

DynamoDB 테이블이 생성되면 콘솔에서 AWS AppSync GraphQL API로 이동하여 **데이터 소스** 탭을 선택합니다. 이제 방금 생성한 각 DynamoDB 테이블에 대해 AWS AppSync에서 데이터 소스를 생성합니다.

1. **데이터 원본** 탭을 선택합니다.

1. **새로 만들기**를 선택하여 새 데이터 원본을 생성합니다.

1. 데이터 원본 이름에 `PicturesDynamoDBTable`을 입력합니다.

1. Data Source Type(데이터 원본 유형)으로 **Amazon DynamoDB table(Amazon DynamoDB 테이블)**을 선택합니다.

1. 리전으로 **US-WEST-2**를 선택합니다.

1. 테이블 목록에서 **AppSyncTutorial-Pictures** DynamoDB 테이블을 선택합니다.

1. **새 역할 생성 또는 기존 역할 사용** 섹션에서 **기존 역할**을 선택합니다.

1. CloudFormation 템플릿에서 방금 생성한 역할을 선택합니다. *ResourceNamePrefix*를 변경하지 않은 경우 역할 이름은 **AppSyncTutorial-DynamoDBRole**이어야 합니다.

1. **생성(Create)**을 선택합니다.

**친구** 테이블에 대해 동일한 프로세스를 반복합니다. CloudFormation 스택을 생성할 때 *ResourceNamePrefix* 파라미터를 변경하지 않은 경우 DynamoDB 테이블의 이름은 **AppSyncTutorial-Friends**가 되어야 합니다.

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

이제 데이터 소스가 DynamoDB 테이블에 연결되었으며 GraphQL 스키마를 생성해 보겠습니다. AWS AppSync 콘솔의 스키마 편집기에서 스키마가 다음 스키마와 일치하는지 확인합니다.

```
schema {
    query: Query
    mutation: Mutation
}

type Mutation {
    createPicture(input: CreatePictureInput!): Picture!
    @aws_auth(cognito_groups: ["Admins"])
    createFriendship(id: ID!, target: ID!): Boolean
    @aws_auth(cognito_groups: ["Admins"])
}

type Query {
    getPicturesByOwner(id: ID!): [Picture]
    @aws_auth(cognito_groups: ["Admins", "Viewers"])
}

type Picture {
    id: ID!
    owner: ID!
    src: String
}

input CreatePictureInput {
    owner: ID!
    src: String!
}
```

스키마를 저장하려면 **Save Schema(스키마 저장)**를 선택합니다.

일부 스키마 필드에는 *@aws\$1auth* 명령으로 주석이 달려 있습니다. API 기본 작업 구성이 *DENY*로 설정되어 있기 때문에 API에서는 *@aws\$1auth* 명령 내에 언급된 그룹의 구성원이 아닌 사용자는 모두 거부합니다. API를 보호하는 방법에 대한 자세한 내용은 [보안](security-authz.md#aws-appsync-security) 페이지를 참조하십시오. 이 경우에는 관리자 사용자만 Mutation.createPicture 및 Mutation.createFriendship 필드에 대한 액세스 권한을 가지고 있으며, Admins 또는 Viewers 그룹의 구성원인 사용자는 Query.getPicturesByOwner 필드에 액세스할 수 있습니다. 다른 모든 사용자는 액세스 권한이 없습니다.

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

이제 유효한 GraphQL 스키마와 데이터 원본이 2개 있으므로 해석기를 스키마에 대한 GraphQL 필드에 연결할 수 있습니다. API는 다음과 같은 기능을 제공합니다.
+ *Mutation.createPicture* 필드를 통해 사진 생성
+ *Mutation.createFriendship* 필드를 통해 친구 관계 생성
+ *Query.getPicture* 필드를 통해 사진 가져오기

#### Mutation.createPicture
<a name="mutation-createpicture"></a>

 AWS AppSync 콘솔의 스키마 편집기에서 오른쪽에서 용 **해석기 연결을** 선택합니다`createPicture(input: CreatePictureInput!): Picture!`. DynamoDB*PicturesDynamoDBTable* 데이터 소스를 선택합니다. **요청 매핑 템플릿** 섹션에 다음 템플릿을 추가합니다.

```
#set($id = $util.autoId())

{
    "version" : "2018-05-29",

    "operation" : "PutItem",

    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($id),
        "owner": $util.dynamodb.toDynamoDBJson($ctx.args.input.owner)
    },

    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args.input)
}
```

**응답 매핑 템플릿** 섹션에 다음 템플릿을 추가합니다.

```
#if($ctx.error)
    $util.error($ctx.error.message, $ctx.error.type)
#end
$util.toJson($ctx.result)
```

사진 생성 기능이 완료되었습니다. 임의로 생성되는 UUID를 사진 ID로, Cognito 사용자 이름을 사진의 소유자로 사용하여 **사진** 테이블에 사진을 저장합니다.

#### Mutation.createFriendship
<a name="mutation-createfriendship"></a>

 AWS AppSync 콘솔의 스키마 편집기에서 오른쪽에서 용 **해석기 연결을** 선택합니다`createFriendship(id: ID!, target: ID!): Boolean`. DynamoDB**FriendsDynamoDBTable** 데이터 소스를 선택합니다. **요청 매핑 템플릿** 섹션에 다음 템플릿을 추가합니다.

```
#set($userToFriendFriendship = { "userId" : "$ctx.args.id", "friendId": "$ctx.args.target" })
#set($friendToUserFriendship = { "userId" : "$ctx.args.target", "friendId": "$ctx.args.id" })
#set($friendsItems = [$util.dynamodb.toMapValues($userToFriendFriendship), $util.dynamodb.toMapValues($friendToUserFriendship)])

{
    "version" : "2018-05-29",
    "operation" : "BatchPutItem",
    "tables" : {
        ## Replace 'AppSyncTutorial-' default below with the ResourceNamePrefix you provided in the CloudFormation template
        "AppSyncTutorial-Friends": $util.toJson($friendsItems)
    }
}
```

중요: **BatchPutItem** 요청 템플릿에 DynamoDB 테이블의 정확한 이름이 있어야 합니다. 기본 테이블 이름은 *AppSyncTutorial-Friends*입니다. 잘못된 테이블 이름을 사용하면 AppSync에서 제공된 역할을 수행하려고 할 때 오류가 발생합니다.

이 자습서에서는 간단한 설명을 위해 친구 관계 요청이 승인되어 친구 관계 항목이 **AppSyncTutorialFriends** 테이블에 직접 저장된 것처럼 진행합니다.

효율적으로, 관계는 양방향이기 때문에 각 친구 관계에 대해 항목 2개를 저장합니다. 다대다 관계를 나타내기 위한 Amazon DynamoDB 모범 사례에 대한 자세한 내용은 [DynamoDB 모범 사례](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-adjacency-graphs.html)를 참조하세요.

**응답 매핑 템플릿** 섹션에 다음 템플릿을 추가합니다.

```
#if($ctx.error)
    $util.error($ctx.error.message, $ctx.error.type)
#end
true
```

참고: 요청 템플릿에 올바른 테이블 이름이 포함되어 있는지 확인합니다. 기본 이름은 *AppSyncTutorial-Friends*인데, CloudFormation **ResourceNamePrefix** 파라미터를 변경한 경우에는 테이블 이름이 약간 다를 수 있습니다.

#### Query.getPicturesByOwner
<a name="query-getpicturesbyowner"></a>

이제, 친구 관계 및 사진이 있으므로 사용자가 친구의 사진을 볼 수 있는 기능을 제공해야 합니다. 이러한 요구 사항을 충족하기 위해 먼저 요청자가 소유자의 친구인지 확인하고 마지막으로 사진을 쿼리해야 합니다.

이 기능에는 두 가지 데이터 원본 작업이 필요하기 때문에 함수 2개를 생성해 보겠습니다. 첫 번째 함수 **isFriend**는 요청자와 소유자가 친구인지 확인합니다. 두 번째 함수 **getPicturesByOwner**는 제공된 소유자 ID를 사용해 요청된 사진을 가져옵니다. 아래에서 *Query.getPicturesByOwner* 필드에 대해 제안된 해석기에 대한 실행 흐름을 살펴보겠습니다.

1. Before 매핑 템플릿: 컨텍스트와 필드 입력 파라미터를 준비합니다.

1. isFriend 함수: 요청자가 사진의 소유자인지 확인합니다. 소유자가 아닌 경우 친구 테이블에 대해 DynamoDB GetItem 작업을 수행하여 요청자와 소유자 사용자가 친구인지 확인합니다.

1. getPicturesByOwner 함수: *owner-index* 글로벌 보조 인덱스에 대한 DynamoDB 쿼리 작업을 사용하여 사진 테이블에서 사진을 검색합니다.

1. After 매핑 템플릿: DynamoDB 속성이 예상되는 GraphQL 유형 필드에 정확하게 매핑되도록 사진 결과를 매핑합니다.

먼저 함수를 생성해 보겠습니다.

##### isFriend 함수
<a name="isfriend-function"></a>

1. **Functions(함수)** 탭을 선택합니다.

1. **Create Function(함수 생성)**을 선택하여 함수를 생성합니다.

1. 데이터 원본 이름에 `FriendsDynamoDBTable`을 입력합니다.

1. 함수 이름으로 *isFriend*를 입력합니다.

1. 요청 매핑 템플릿의 텍스트 영역 내에서 다음 템플릿을 붙여 넣습니다.

   ```
   #set($ownerId = $ctx.prev.result.owner)
   #set($callerId = $ctx.prev.result.callerId)
   
   ## if the owner is the caller, no need to make the check
   #if($ownerId == $callerId)
       #return($ctx.prev.result)
   #end
   
   {
       "version" : "2018-05-29",
   
       "operation" : "GetItem",
   
       "key" : {
           "userId" : $util.dynamodb.toDynamoDBJson($callerId),
           "friendId" : $util.dynamodb.toDynamoDBJson($ownerId)
       }
   }
   ```

1. 응답 매핑 템플릿의 텍스트 영역 내에서 다음 템플릿을 붙여 넣습니다.

   ```
   #if($ctx.error)
       $util.error("Unable to retrieve friend mapping message: ${ctx.error.message}", $ctx.error.type)
   #end
   
   ## if the users aren't friends
   #if(!$ctx.result)
       $util.unauthorized()
   #end
   
   $util.toJson($ctx.prev.result)
   ```

1. **함수 생성**을 선택합니다.

결과: **isFriend** 함수를 생성했습니다.

##### getPicturesByOwner 함수
<a name="getpicturesbyowner-function"></a>

1. **Functions(함수)** 탭을 선택합니다.

1. **Create Function(함수 생성)**을 선택하여 함수를 생성합니다.

1. 데이터 원본 이름에 `PicturesDynamoDBTable`을 입력합니다.

1. 함수 이름으로 `getPicturesByOwner`를 입력합니다.

1. 요청 매핑 템플릿의 텍스트 영역 내에서 다음 템플릿을 붙여 넣습니다.

   ```
   {
       "version" : "2018-05-29",
   
       "operation" : "Query",
   
       "query" : {
           "expression": "#owner = :owner",
           "expressionNames": {
               "#owner" : "owner"
           },
           "expressionValues" : {
               ":owner" : $util.dynamodb.toDynamoDBJson($ctx.prev.result.owner)
           }
       },
   
       "index": "owner-index"
   }
   ```

1. 응답 매핑 템플릿의 텍스트 영역 내에서 다음 템플릿을 붙여 넣습니다.

   ```
   #if($ctx.error)
       $util.error($ctx.error.message, $ctx.error.type)
   #end
   
   $util.toJson($ctx.result)
   ```

1. **함수 생성**을 선택합니다.

결과: **getPicturesByOwner** 함수를 생성했습니다. 이제 함수를 생성했으므로 *Query.getPicturesByOwner* 필드에 파이프라인 해석기를 연결합니다.

 AWS AppSync 콘솔의 스키마 편집기에서 오른쪽에서 용 **해석기 연결을** 선택합니다`Query.getPicturesByOwner(id: ID!): [Picture]`. 다음 페이지에서는 데이터 원본 드롭다운 목록에 아래에 표시되는 **Convert to pipeline resolver(파이프라인 해석기로 변환)** 링크를 선택합니다. Before 매핑 템플릿에 다음을 사용합니다.

```
#set($result = { "owner": $ctx.args.id, "callerId": $ctx.identity.username })
$util.toJson($result)
```

**after mapping template(사후 매핑 템플릿)** 섹션에서 다음을 사용합니다.

```
#foreach($picture in $ctx.result.items)
    ## prepend "src://" to picture.src property
    #set($picture['src'] = "src://${picture['src']}")
#end
$util.toJson($ctx.result.items)
```

**Create Resolver(해석기 생성)**를 선택합니다. 이제 첫 번째 파이프라인 해석기를 성공적으로 연결했습니다. 동일한 페이지에서 이전에 생성한 함수 2개를 추가합니다. 함수 섹션에서 **Add A Function(함수 추가)**를 선택하고 첫 번째 함수의 이름을 선택하거나 **isFriend**를 입력합니다. **getPicturesByOwner** 함수에 대해 동일한 프로세스를 수행하여 두 번째 함수를 추가합니다. **isFriend** 함수가 목록 맨 위에 나타나고 그 다음에 **getPicturesByOwner** 함수가 표시되는지 확인합니다. 위쪽 및 아래쪽 화살표를 사용하여 파이프라이니 내 함수의 실행 순서를 다시 정렬할 수 있습니다.

이제, 파이프라인 해석기가 생성되었고, 함수를 연결했으므로 새로 생성된 GraphQL API를 테스트해보겠습니다.

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

먼저, 생성한 관리자 사용자를 사용하여 몇 가지 변형을 실행해 사진과 친구 관계를 채워야 합니다. AWS AppSync 콘솔 왼쪽에서 **쿼리** 탭을 선택합니다.

### createPicture 변형
<a name="createpicture-mutation"></a>

1.  AWS AppSync 콘솔에서 **쿼리** 탭을 선택합니다.

1. **Login With User Pools(사용자 풀로 로그인)**를 선택합니다.

1. 모달에서 CloudFormation 스택에서 생성한 Cognito 샘플 클라이언트 ID(예: 37solo6mmhh7k4v63cqdfgdg5d)를 입력합니다.

1. 파라미터로 CloudFormation 스택에 전달한 사용자 이름을 입력합니다. 기본값은 **nadia**입니다.

1. CloudFormation 스택에 파라미터로 입력한 이메일로 전송된 임시 암호를 사용합니다(예: *UserPoolUserEmail*).

1. 로그인을 선택합니다. 버튼이 **Logout nadia**로 바뀌거나 CloudFormation 스택을 생성할 때 사용자 이름(즉, *UserPoolUsername*)으로 바뀌어야 합니다.

몇 가지 *createPicture* 변경을 전송해 사진 테이블을 채워 보겠습니다. 콘솔 내에서 다음 GraphQL 쿼리를 실행합니다.

```
mutation {
  createPicture(input:{
    owner: "nadia"
    src: "nadia.jpg"
  }) {
    id
    owner
    src
  }
}
```

응답은 아래와 같아야 합니다.

```
{
  "data": {
    "createPicture": {
      "id": "c6fedbbe-57ad-4da3-860a-ffe8d039882a",
      "owner": "nadia",
      "src": "nadia.jpg"
    }
  }
}
```

사진을 몇 개 더 추가해 보겠습니다.

```
mutation {
  createPicture(input:{
    owner: "shaggy"
    src: "shaggy.jpg"
  }) {
    id
    owner
    src
  }
}
```

```
mutation {
  createPicture(input:{
    owner: "rex"
    src: "rex.jpg"
  }) {
    id
    owner
    src
  }
}
```

**nadia**를 관리자 사용자로 사용하여 사진을 3개 더 추가했습니다.

### createFriendship 변형
<a name="createfriendship-mutation"></a>

친구 관계 항목을 추가해 보겠습니다. 콘솔에서 다음 변형을 실행합니다.

참고: 관리자 사용자로 로그인한 상태여야 합니다(기본 관리자 사용자: **nadia**).

```
mutation {
  createFriendship(id: "nadia", target: "shaggy")
}
```

응답이 다음과 같아야 합니다.

```
{
  "data": {
    "createFriendship": true
  }
}
```

 **nadia** 및 **shaggy**는 친구이지만 **rex**는 그 누구와도 친구가 아닙니다.

### getPicturesByOwner 쿼리
<a name="getpicturesbyowner-query"></a>

이 단계에서는 Cognito 사용자 풀과 이 자습서 초반에 설정한 자격 증명을 사용하여 **nadia**로 로그인합니다. **nadia**로 **shaggy**가 소유하고 있는 사진을 검색합니다.

```
query {
    getPicturesByOwner(id: "shaggy") {
        id
        owner
        src
    }
}
```

**nadia**와 **shaggy**는 친구이기 때문에 이 쿼리는 해당하는 사진을 반환해야 합니다.

```
{
  "data": {
    "getPicturesByOwner": [
      {
        "id": "05a16fba-cc29-41ee-a8d5-4e791f4f1079",
        "owner": "shaggy",
        "src": "src://shaggy.jpg"
      }
    ]
  }
}
```

마찬가지로, **nadia**가 자신의 사진을 검색하려고 하는 경우에도 성공합니다. 파이프라인 해석기는 이 경우 **isFriend** GetItem 작업 실행을 피하도록 최적화되어 있습니다. 다음 쿼리를 시도해 보십시오.

```
query {
    getPicturesByOwner(id: "nadia") {
        id
        owner
        src
    }
}
```

(**Settings(설정)** 창에서) API에 대한 로깅을 활성화한 경우 디버그 수준을 **ALL**로 설정하고 동일한 쿼리를 다시 실행하면 필드 실행에 대한 로그가 반환됩니다. 로그를 보면 **isFriend** 함수가 **요청 매핑 템플릿** 단계에서 초기에 반환되었는지 여부를 확인할 수 있습니다.

```
{
  "errors": [],
  "mappingTemplateType": "Request Mapping",
  "path": "[getPicturesByOwner]",
  "resolverArn": "arn:aws:appsync:us-west-2:XXXX:apis/XXXX/types/Query/fields/getPicturesByOwner",
  "functionArn": "arn:aws:appsync:us-west-2:XXXX:apis/XXXX/functions/o2f42p2jrfdl3dw7s6xub2csdfs",
  "functionName": "isFriend",
  "earlyReturnedValue": {
    "owner": "nadia",
    "callerId": "nadia"
  },
  "context": {
    "arguments": {
      "id": "nadia"
    },
    "prev": {
      "result": {
        "owner": "nadia",
        "callerId": "nadia"
      }
    },
    "stash": {},
    "outErrors": []
  },
  "fieldInError": false
}
```

*earlyReturnedValue* 키는 *\$1return* 명령으로 반환된 데이터를 나타냅니다.

마지막으로, **rex**가 **Viewers** Cognito UserPool의 구성원이긴 하지만 **rex**는 그 누구와도 친구가 아니기 때문에 **shaggy** 또는 **nadia**가 소유한 어떤 사진에도 액세스할 수 없습니다. 콘솔에서 **rex**로 로그인해 다음 쿼리를 실행해 보십시오.

```
query {
    getPicturesByOwner(id: "nadia") {
        id
        owner
        src
    }
}
```

다음과 같은 권한 없음 오류가 발생합니다.

```
{
  "data": {
    "getPicturesByOwner": null
  },
  "errors": [
    {
      "path": [
        "getPicturesByOwner"
      ],
      "data": null,
      "errorType": "Unauthorized",
      "errorInfo": null,
      "locations": [
        {
          "line": 2,
          "column": 9,
          "sourceName": null
        }
      ],
      "message": "Not Authorized to access getPicturesByOwner on type Query"
    }
  ]
}
```

지금까지 파이프라인 해석기를 사용하여 복잡한 권한 부여를 성공적으로 구현해 보았습니다.