

# 자습서 \$11: 필터를 사용하여 AWS CLI로 AWS Lambda 및 Amazon DynamoDB에서 모든 이벤트 처리
<a name="Streams.Lambda.Tutorial"></a>

 

이 자습서에서는 DynamoDB 테이블의 스트림을 처리하기 위해 AWS Lambda 트리거를 생성합니다.

**Topics**
+ [1단계: 스트림을 활성화하여 DynamoDB 테이블 생성](#Streams.Lambda.Tutorial.CreateTable)
+ [2단계: Lambda 실행 역할 생성](#Streams.Lambda.Tutorial.CreateRole)
+ [3단계: Amazon SNS 주제 생성](#Streams.Lambda.Tutorial.SNSTopic)
+ [4단계: Lambda 함수 생성 및 테스트](#Streams.Lambda.Tutorial.LambdaFunction)
+ [5단계: 트리거 생성 및 테스트](#Streams.Lambda.Tutorial.CreateTrigger)

이 자습서의 시나리오는 간단한 소셜 네트워크인 Woofer입니다. Woofer 사용자는 다른 Woofer 사용자에게 전달되는 *바크*(간단한 문자 메시지)를 이용해 의사소통합니다. 다음 다이어그램은 이 애플리케이션에 대한 구성 요소 및 워크플로우를 보여줍니다.

![\[DynamoDB 테이블, 스트림 레코드, Lambda 함수 및 Amazon SNS 주제의 Woofer 애플리케이션 워크플로입니다.\]](http://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/images/StreamsAndTriggers.png)


1. 사용자는 DynamoDB 테이블(`BarkTable`)에 항목을 씁니다. 테이블에서 각 항목은 바크를 나타냅니다.

1. 작성된 새 스트림 레코드는 새 항목이 `BarkTable`에 추가되었다는 것을 반영합니다.

1. 새 스트림 레코드에서 AWS Lambda 함수(`publishNewBark`)를 트리거합니다.

1. 스트림 레코드가 새 항목이 `BarkTable`에 추가되었음을 나타내는 경우 Lambda 함수는 스트림 레코드에서 데이터를 읽고 Amazon Simple Notification Service(Amazon SNS)의 주제에 메시지를 게시합니다.

1. Amazon SNS 주제의 구독자는 메시지를 수신합니다. (본 자습서에서 이메일 주소는 구독자에 해당됩니다.)

**시작하기 전**  
이 자습서에서는 AWS Command Line Interface AWS CLI을 사용합니다. 아직 완료하지 않았다면 [AWS Command Line Interface 사용 설명서](https://docs.aws.amazon.com/cli/latest/userguide/)의 지침에 따라 AWS CLI를 설치 및 구성하세요.

## 1단계: 스트림을 활성화하여 DynamoDB 테이블 생성
<a name="Streams.Lambda.Tutorial.CreateTable"></a>

이 단계에서는 Woofer 사용자의 모든 바크를 저장할 DynamoDB 테이블(`BarkTable`)을 생성합니다. 기본 키는 `Username`(파티션 키)와 `Timestamp`(정렬 키)로 구성됩니다. 이 두 가지 속성 모두 문자열 유형입니다.

`BarkTable`에서는 스트림이 활성화되어 있습니다. 이 자습서에서 나중에 AWS Lambda 함수를 스트림에 연결하여 트리거를 생성할 수 있습니다.

1. 테이블을 생성하려면 다음 명령을 입력합니다.

   ```
   aws dynamodb create-table \
       --table-name BarkTable \
       --attribute-definitions AttributeName=Username,AttributeType=S AttributeName=Timestamp,AttributeType=S \
       --key-schema AttributeName=Username,KeyType=HASH  AttributeName=Timestamp,KeyType=RANGE \
       --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
       --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
   ```

1. 출력에서 `LatestStreamArn`를 찾습니다.

   ```
   ...
   "LatestStreamArn": "arn:aws:dynamodb:region:accountID:table/BarkTable/stream/timestamp
   ...
   ```

   `region` 및 `accountID`를 기록해 둡니다. 이 두 항목은 자습서의 다른 단계에서 필요합니다.

## 2단계: Lambda 실행 역할 생성
<a name="Streams.Lambda.Tutorial.CreateRole"></a>

이 단계에서는 AWS Identity and Access Management(IAM) 역할(`WooferLambdaRole`\$1을 만들어 권한을 할당합니다. 이 역할은 [4단계: Lambda 함수 생성 및 테스트](#Streams.Lambda.Tutorial.LambdaFunction)에서 만드는 Lambda 함수에서 사용합니다.

또한 해당 역할에 대한 정책도 생성합니다. 이 정책에는 Lambda 함수에서 런타임에 필요로 하는 모든 권한이 포함되어 있습니다.

1. 다음 콘텐츠를 가진 `trust-relationship.json`이라는 파일을 생성합니다:

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

****  

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

------

1. 다음 명령을 입력하여 `WooferLambdaRole`을 생성합니다.

   ```
   aws iam create-role --role-name WooferLambdaRole \
       --path "/service-role/" \
       --assume-role-policy-document file://trust-relationship.json
   ```

1. 다음 콘텐츠를 가진 `role-policy.json`이라는 파일을 생성합니다: (`region` 및 `accountID`를 AWS 리전 및 계정 ID로 바꿉니다.)

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

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "logs:CreateLogGroup",
                   "logs:CreateLogStream",
                   "logs:PutLogEvents"
               ],
               "Resource": "arn:aws:logs:us-east-1:111122223333:*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "dynamodb:DescribeStream",
                   "dynamodb:GetRecords",
                   "dynamodb:GetShardIterator",
                   "dynamodb:ListStreams"
               ],
               "Resource": "arn:aws:dynamodb:us-east-1:111122223333:table/BarkTable/stream/*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "sns:Publish"
               ],
               "Resource": [
                   "*"
               ]
           }
       ]
   }
   ```

------

   정책은 `WooferLambdaRole`이 다음을 수행할 수 있도록 해주는 네 가지 문을 가지고 있습니다.
   + Lambda 함수 실행(`publishNewBark`). 이 자습서에서는 나중에 함수를 생성합니다.
   + Amazon CloudWatch Logs 액세스. Lambda 함수는 런타임에 CloudWatch Logs에 진단을 씁니다.
   + `BarkTable`에 대한 DynamoDB 스트림에서 데이터 읽기
   + Amazon SNS에 메시지 게시

1. 다음 명령을 입력하여 정책을 `WooferLambdaRole`에 연결합니다.

   ```
   aws iam put-role-policy --role-name WooferLambdaRole \
       --policy-name WooferLambdaRolePolicy \
       --policy-document file://role-policy.json
   ```

## 3단계: Amazon SNS 주제 생성
<a name="Streams.Lambda.Tutorial.SNSTopic"></a>

이 단계에서는 Amazon SNS 주제(`wooferTopic`)를 생성하고 해당 주제에 대한 이메일 주소를 구독합니다. Lambda 함수에서는 이 주제를 사용하여 Woofer 사용자의 새 바크를 게시합니다.

1. 다음 명령을 입력하여 새 Amazon SNS 주제를 생성합니다.

   ```
   aws sns create-topic --name wooferTopic
   ```

1. 다음 명령을 입력해 `wooferTopic`에 대한 이메일 주소를 구독합니다. (`region` 및 `accountID`를 AWS 리전 및 계정 ID로 바꾸고, `example@example.com`을 유효한 이메일 주소로 바꿉니다.)

   ```
   aws sns subscribe \
       --topic-arn arn:aws:sns:region:accountID:wooferTopic \
       --protocol email \
       --notification-endpoint example@example.com
   ```

1. Amazon SNS에서 사용자 이메일 주소로 확인 메시지를 보냅니다. 구독 프로세스를 완료하는 메시지와 연결된 **구독 확인** 링크를 클릭합니다.

## 4단계: Lambda 함수 생성 및 테스트
<a name="Streams.Lambda.Tutorial.LambdaFunction"></a>

이 단계에서는 AWS Lambda 함수(`publishNewBark`)를 만들어 `BarkTable`에서 스트림 레코드를 처리합니다.

`publishNewBark` 함수는 `BarkTable`의 새 항목에 해당하는 스트림 이벤트만을 처리합니다. 함수는 해당 이벤트에서 데이터를 읽은 다음 Amazon SNS를 호출하여 게시합니다.

1. 다음 콘텐츠를 가진 `publishNewBark.js`이라는 파일을 생성합니다: `region` 및 `accountID`를 AWS 리전 및 계정 ID로 바꿉니다.

   ```
   'use strict';
   var AWS = require("aws-sdk");
   var sns = new AWS.SNS();
   
   exports.handler = (event, context, callback) => {
   
       event.Records.forEach((record) => {
           console.log('Stream record: ', JSON.stringify(record, null, 2));
   
           if (record.eventName == 'INSERT') {
               var who = JSON.stringify(record.dynamodb.NewImage.Username.S);
               var when = JSON.stringify(record.dynamodb.NewImage.Timestamp.S);
               var what = JSON.stringify(record.dynamodb.NewImage.Message.S);
               var params = {
                   Subject: 'A new bark from ' + who,
                   Message: 'Woofer user ' + who + ' barked the following at ' + when + ':\n\n ' + what,
                   TopicArn: 'arn:aws:sns:region:accountID:wooferTopic'
               };
               sns.publish(params, function(err, data) {
                   if (err) {
                       console.error("Unable to send message. Error JSON:", JSON.stringify(err, null, 2));
                   } else {
                       console.log("Results from sending message: ", JSON.stringify(data, null, 2));
                   }
               });
           }
       });
       callback(null, `Successfully processed ${event.Records.length} records.`);
   };
   ```

1. `publishNewBark.js`가 포함된 zip 파일을 만듭니다. zip 명령줄 유틸리티를 사용하는 경우 다음과 같은 명령을 입력하여 이를 수행할 수 있습니다.

   ```
   zip publishNewBark.zip publishNewBark.js
   ```

1. Lambda 함수를 만들 때 [2단계: Lambda 실행 역할 생성](#Streams.Lambda.Tutorial.CreateRole)에서 생성한 `WooferLambdaRole`의 Amazon 리소스 이름(ARN)을 지정합니다. 이 ARN을 가져오려면 다음 명령을 입력합니다.

   ```
   aws iam get-role --role-name WooferLambdaRole
   ```

   출력에서 `WooferLambdaRole`의 ARN을 찾습니다.

   ```
   ...
   "Arn": "arn:aws:iam::region:role/service-role/WooferLambdaRole"
   ...
   ```

   Lambda 함수를 생성하려면 다음 명령을 입력합니다. *roleARN*를 `WooferLambdaRole`의 ARN으로 바꿉니다.

   ```
   aws lambda create-function \
       --region region \
       --function-name publishNewBark \
       --zip-file fileb://publishNewBark.zip \
       --role roleARN \
       --handler publishNewBark.handler \
       --timeout 5 \
       --runtime nodejs16.x
   ```

1. 이제, `publishNewBark`을 테스트하여 제대로 작동하는지 확인합니다. 이렇게 하려면 DynamoDB Streams의 실제 레코드와 유사한 내용을 입력합니다.

   다음 콘텐츠를 가진 `payload.json`이라는 파일을 생성합니다: `region` 및 `accountID`를 AWS 리전 및 계정 ID로 바꿉니다.

   ```
   {
       "Records": [
           {
               "eventID": "7de3041dd709b024af6f29e4fa13d34c",
               "eventName": "INSERT",
               "eventVersion": "1.1",
               "eventSource": "aws:dynamodb",
               "awsRegion": "region",
               "dynamodb": {
                   "ApproximateCreationDateTime": 1479499740,
                   "Keys": {
                       "Timestamp": {
                           "S": "2016-11-18:12:09:36"
                       },
                       "Username": {
                           "S": "John Doe"
                       }
                   },
                   "NewImage": {
                       "Timestamp": {
                           "S": "2016-11-18:12:09:36"
                       },
                       "Message": {
                           "S": "This is a bark from the Woofer social network"
                       },
                       "Username": {
                           "S": "John Doe"
                       }
                   },
                   "SequenceNumber": "13021600000000001596893679",
                   "SizeBytes": 112,
                   "StreamViewType": "NEW_IMAGE"
               },
               "eventSourceARN": "arn:aws:dynamodb:region:account ID:table/BarkTable/stream/2016-11-16T20:42:48.104"
           }
       ]
   }
   ```

   `publishNewBark` 함수를 테스트하려면 다음 명령을 입력합니다.

   ```
   aws lambda invoke --function-name publishNewBark --payload file://payload.json --cli-binary-format raw-in-base64-out output.txt
   ```

   테스트가 성공적이면 다음 출력이 생성됩니다.

   ```
   {
       "StatusCode": 200,
       "ExecutedVersion": "$LATEST"
   }
   ```

   또한 `output.txt` 파일에는 다음 텍스트가 포함됩니다.

   ```
   "Successfully processed 1 records."
   ```

   몇 분 안에 새 이메일 메시지가 전송됩니다.
**참고**  
AWS Lambda는 진단 정보를 Amazon CloudWatch Logs에 씁니다. Lambda 함수에서 오류가 발생하면 문제 해결을 위해 이 진단 정보를 사용할 수 있습니다.  
[https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)에서 CloudWatch 콘솔을 엽니다.
탐색 창에서 **로그**를 선택합니다.
다음과 같은 로그 그룹을 선택합니다.`/aws/lambda/publishNewBark`
최신 로그 스트림을 선택하여 함수의 출력(오류 사항 포함)을 봅니다.

## 5단계: 트리거 생성 및 테스트
<a name="Streams.Lambda.Tutorial.CreateTrigger"></a>

[4단계: Lambda 함수 생성 및 테스트](#Streams.Lambda.Tutorial.LambdaFunction)에서 Lambda 함수를 테스트하여 제대로 실행되는지 확인합니다. 이 단계에서는 Lambda 함수(`publishNewBark`)를 이벤트 소스(`BarkTable` 스트림)과 연결하여 *트리거*를 생성합니다.

1. 트리거를 생성할 때 `BarkTable` 스트림의 ARN을 지정해야 합니다. 이 ARN을 가져오려면 다음 명령을 입력합니다.

   ```
   aws dynamodb describe-table --table-name BarkTable
   ```

   출력에서 `LatestStreamArn`를 찾습니다.

   ```
   ...
    "LatestStreamArn": "arn:aws:dynamodb:region:accountID:table/BarkTable/stream/timestamp
   ...
   ```

1. 다음 명령을 입력하여 트리거를 생성합니다. `streamARN`를 실제 스트림 ARN으로 바꿉니다.

   ```
   aws lambda create-event-source-mapping \
       --region region \
       --function-name publishNewBark \
       --event-source streamARN  \
       --batch-size 1 \
       --starting-position TRIM_HORIZON
   ```

1. 트리거를 테스트합니다. 다음 명령을 입력하여 `BarkTable`에 항목을 추가합니다.

   ```
   aws dynamodb put-item \
       --table-name BarkTable \
       --item Username={S="Jane Doe"},Timestamp={S="2016-11-18:14:32:17"},Message={S="Testing...1...2...3"}
   ```

   몇 분 이내에 새 이메일 메시지를 수신합니다.

1. DynamoDB 콘솔을 열어서 `BarkTable`에 몇 개 항목을 추가합니다. `Username` 및 `Timestamp`에 대한 속성값을 지정해야 합니다. (필수 사항은 아니지만 `Message`에 대한 값을 지정할 수도 있습니다.) 추가한 `BarkTable`의 각 항목에 대해 새 이메일 메시지를 수신하게 됩니다.

   Lambda 함수는 `BarkTable`에 추가된 새 항목만을 처리합니다. 테이블에 업데이트되거나 삭제한 항목에 대해 이 함수는 별도의 작업을 하지 않습니다.

**참고**  
AWS Lambda는 진단 정보를 Amazon CloudWatch Logs에 씁니다. Lambda 함수에서 오류가 발생하면 문제 해결을 위해 이 진단 정보를 사용할 수 있습니다.  
[https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)에서 CloudWatch 콘솔을 엽니다.
탐색 창에서 **로그**를 선택합니다.
다음과 같은 로그 그룹을 선택합니다.`/aws/lambda/publishNewBark`
최신 로그 스트림을 선택하여 함수의 출력(오류 사항 포함)을 봅니다.