

# 자습서: AWS 서비스에 대한 통합의 통합 요청 및 응답 수정
<a name="set-up-data-transformations-in-api-gateway"></a>

다음 자습서에서는 콘솔과 AWS CLI를 사용하여 통합 요청 및 응답을 변환하도록 매핑 템플릿을 설정하기 위해 매핑 템플릿 변환을 사용하는 방법을 보여줍니다.

**Topics**
+ [API Gateway 콘솔을 사용하여 데이터 변환 설정](#mapping-example-console)
+ [AWS CLI를 사용하여 데이터 변환 설정](#mapping-example-cli)
+ [완성된 데이터 변환 CloudFormation 템플릿](#api-gateway-data-transformations-full-cfn-stack)

## API Gateway 콘솔을 사용하여 데이터 변환 설정
<a name="mapping-example-console"></a>

이 자습서에서는 .zip 파일([data-transformation-tutorial-console.zip](samples/data-transformation-tutorial-console.zip))을 사용하여 불완전한 API 및 DynamoDB 테이블을 생성합니다. 이 불완전한 API에는 `GET` 및 `POST` 메서드가 포함된 `/pets` 리소스가 있습니다.
+ `GET` 메서드는 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 엔드포인트에서 데이터를 가져옵니다. 출력 데이터는 [API Gateway에서 REST API의 데이터 변환 매핑](models-mappings.md)의 매핑 템플릿에 따라 변환됩니다.
+ `POST` 메서드를 사용하면 사용자가 매핑 템플릿을 사용하여 Amazon DynamoDB 테이블에 `POST` 반려동물 정보를 입력할 수 있습니다.

[CloudFormation용 앱 생성 템플릿](samples/data-transformation-tutorial-console.zip)을 다운로드하고 압축을 해제합니다. 이 템플릿을 사용하여 반려동물 정보와 불완전한 API를 게시하기 위한 DynamoDB 테이블을 생성할 것입니다. API Gateway 콘솔에서 나머지 단계를 완료하게 됩니다.

**CloudFormation 스택을 생성하려면**

1. CloudFormation 콘솔([https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/))을 엽니다.

1. **스택 생성**을 선택한 다음 **새 리소스 사용(표준)**을 선택합니다.

1. **템플릿 지정**에서 **템플릿 파일 업로드**를 선택합니다.

1. 다운로드한 템플릿을 선택합니다.

1. **다음**을 선택합니다.

1. **스택 이름**에 **data-transformation-tutorial-console**을 입력하고 **다음**을 선택합니다.

1. **스택 옵션 구성**에서 **다음**을 선택합니다.

1. **기능**의 경우 CloudFormation이 계정에 IAM 리소스를 생성할 수 있음을 확인합니다.

1. **다음**을 선택한 후 **제출**을 선택합니다.

CloudFormation은 템플릿에 지정된 리소스를 프로비저닝합니다. 리소스 프로비저닝을 완료하는 데 몇 분 정도 걸릴 수 있습니다. CloudFormation 스택 상태가 **CREATE\_COMPLETE**인 경우 다음 단계로 넘어갈 준비가 된 것입니다.

**`GET` 통합 응답을 테스트하는 방법**

1. **data-transformation-tutorial-console**의 CloudFormation 스택에 있는 **리소스** 탭에서 API의 물리적 ID를 선택합니다.

1. 기본 탐색 창에서 **리소스**를 선택하고 **GET** 메서드를 선택합니다.

1. **테스트** 탭을 선택합니다. 탭을 표시하려면 오른쪽 화살표 버튼을 선택해야 할 수도 있습니다.

   테스트 결과는 다음과 같습니다.

   ```
   [
     {
       "id": 1,
       "type": "dog",
       "price": 249.99
     },
     {
       "id": 2,
       "type": "cat",
       "price": 124.99
     },
     {
       "id": 3,
       "type": "fish",
       "price": 0.99
     }
   ]
   ```

   [API Gateway에서 REST API의 데이터 변환 매핑](models-mappings.md)의 매핑 테이블에 따라 이 출력 데이터를 변환합니다.

**`GET` 통합 응답을 변환하는 방법**

1. **통합 응답** 탭을 선택합니다.

   현재 정의된 매핑 템플릿이 없으므로 통합 응답은 변환되지 않습니다.

1. **기본값 - 응답**에서 **편집**을 선택합니다.

1. **매핑 템플릿**을 선택한 후 다음을 수행합니다.

   1. **매핑 템플릿 추가(Add mapping template)**를 선택합니다.

   1. **콘텐츠 유형**에 **application/json**을 입력합니다.

   1. **템플릿 본문**에 다음을 입력합니다.

      ```
      #set($inputRoot = $input.path('$'))
      [
      #foreach($elem in $inputRoot)
        {
          "description" : "Item $elem.id is a $elem.type.",
          "askingPrice" : $elem.price
        }#if($foreach.hasNext),#end
      
      #end
      ]
      ```

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

**`GET` 통합 응답을 테스트하는 방법**
+ **테스트** 탭을 선택한 다음 **테스트**를 선택합니다.

  테스트 출력에는 변환된 응답이 표시됩니다.

  ```
  [
    {
      "description" : "Item 1 is a dog.",
      "askingPrice" : 249.99
    },
    {
      "description" : "Item 2 is a cat.",
      "askingPrice" : 124.99
    },
    {
      "description" : "Item 3 is a fish.",
      "askingPrice" : 0.99
    }
  ]
  ```

**`POST` 메서드의 입력 데이터를 변환하는 방법**

1. **POST** 메서드를 선택합니다.

1. **통합 요청** 탭을 선택한 다음 **통합 요청 설정**에서 **편집**을 선택합니다.

   CloudFormation 템플릿에 일부 통합 요청 필드가 채워져 있습니다.
   +  통합 유형은 AWS 서비스입니다.
   +  AWS 서비스는 DynamoDB입니다.
   +  HTTP 메서드는 `POST`입니다.
   +  작업은 `PutItem`입니다.
   +  API Gateway가 DynamoDB 테이블에 항목을 넣을 수 있도록 하는 실행 역할은 `data-transformation-tutorial-console-APIGatewayRole`입니다. API Gateway가 DynamoDB와 상호 작용하는 데 필요한 최소한의 권한을 가질 수 있도록 하기 위해 CloudFormation이 생성한 역할입니다.

    DynamoDB 테이블의 이름이 지정되지 않았습니다. 다음 단계에서 이름을 지정합니다.

1. **요청 본문 패스스루**에서 **없음**을 선택합니다.

   이렇게 하면 API는 매핑 템플릿이 없는 Content-Types의 데이터를 거부합니다.

1. **매핑 템플릿**을 선택합니다.

1. **콘텐츠 유형**이 `application/json`으로 설정되어 있습니다. 이는 application/json이 아닌 콘텐츠 유형은 API에서 거부함을 의미합니다. 통합 패스스루 동작에 관한 자세한 정보는 [API Gateway의 REST API에 대한 매핑 템플릿이 없는 페이로드의 메서드 요청 동작](integration-passthrough-behaviors.md) 섹션을 참조하세요.

1. 텍스트 편집기에 다음 코드를 입력합니다.

   ```
   {
       "TableName":"data-transformation-tutorial-console-ddb",
       "Item": {
           "id": {
               "N": $input.json("$.id")
           },
           "type": {
               "S": $input.json("$.type")
           },
           "price": {
               "N": $input.json("$.price")
           }
       }
   }
   ```

    이 템플릿은 테이블을 `data-transformation-tutorial-console-ddb`로 지정하고 항목을 `id`, `type` 및 `price`로 설정합니다. 항목은 `POST` 메서드 본문에서 가져옵니다. 또한 매핑 템플릿을 만드는 데 데이터 모델을 사용할 수 있습니다. 자세한 내용은 [API Gateway의 REST API API 검증 요청](api-gateway-method-request-validation.md) 섹션을 참조하세요.

1. **저장**을 선택하여 매핑 템플릿을 저장합니다.

**메서드 및 `POST` 메서드의 통합 응답을 추가하는 방법**

CloudFormation이 빈 메서드와 통합 응답을 만들었습니다. 이 응답을 편집하여 자세한 정보를 제공할 수 있습니다. 응답을 편집하는 방법에 대한 자세한 내용은 [API Gateway의 REST API에 대한 파라미터 매핑 예제](request-response-data-mappings.md) 섹션을 참조하세요.

1. **통합 응답** 탭의 **기본값 - 응답**에서 **편집**을 선택합니다.

1. **매핑 템플릿**을 선택한 다음 **매핑 템플릿 추가**를 선택합니다.

1. **Content-type**에 **application/json**을 입력합니다.

1. 코드 편집기에서 다음 출력 매핑 템플릿을 입력하여 출력 메시지를 보냅니다.

   ```
   { "message" : "Your response was recorded at $context.requestTime" }
   ```

   컨텍스트 변수에 대한 자세한 내용은 [데이터 변환용 컨텍스트 변수](api-gateway-mapping-template-reference.md#context-variable-reference) 섹션을 참조하세요.

1. **저장**을 선택하여 매핑 템플릿을 저장합니다.

**`POST` 메서드 테스트**

**테스트** 탭을 선택합니다. 탭을 표시하려면 오른쪽 화살표 버튼을 선택해야 할 수도 있습니다.

1. 요청 본문에 다음 예를 입력합니다.

   ```
   {
             "id": "4",
             "type" : "dog",
             "price": "321"
   }
   ```

1. **테스트**를 선택합니다.

   출력에 성공 메시지가 표시되어야 합니다.

    [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)에서 DynamoDB 콘솔을 열어 예시 항목이 테이블에 있는지 확인할 수 있습니다.

**CloudFormation 스택을 삭제하려면**

1. CloudFormation 콘솔([https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/))을 엽니다.

1. CloudFormation 스택을 선택합니다.

1. **삭제**를 선택한 다음 해당 선택을 확인합니다.

## AWS CLI를 사용하여 데이터 변환 설정
<a name="mapping-example-cli"></a>

이 자습서에서는 .zip 파일([data-transformation-tutorial-cli.zip](samples/data-transformation-tutorial-cli.zip))을 사용하여 불완전한 API 및 DynamoDB 테이블을 생성합니다. 이 불완전한 API에는 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 엔드포인트와 통합된 `GET` 메서드가 포함된 `/pets` 리소스가 있습니다. DynamoDB 테이블에 연결할 `POST` 메서드를 생성하고 매핑 템플릿을 사용하여 DynamoDB 테이블에 데이터를 입력합니다.
+ [API Gateway에서 REST API의 데이터 변환 매핑](models-mappings.md)의 매핑 템플릿에 따라 출력 데이터를 변화합니다.
+ 사용자가 매핑 템플릿을 사용하여 Amazon DynamoDB 테이블에 `POST` 반려동물 정보를 입력할 수 있도록 `POST` 메서드를 생성합니다.

**CloudFormation 스택을 생성하려면**

[CloudFormation용 앱 생성 템플릿](samples/data-transformation-tutorial-cli.zip)을 다운로드하고 압축을 해제합니다.

다음 자습서를 완료하려면 [AWS Command Line Interface(AWS CLI) 버전 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)가 필요합니다.

긴 명령의 경우 이스케이프 문자(`\`)를 사용하여 명령을 여러 행으로 분할합니다.
**참고**  
Windows에서는 일반적으로 사용하는 일부 Bash CLI 명령(예: `zip`)은 운영 체제의 기본 제공 터미널에서 지원되지 않습니다. Ubuntu와 Bash의 Windows 통합 버전을 가져오려면 [Linux용 Windows Subsystem을 설치](https://learn.microsoft.com/en-us/windows/wsl/install)합니다. 이 안내서의 예제 CLI 명령은 Linux 형식을 사용합니다. Windows CLI를 사용하는 경우 인라인 JSON 문서를 포함하는 명령의 형식을 다시 지정해야 합니다.

1.  다음 명령을 사용하여 CloudFormation 스택을 생성합니다.

   ```
   aws cloudformation create-stack --stack-name data-transformation-tutorial-cli --template-body file://data-transformation-tutorial-cli.zip --capabilities CAPABILITY_NAMED_IAM 
   ```

1. CloudFormation은 템플릿에 지정된 리소스를 프로비저닝합니다. 리소스 프로비저닝을 완료하는 데 몇 분 정도 걸릴 수 있습니다. 다음 명령을 실행하여 CloudFormation 스택의 상태를 확인합니다.

   ```
   aws cloudformation describe-stacks --stack-name data-transformation-tutorial-cli
   ```

1. CloudFormation 스택의 상태가 `StackStatus: "CREATE_COMPLETE"`이면 다음 명령을 사용하여 향후 단계에 대한 관련 출력 값을 검색합니다.

   ```
    aws cloudformation describe-stacks --stack-name data-transformation-tutorial-cli --query "Stacks[*].Outputs[*].{OutputKey: OutputKey, OutputValue: OutputValue, Description: Description}"
   ```

   출력 값은 다음과 같습니다.
   + ApiRole은 API Gateway가 DynamoDB 테이블에 항목을 배치할 수 있도록 하는 역할 이름입니다. 이 자습서에서 역할 이름은 `data-transformation-tutorial-cli-APIGatewayRole-ABCDEFG`입니다.
   + DDBTableName은 DynamoDB 테이블의 이름입니다. 이 자습서에서 테이블 이름은 `data-transformation-tutorial-cli-ddb`입니다.
   + ResourceId는 `GET` 및 `POST` 메서드가 노출되는 반려동물 리소스의 ID입니다. 이 자습서에서 리소스 ID는 `efg456`입니다.
   + APIID는 API의 ID입니다. 이 자습서에서 API ID는 `abc123`입니다.

**데이터 변환 전에 `GET` 메서드를 테스트하는 방법**
+ 다음 명령을 사용하여 `GET` 메서드를 테스트합니다.

  ```
  aws apigateway test-invoke-method --rest-api-id {{abc123}} \
            --resource-id {{efg456}} \
            --http-method GET
  ```

  테스트의 출력은 다음과 같습니다.

  ```
  [
    {
      "id": 1,
      "type": "dog",
      "price": 249.99
    },
    {
      "id": 2,
      "type": "cat",
      "price": 124.99
    },
    {
      "id": 3,
      "type": "fish",
      "price": 0.99
    }
  ]
  ```

  [API Gateway에서 REST API의 데이터 변환 매핑](models-mappings.md)의 매핑 테이블에 따라 이 출력 데이터를 변환합니다.

**`GET` 통합 응답을 변환하는 방법**
+ 다음 명령을 사용하여 `GET` 메서드 통합 응답을 업데이트합니다. {{rest-api-id}}와 {{resource-id}}를 실제 값으로 바꿉니다.

  다음 명령을 사용하여 통합 응답을 생성합니다.

  ```
  aws apigateway put-integration-response --rest-api-id {{abc123}} \
    --resource-id {{efg456}} \
    --http-method GET \
    --status-code 200 \
    --selection-pattern "" \
    --response-templates '{"application/json": "#set($inputRoot = $input.path(\"$\"))\n[\n#foreach($elem in $inputRoot)\n {\n  \"description\": \"Item $elem.id is a $elem.type\",\n  \"askingPrice\": \"$elem.price\"\n }#if($foreach.hasNext),#end\n\n#end\n]"}'
  ```

**`GET` 메서드를 테스트하는 방법**
+ 다음 명령을 사용하여 `GET` 메서드를 테스트합니다.

  ```
  aws apigateway test-invoke-method --rest-api-id {{abc123}} \
    --resource-id {{efg456}} \
    --http-method GET \
  ```

  테스트 출력에는 변환된 응답이 표시됩니다.

  ```
  [
    {
      "description" : "Item 1 is a dog.",
      "askingPrice" : 249.99
    },
    {
      "description" : "Item 2 is a cat.",
      "askingPrice" : 124.99
    },
    {
      "description" : "Item 3 is a fish.",
      "askingPrice" : 0.99
    }
  ]
  ```

**`POST` 메서드를 생성하는 방법**

1. 다음 명령을 사용하여 `/pets` 리소스에 새로운 메서드를 생성합니다.

   ```
   aws apigateway put-method --rest-api-id {{abc123}} \
     --resource-id {{efg456}} \
     --http-method POST \
     --authorization-type "NONE" \
   ```

   이 방법을 사용하면 CloudFormation 스택에 생성한 DynamoDB 테이블로 반려동물 정보를 보낼 수 있습니다.

1.  다음 명령을 사용하여 `POST` 메서드에 AWS 서비스 통합을 생성합니다.

   ```
   aws apigateway put-integration --rest-api-id {{abc123}} \
     --resource-id {{efg456}} \
     --http-method POST \
     --type AWS \
     --integration-http-method POST \
     --uri "arn:aws:apigateway:{{us-east-2}}:dynamodb:action/PutItem" \
     --credentials arn:aws:iam::{{111122223333}}:role/{{data-transformation-tutorial-cli-APIGatewayRole-ABCDEFG}} \
     --request-templates '{"application/json":"{\"TableName\":\"data-transformation-tutorial-cli-ddb\",\"Item\":{\"id\":{\"N\":$input.json(\"$.id\")},\"type\":{\"S\":$input.json(\"$.type\")},\"price\":{\"N\":$input.json(\"$.price\")} }}"}'
   ```

1.  다음 명령을 사용하여 성공적인 `POST` 메서드 호출에 대한 메서드 응답을 생성합니다.

   ```
   aws apigateway put-method-response --rest-api-id {{abc123}} \
     --resource-id {{efg456}} \
     --http-method POST \
     --status-code 200
   ```

1. 다음 명령을 사용하여 성공적인 `POST` 메서드 호출에 대한 통합 응답을 생성합니다.

   ```
   aws apigateway put-integration-response --rest-api-id {{abc123}} \
     --resource-id {{efg456}} \
     --http-method POST \
     --status-code 200 \
     --selection-pattern "" \
     --response-templates '{"application/json": "{\"message\": \"Your response was recorded at $context.requestTime\"}"}'
   ```

**`POST` 메서드를 테스트하는 방법**
+ 다음 명령을 사용하여 `POST` 메서드를 테스트합니다.

  ```
  aws apigateway test-invoke-method --rest-api-id {{abc123}} \
    --resource-id {{efg456}} \
    --http-method POST \
    --body '{\"id\": \"4\", \"type\": \"dog\", \"price\": \"321\"}'
  ```

  출력에 성공 메시지가 표시됩니다.

**CloudFormation 스택을 삭제하려면**
+ 다음 명령을 사용하여 CloudFormation 리소스를 삭제합니다.

  ```
  aws cloudformation delete-stack  --stack-name data-transformation-tutorial-cli
  ```

## 완성된 데이터 변환 CloudFormation 템플릿
<a name="api-gateway-data-transformations-full-cfn-stack"></a>

다음 예시는 `GET` 및 `POST` 메서드가 있는 `/pets` 리소스가 포함된 DynamoDB 테이블과 API를 생성하는 완성된 CloudFormation 템플릿입니다.
+ `GET` 메서드는 `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP 엔드포인트에서 데이터를 가져옵니다. 출력 데이터는 [API Gateway에서 REST API의 데이터 변환 매핑](models-mappings.md)의 매핑 템플릿에 따라 변환됩니다.
+ `POST` 메서드를 사용하면 사용자가 매핑 템플릿을 사용하여 DynamoDB 테이블에 `POST` 반려동물 정보를 입력할 수 있습니다.

### 예제 CloudFormation 템플릿
<a name="mapping-template-cfn-example"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Description: A completed Amazon API Gateway REST API that uses non-proxy integration to POST to an Amazon DynamoDB table and non-proxy integration to GET transformed pets data.
Parameters:
  StageName:
    Type: String
    Default: v1
    Description: Name of API stage.
Resources:
  DynamoDBTable:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      TableName: !Sub data-transformation-tutorial-complete
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: N
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
  APIGatewayRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17		 	 	 
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
      Policies:
        - PolicyName: APIGatewayDynamoDBPolicy
          PolicyDocument:
            Version: 2012-10-17		 	 	 
            Statement:
              - Effect: Allow
                Action:
                  - 'dynamodb:PutItem'
                Resource: !GetAtt DynamoDBTable.Arn
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: data-transformation-complete-api
      ApiKeySourceType: HEADER
  PetsResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'pets'
  PetsMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: HTTP
        Credentials: !GetAtt APIGatewayRole.Arn
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
        PassthroughBehavior: WHEN_NO_TEMPLATES
        IntegrationResponses:
          - StatusCode: '200'
            ResponseTemplates:
              application/json: "#set($inputRoot = $input.path(\"$\"))\n[\n#foreach($elem in $inputRoot)\n {\n  \"description\": \"Item $elem.id is a $elem.type\",\n  \"askingPrice\": \"$elem.price\"\n }#if($foreach.hasNext),#end\n\n#end\n]"
      MethodResponses:
        - StatusCode: '200'
  PetsMethodPost:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: POST
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: AWS
        Credentials: !GetAtt APIGatewayRole.Arn
        IntegrationHttpMethod: POST
        Uri: arn:aws:apigateway:us-west-1:dynamodb:action/PutItem
        PassthroughBehavior: NEVER
        RequestTemplates: 
          application/json: "{\"TableName\":\"data-transformation-tutorial-complete\",\"Item\":{\"id\":{\"N\":$input.json(\"$.id\")},\"type\":{\"S\":$input.json(\"$.type\")},\"price\":{\"N\":$input.json(\"$.price\")} }}"
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: "{\"message\": \"Your response was recorded at $context.requestTime\"}"
      MethodResponses:
        - StatusCode: '200'

  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - PetsMethodGet
    Properties:
      RestApiId: !Ref Api
      StageName: !Sub '${StageName}'
Outputs:
  ApiId:
    Description: API ID for CLI commands
    Value: !Ref Api
  ResourceId:
    Description: /pets resource ID for CLI commands
    Value: !Ref PetsResource
  ApiRole:
    Description: Role ID to allow API Gateway to put and scan items in DynamoDB table
    Value: !Ref APIGatewayRole
  DDBTableName:
    Description: DynamoDB table name
    Value: !Ref DynamoDBTable
```