

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

# 자습서: CodeDeploy 및 AWS 서버리스 애플리케이션 모델을 사용하여 업데이트된 Lambda 함수 배포
<a name="tutorial-lambda-sam"></a>

AWS SAM은 서버리스 애플리케이션을 빌드하기 위한 오픈 소스 프레임워크입니다. AWS SAM 템플릿의 YAML 구문을 CloudFormation 구문으로 변환하고 확장하여 Lambda 함수와 같은 서버리스 애플리케이션을 빌드합니다. 자세한 내용은 [AWS Serverless Application Model이란 무엇입니까?](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html)를 참조하세요.

 이 자습서에서는 AWS SAM을 사용하여 다음을 수행하는 솔루션을 생성합니다.
+  Lambda 함수를 생성합니다.
+  CodeDeploy 애플리케이션 및 배포 그룹을 생성합니다.
+  CodeDeploy 수명 주기 후크 중에 배포 확인 테스트를 실행하는 Lambda 함수 두 개를 생성합니다.
+  언제 Lambda 함수가 업데이트되는지를 감지합니다. Lambda 함수를 업데이트하면 Lambda 함수의 원래 버전에서 업데이트된 버전으로 프로덕션 트래픽을 증분식으로 이동하는 CodeDeploy를 통해 배포가 트리거됩니다.

**참고**  
이 튜토리얼에서는 결과적으로 AWS 계정에 요금이 부과될 수 있는 리소스를 생성해야 합니다. 여기에는 CodeDeploy, Amazon CloudWatch 및에 대해 발생할 수 있는 요금이 포함됩니다 AWS Lambda. 자세한 내용은 [CodeDeploy 요금](https://aws.amazon.com/codedeploy/pricing/), [Amazon CloudWatch 요금](https://aws.amazon.com/cloudwatch/pricing/) 및 [AWS Lambda 요금](https://aws.amazon.com/lambda/pricing/)을 참조하세요.

**Topics**
+ [사전 조건](tutorial-lambda-sam-prereqs.md)
+ [1단계: 인프라 설정](tutorial-lambda-sam-setup-infrastructure.md)
+ [2단계: Lambda 함수 업데이트](tutorial-lambda-sam-update-function.md)
+ [3단계: 업데이트된 Lambda 함수 배포](tutorial-lambda-sam-deploy-update.md)
+ [4단계: 배포 결과 보기](tutorial-lambda-sam-deploy-view-results.md)
+ [5단계: 정리](tutorial-lambda-clean-up.md)

# 사전 조건
<a name="tutorial-lambda-sam-prereqs"></a>

이 자습서를 완료하려면 먼저 다음을 수행해야 합니다.
+  [CodeDeploy 시작하기](getting-started-codedeploy.md)의 단계를 수행하세요.
+  AWS Serverless Application Model CLI를 설치합니다. 자세한 내용은 [AWS SAM CLI 설치를 참조하세요](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html).
+  S3 버킷을 생성합니다. AWS SAM은 [AWS SAM 템플릿](https://docs.aws.amazon.com/en_us/codedeploy/latest/userguide/tutorial-lambda-sam-template.html)에서 참조되는 아티팩트를이 버킷에 업로드합니다.

# 1단계: 인프라 설정
<a name="tutorial-lambda-sam-setup-infrastructure"></a>

 이 주제에서는를 AWS SAM 사용하여 AWS SAM 템플릿 및 Lambda 함수에 대한 파일을 생성하는 방법을 보여줍니다. 그런 다음 및 `deploy` 명령을 사용하여 AWS SAM `package` 인프라에서 구성 요소를 생성합니다. 인프라가 준비되면 CodeDeploy 애플리케이션 및 배포 그룹, 업데이트하고 배포할 Lambda 함수, Lambda 함수를 배포할 때 실행되는 확인 테스트가 포함된 Lambda 함수 두 개를 갖추게 됩니다. 완료되면 CloudFormation 를 사용하여 Lambda 콘솔 또는에서 구성 요소를 보고 Lambda 함수를 테스트 AWS CLI 할 수 있습니다.

**Topics**
+ [파일 생성](tutorial-lambda-create-files.md)
+ [AWS SAM 애플리케이션 패키징](tutorial-lambda-sam-package.md)
+ [AWS SAM 애플리케이션 배포](tutorial-lambda-sam-deploy.md)
+ [(선택 사항) 인프라 검사 및 테스트](tutorial-lambda-sam-confirm-components.md)

# 파일 생성
<a name="tutorial-lambda-create-files"></a>

 인프라를 생성하려면 다음 파일을 생성해야 합니다.
+ `template.yml`
+ `myDateTimeFunction.js`
+ `beforeAllowTraffic.js`
+ `afterAllowTraffic.js`

**Topics**
+ [AWS SAM 템플릿 생성](tutorial-lambda-sam-template.md)
+ [Lambda 함수에 대한 파일 생성](tutorial-lambda-sam-create-lambda-function.md)
+ [BeforeAllowTraffic Lambda 함수에 대한 파일 생성](tutorial-lambda-sam-create-lambda-before-traffic.md)
+ [AfterAllowTraffic Lambda 함수에 대한 파일 생성](tutorial-lambda-sam-create-lambda-after-traffic.md)

# AWS SAM 템플릿 생성
<a name="tutorial-lambda-sam-template"></a>

인프라의 구성 요소를 지정하는 AWS SAM 템플릿 파일을 생성합니다.

**AWS SAM 템플릿을 생성하려면**

1.  `SAM-Tutorial`이라는 디렉터리를 생성합니다.

1.  `SAM-Tutorial` 디렉터리에서 `template.yml`이라는 파일을 생성합니다.

1.  다음 YAML 코드를 `template.yml`에 복사합니다. 이 파일은 AWS SAM 템플릿입니다.

   ```
   AWSTemplateFormatVersion : '2010-09-09'
   Transform: AWS::Serverless-2016-10-31
   Description: A sample SAM template for deploying Lambda functions.
   
   Resources:
   # Details about the myDateTimeFunction Lambda function
     myDateTimeFunction:
       Type: AWS::Serverless::Function
       Properties:
         Handler: myDateTimeFunction.handler
         Runtime: nodejs18.x
   # Instructs your myDateTimeFunction is published to an alias named "live".      
         AutoPublishAlias: live
   # Grants this function permission to call lambda:InvokeFunction
         Policies:
           - Version: "2012-10-17"		 	 	 
             Statement: 
             - Effect: "Allow"
               Action: 
                 - "lambda:InvokeFunction"
               Resource: '*'
         DeploymentPreference:
   # Specifies the deployment configuration      
             Type: Linear10PercentEvery1Minute
   # Specifies Lambda functions for deployment lifecycle hooks
             Hooks:
               PreTraffic: !Ref beforeAllowTraffic
               PostTraffic: !Ref afterAllowTraffic
               
   # Specifies the BeforeAllowTraffic lifecycle hook Lambda function
     beforeAllowTraffic:
       Type: AWS::Serverless::Function
       Properties:
         Handler: beforeAllowTraffic.handler
         Policies:
           - Version: "2012-10-17"		 	 	 
   # Grants this function permission to call codedeploy:PutLifecycleEventHookExecutionStatus        
             Statement: 
             - Effect: "Allow"
               Action: 
                 - "codedeploy:PutLifecycleEventHookExecutionStatus"
               Resource:
                 !Sub 'arn:aws:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:${ServerlessDeploymentApplication}/*'
           - Version: "2012-10-17"		 	 	 
   # Grants this function permission to call lambda:InvokeFunction        
             Statement: 
             - Effect: "Allow"
               Action: 
                 - "lambda:InvokeFunction"
               Resource: !Ref myDateTimeFunction.Version
         Runtime: nodejs18.x
   # Specifies the name of the Lambda hook function      
         FunctionName: 'CodeDeployHook_beforeAllowTraffic'
         DeploymentPreference:
           Enabled: false
         Timeout: 5
         Environment:
           Variables:
             NewVersion: !Ref myDateTimeFunction.Version
             
   # Specifies the AfterAllowTraffic lifecycle hook Lambda function
     afterAllowTraffic:
       Type: AWS::Serverless::Function
       Properties:
         Handler: afterAllowTraffic.handler
         Policies:
           - Version: "2012-10-17"		 	 	 
             Statement: 
   # Grants this function permission to call codedeploy:PutLifecycleEventHookExecutionStatus         
             - Effect: "Allow"
               Action: 
                 - "codedeploy:PutLifecycleEventHookExecutionStatus"
               Resource:
                 !Sub 'arn:aws:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:${ServerlessDeploymentApplication}/*'
           - Version: "2012-10-17"		 	 	 
             Statement: 
   # Grants this function permission to call lambda:InvokeFunction          
             - Effect: "Allow"
               Action: 
                 - "lambda:InvokeFunction"
               Resource: !Ref myDateTimeFunction.Version
         Runtime: nodejs18.x
   # Specifies the name of the Lambda hook function      
         FunctionName: 'CodeDeployHook_afterAllowTraffic'
         DeploymentPreference:
           Enabled: false
         Timeout: 5
         Environment:
           Variables:
             NewVersion: !Ref myDateTimeFunction.Version
   ```

이 템플릿은 다음을 지정합니다. 자세한 내용은 [AWS SAM 템플릿 개념](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-basics.html)을 참조하세요.

**Lambda 함수 `myDateTimeFunction`**  
 이 Lambda 함수가 게시되면 템플릿의 `AutoPublishAlias`줄은 이 함수를 `live` (이)라는 별칭에 연결합니다. 이 자습서의 뒷부분에서이 함수를 업데이트 AWS CodeDeploy 하면 프로덕션 트래픽을 원래 버전에서 업데이트된 버전으로 점진적으로 이동하는 배포가 트리거됩니다.

**두 개의 Lambda 배포 확인 함수**  
 다음 Lambda 함수는 CodeDeploy 수명 주기 후크 중에 실행됩니다. 이 함수에는 업데이트된 `myDateTimeFunction`의 배포를 확인하는 코드가 포함되어 있습니다. 확인 테스트의 결과는 `PutLifecycleEventHookExecutionStatus` API 메서드를 사용하여 CodeDeploy에 전달됩니다. 확인 테스트가 실패하면 배포가 실패하고 롤백됩니다.  
+  `CodeDeployHook_beforeAllowTraffic`은 `BeforeAllowTraffic` 후크 중에 실행됩니다.
+  `CodeDeployHook_afterAllowTraffic`은 `AfterAllowTraffic` 후크 중에 실행됩니다.
두 함수의 이름은 모두 `CodeDeployHook_`로 시작합니다. `CodeDeployRoleForLambda` 역할은 이름이 이 접두사로 시작하는 Lambda 함수의 Lambda `invoke` 메서드에 대한 호출만 허용합니다. 자세한 내용은 [AWS Lambda 배포를 위한 AppSpec 'hooks' 섹션](reference-appspec-file-structure-hooks.md#appspec-hooks-lambda)와(과) *CodeDeploy API 참조*의 [PutLifecycleEventHookExecutionStatus](https://docs.aws.amazon.com/codedeploy/latest/APIReference/API_PutLifecycleEventHookExecutionStatus.html)를 참조하세요.

**업데이트된 Lambda 함수의 자동 감지**  
 `AutoPublishAlias` 기간은 `myDateTimeFunction` 함수가 언제 변경되는지를 감지한 다음 `live` 별칭을 사용하여 함수를 배포합니다.

**배포 구성**  
 배포 구성에 따라 CodeDeploy 애플리케이션이 Lambda 함수의 원래 버전에서 새 버전으로 트래픽을 이동하는 속도가 결정됩니다. 이 템플릿은 미리 정의된 배포 구성인 `Linear10PercentEvery1Minute`를 지정합니다.  
 AWS SAM 템플릿에서는 사용자 지정 배포 구성을 지정할 수 없습니다. 자세한 내용은 [CodeDeploy에서 배포 구성 만들기](deployment-configurations-create.md) 단원을 참조하십시오.

**배포 수명 주기 후크 함수**  
 `Hooks` 섹션은 수명 주기 이벤트 후크 중에 실행할 함수를 지정합니다. `PreTraffic`은 `BeforeAllowTraffic` 후크 중에 실행되는 함수를 지정합니다. `PostTraffic`는 `AfterAllowTraffic` 후크 중에 실행되는 함수를 지정합니다.

**또 다른 Lambda 함수를 호출할 Lambda의 권한**  
 지정된 `lambda:InvokeFunction` 권한은 AWS SAM 애플리케이션에서 사용하는 역할에 Lambda 함수를 호출할 수 있는 권한을 부여합니다. 이 권한은 확인 테스트 중에 `CodeDeployHook_beforeAllowTraffic` 및 `CodeDeployHook_afterAllowTraffic` 함수가 배포된 Lambda 함수를 호출할 때 필요합니다.

# Lambda 함수에 대한 파일 생성
<a name="tutorial-lambda-sam-create-lambda-function"></a>

이 튜토리얼에서 나중에 업데이트하고 배포하는 함수에 대한 파일을 생성합니다.

**참고**  
 Lambda 함수는 AWS Lambda에서 지원되는 모든 런타임을 사용할 수 있습니다. 자세한 내용은 [AWS Lambda 런타임](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html)을 참조하세요.

**Lambda 함수를 만들려면**

1.  텍스트 파일을 생성하고 `SAM-Tutorial` 디렉터리에 `myDateTimeFunction.js`로 저장합니다.

1.  다음 Node.js 코드를 `myDateTimeFunction.js`에 복사합니다.

   

   ```
   'use strict';
       
       exports.handler = function(event, context, callback) {
       
         if (event.body) {
           event = JSON.parse(event.body);
         }
       
         var sc; // Status code
         var result = ""; // Response payload
       
         switch(event.option) {
           case "date": 
             switch(event.period) {
               case "yesterday":
                 result = setDateResult("yesterday");
                 sc = 200;
                 break;
               case "today":
                 result = setDateResult();
                 sc = 200;
                 break;
               case "tomorrow":
                 result = setDateResult("tomorrow");
                 sc = 200;
                 break;
               default:
                 result = {
                   "error": "Must specify 'yesterday', 'today', or 'tomorrow'."
                 };
                 sc = 400;
                 break;
             }
             break;
             
       /*      Later in this tutorial, you update this function by uncommenting 
               this section. The framework created by AWS SAM detects the update 
               and triggers a deployment by CodeDeploy. The deployment shifts 
               production traffic to the updated version of this function.
               
               case "time":
               var d = new Date();
               var h = d.getHours();
               var mi = d.getMinutes();
               var s = d.getSeconds();
       
               result = {
                 "hour": h,
                 "minute": mi,
                 "second": s
               };
               sc = 200;
               break;
       */
             default:
               result = {
                 "error": "Must specify 'date' or 'time'."
               };
               sc = 400;
             break;
         }
       
         const response = {
           statusCode: sc,
           headers: { "Content-type": "application/json" },
           body: JSON.stringify( result )
         };
       
         callback(null, response);
       
         function setDateResult(option) {
       
           var d = new Date(); // Today
           var mo; // Month
           var da; // Day
           var y; // Year
       
           switch(option) {
             case "yesterday":
               d.setDate(d.getDate() - 1);
               break;
             case "tomorrow":
               d.setDate(d.getDate() + 1);
             default:
              break;
           }
       
           mo = d.getMonth() + 1; // Months are zero offset (0-11)
           da = d.getDate();
           y = d.getFullYear();
       
           result = {
             "month": mo,
             "day": da,
             "year": y
           };
       
           return result;
         }
       };
   ```

Lambda 함수는 어제, 오늘 또는 내일의 일, 월 및 연도를 반환합니다. 이 튜토리얼의 뒷부분에서, 지정하는 일 또는 시간(예: 일, 월, 년 또는 현재 시간, 분, 초)에 대한 정보를 반환하도록 함수를 업데이트하는 코드의 주석 처리를 해제합니다. 에서 생성한 프레임워크는 업데이트된 버전의 함수를 AWS SAM 감지하고 배포합니다.

**참고**  
 이 Lambda 함수는 AWS Cloud9 자습서에서도 사용됩니다.는 클라우드 기반 통합 개발 환경 AWS Cloud9 입니다. 에서이 함수를 생성, 실행, 업데이트 및 디버깅하는 방법에 대한 자세한 내용은 자습서를 AWS Cloud9참조하세요. [AWS LambdaAWS Cloud9](https://docs.aws.amazon.com/cloud9/latest/user-guide/tutorial-lambda.html) 

# BeforeAllowTraffic Lambda 함수에 대한 파일 생성
<a name="tutorial-lambda-sam-create-lambda-before-traffic"></a>

`beforeAllowTraffic` 후크 Lambda 함수에 대한 파일을 생성합니다.

1.  텍스트 파일을 생성하고 `SAM-Tutorial` 디렉터리에 `beforeAllowTraffic.js`로 저장합니다.

1.  다음 Node.js 코드를 `beforeAllowTraffic.js`에 복사합니다. 이 함수는 배포의 `BeforeAllowTraffic` 후크 중에 실행됩니다.

   ```
   'use strict';
       
       const AWS = require('aws-sdk'); 
       const codedeploy = new AWS.CodeDeploy({apiVersion: '2014-10-06'});
       var lambda = new AWS.Lambda();
       
       exports.handler = (event, context, callback) => {
       
       	console.log("Entering PreTraffic Hook!");
       	
       	// Read the DeploymentId and LifecycleEventHookExecutionId from the event payload
         var deploymentId = event.DeploymentId;
       	var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;
       
       	var functionToTest = process.env.NewVersion;
       	console.log("BeforeAllowTraffic hook tests started");
       	console.log("Testing new function version: " + functionToTest);
       
       	// Create parameters to pass to the updated Lambda function that
       	// include the newly added "time" option. If the function did not
       	// update, then the "time" option is invalid and function returns
       	// a statusCode of 400 indicating it failed.
       	var lambdaParams = {
       		FunctionName: functionToTest,    
       		Payload: "{\"option\": \"time\"}", 
       		InvocationType: "RequestResponse"
       	};
       
       	var lambdaResult = "Failed";
       	// Invoke the updated Lambda function.
       	lambda.invoke(lambdaParams, function(err, data) {
       		if (err){	// an error occurred
       			console.log(err, err.stack);
       			lambdaResult = "Failed";
       		}
       		else{	// successful response
       			var result = JSON.parse(data.Payload);
       			console.log("Result: " +  JSON.stringify(result));
             console.log("statusCode: " + result.statusCode);
             
             // Check if the status code returned by the updated
             // function is 400. If it is, then it failed. If 
             // is not, then it succeeded.
       			if (result.statusCode != "400"){
               console.log("Validation succeeded");
       				lambdaResult = "Succeeded";
             }
             else {
               console.log("Validation failed");
             }
       
       			// Complete the PreTraffic Hook by sending CodeDeploy the validation status
       			var params = {
       				deploymentId: deploymentId,
       				lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
       				status: lambdaResult // status can be 'Succeeded' or 'Failed'
       			};
       			
       			// Pass CodeDeploy the prepared validation test results.
       			codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) {
       				if (err) {
       					// Validation failed.
       					console.log("CodeDeploy Status update failed");
       					console.log(err, err.stack);
       					callback("CodeDeploy Status update failed");
       				} else {
       					// Validation succeeded.
       					console.log("CodeDeploy status updated successfully");
       					callback(null, "CodeDeploy status updated successfully");
       				}
       			});
       		}  
       	});
       }
   ```

# AfterAllowTraffic Lambda 함수에 대한 파일 생성
<a name="tutorial-lambda-sam-create-lambda-after-traffic"></a>

`afterAllowTraffic` 후크 Lambda 함수에 대한 파일을 생성합니다.

1.  텍스트 파일을 생성하고 `SAM-Tutorial` 디렉터리에 `afterAllowTraffic.js`로 저장합니다.

1.  다음 Node.js 코드를 `afterAllowTraffic.js`에 복사합니다. 이 함수는 배포의 `AfterAllowTraffic` 후크 중에 실행됩니다.

   ```
   'use strict';
       
       const AWS = require('aws-sdk');
       const codedeploy = new AWS.CodeDeploy({apiVersion: '2014-10-06'});
       var lambda = new AWS.Lambda();
       
       exports.handler = (event, context, callback) => {
       
       	console.log("Entering PostTraffic Hook!");
       	
       	// Read the DeploymentId and LifecycleEventHookExecutionId from the event payload
         var deploymentId = event.DeploymentId;
       	var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;
       
       	var functionToTest = process.env.NewVersion;
       	console.log("AfterAllowTraffic hook tests started");
       	console.log("Testing new function version: " + functionToTest);
       
       	// Create parameters to pass to the updated Lambda function that
       	// include the original "date" parameter. If the function did not 
       	// update as expected, then the "date" option might be invalid. If 
       	// the parameter is invalid, the function returns
       	// a statusCode of 400 indicating it failed.
       	var lambdaParams = {
       		FunctionName: functionToTest,    
       		Payload: "{\"option\": \"date\", \"period\": \"today\"}", 
       		InvocationType: "RequestResponse"
       	};
       
       	var lambdaResult = "Failed";
       	// Invoke the updated Lambda function.
       	lambda.invoke(lambdaParams, function(err, data) {
       		if (err){	// an error occurred
       			console.log(err, err.stack);
       			lambdaResult = "Failed";
       		}
       		else{	// successful response
       			var result = JSON.parse(data.Payload);
       			console.log("Result: " +  JSON.stringify(result));
             console.log("statusCode: " + result.statusCode);
             
             // Check if the status code returned by the updated
             // function is 400. If it is, then it failed. If 
             // is not, then it succeeded.
       			if (result.statusCode != "400"){
               console.log("Validation of time parameter succeeded");
       				lambdaResult = "Succeeded";
             }
             else {
               console.log("Validation failed");
             }
       
       			// Complete the PostTraffic Hook by sending CodeDeploy the validation status
       			var params = {
       				deploymentId: deploymentId,
       				lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
       				status: lambdaResult // status can be 'Succeeded' or 'Failed'
       			};
       			
       			// Pass CodeDeploy the prepared validation test results.
       			codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) {
       				if (err) {
       					// Validation failed.
       					console.log("CodeDeploy Status update failed");
       					console.log(err, err.stack);
       					callback("CodeDeploy Status update failed");
       				} else {
       					// Validation succeeded.
       					console.log("CodeDeploy status updated successfully");
       					callback(null, "CodeDeploy status updated successfully");
       				}
       			});
       		}  
       	});
       }
   ```

# AWS SAM 애플리케이션 패키징
<a name="tutorial-lambda-sam-package"></a>

 이제 `SAM-Tutorial` 디렉터리에는 다음과 같은 네 개의 파일이 있습니다.
+ `beforeAllowTraffic.js`
+ `afterAllowTraffic.js`
+ `myDateTimeFunction.js`
+ `template.yml`

 이제 AWS SAM **sam package** 명령을 사용하여 Lambda 함수 및 CodeDeploy 애플리케이션에 대한 아티팩트를 생성하고 패키징할 준비가 되었습니다. 아티팩트는 S3 버킷에 업로드됩니다. 명령의 출력은 `package.yml`이라는 새 파일입니다. 이 파일은 다음 단계에서 AWS SAM **sam deploy** 명령에 사용됩니다.

**참고**  
 **sam package** 명령에 대한 자세한 내용은*AWS Serverless Application Model 개발자 가이드*의 [AWS SAM CLI 명령 참조](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-command-reference.html)를 참조하세요.

 `SAM-Tutorial` 디렉터리에서 다음을 실행합니다.

```
sam package \
  --template-file template.yml \
  --output-template-file package.yml \
  --s3-bucket amzn-s3-demo-bucket
```

`s3-bucket` 파라미터의 경우 이 자습서에 대한 사전 조건으로 생성한 Amazon S3 버킷을 지정합니다. 는 AWS SAM **sam deploy** 명령에서 사용하는 새 파일의 이름을 `output-template-file` 지정합니다.

# AWS SAM 애플리케이션 배포
<a name="tutorial-lambda-sam-deploy"></a>

 `package.yml` 파일과 함께 AWS SAM **sam deploy** 명령을 사용하여를 사용하여 Lambda 함수와 CodeDeploy 애플리케이션 및 배포 그룹을 생성합니다 CloudFormation.

**참고**  
**sam deploy** 명령에 대한 자세한 내용은 *AWS Serverless Application Model 개발자 가이드*의 [AWS SAM CLI 명령 참조](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-command-reference.html)를 참조하세요.

 `SAM-Tutorial` 디렉터리에서 다음 명령을 실행합니다.

```
sam deploy \
  --template-file package.yml \
  --stack-name my-date-time-app \
  --capabilities CAPABILITY_IAM
```

 `--capabilities CAPABILITY_IAM` 파라미터는 CloudFormation 을(를) 인증하여 IAM 역할을 생성하는 데 필요합니다.

# (선택 사항) 인프라 검사 및 테스트
<a name="tutorial-lambda-sam-confirm-components"></a>

 이 주제에서는 인프라 구성 요소를 보고 Lambda 함수를 테스트하는 방법을 보여 줍니다.

**`sam deploy`를 실행한 후 스택의 결과를 보려면**

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

1.  탐색 창에서 **스택**을 선택합니다. `my-date-time-app` 스택은 맨 위에 나타납니다.

1.  **Events(이벤트)** 탭을 선택하여 어떤 이벤트가 완료되었는지를 확인합니다. 스택 생성이 진행 중인 동안 이벤트를 볼 수 있습니다. 스택 생성이 완료되면 모든 스택 생성 이벤트를 볼 수 있습니다.

1.  스택이 선택된 상태에서 **Resources(리소스)**를 선택합니다. **유형** 열에서 Lambda 함수인 `myDateTimeFunction`, `CodeDeployHook_beforeAllowTraffic`, `CodeDeployHook_afterAllowTraffic`을(를) 볼 수 있습니다. 각 Lambda 함수의 **물리적 ID** 열에는 Lambda 콘솔에서 함수를 볼 수 있는 링크가 포함되어 있습니다.
**참고**  
 `myDateTimeFunction` Lambda 함수의 이름 앞에 스택 이름이 추가되고 CloudFormation 여기에 식별자가 추가되므로 처럼 보입니다`my-date-time-app-myDateTimeFunction-123456ABCDEF`.

1. [https://console.aws.amazon.com/codedeploy/](https://console.aws.amazon.com/codedeploy/)에서 CodeDeploy 콘솔을 엽니다.

1.  탐색 창에서 **배포**를 확장하고 **애플리케이션**을 선택합니다.

1.  이름이 로 시작하는 CloudFormation 에서 생성된 새 CodeDeploy 애플리케이션이 표시됩니다`my-date-time-app-ServerlessDeploymentApplication`. 이 애플리케이션을 선택합니다.

1.  `my-date-time-app-myDateTimeFunctionDeploymentGroup`으로 시작하는 이름의 배포 그룹이 보여야 합니다. 이 배포 그룹을 선택합니다.

    **Deployment configuration(배포 구성)** 아래에 **CodeDeployDefault.LambdaLinear10PercentEvery1Minute**가 보여야 합니다.

**(선택 사항) 함수를 테스트하려면(콘솔)**

1. [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) AWS Lambda 콘솔을 엽니다.

1.  탐색 창에서 `my-date-time-app-myDateTimeFunction` 함수를 선택합니다. 콘솔에서는 이름에 ID가 포함되므로 `my-date-time-app-myDateTimeFunction-123456ABCDEF`와 비슷하게 보입니다.

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

1.  **Event name(이벤트 이름)**에 테스트 이벤트의 이름을 입력합니다.

1.  테스트 이벤트에 대해 다음을 입력한 다음 **Create(생성)**을 선택합니다.

   ```
   {
     "option": "date",
     "period": "today"
   }
   ```

1.  **테스트**를 선택합니다. 테스트 이벤트 목록에서 테스트 이벤트만 보여야 합니다.

    **Execution result(실행 결과)**의 경우 **succeeded(성공)**가 보여야 합니다.

1.  **Execution result(실행 결과)**에서 **Details(세부 정보)**를 확장하여 결과를 봅니다. 현재 월, 일 및 연도가 보여야 합니다.

**(선택 사항) 함수(AWS CLI)를 테스트하려면**

1.  Lambda 함수의 ARN을 찾습니다. 함수를 볼 때 Lambda 콘솔 맨 위에 나타납니다.

1.  다음 명령을 실행합니다. *your-function-arn*을 함수ARN으로 바꿉니다.

   ```
   aws lambda invoke \
   --function your-function-arn \
   --cli-binary-format raw-in-base64-out \
   --payload "{\"option\": \"date\", \"period\": \"today\"}" out.txt
   ```

1.  `out.txt`를 열고 결과에 현재 월, 일, 연도가 포함되어 있는지 확인합니다.

# 2단계: Lambda 함수 업데이트
<a name="tutorial-lambda-sam-update-function"></a>

 이 주제에서는 `myDateTimeFunction.js` 파일을 업데이트합니다. 다음 단계에서는 이 파일을 사용하여 업데이트된 함수를 배포합니다. 이 함수는 Lambda 함수의 현재 버전에서 업데이트된 버전으로 프로덕션 트래픽을 이동하여 함수를 배포하도록 CodeDeploy를 트리거합니다.

**Lambda 함수를 업데이트하려면**

1.  `myDateTimeFunction.js`을(를) 엽니다.

1.  `switch` 블록에 있는 `time`이라는 `case`의 시작과 끝에서 두 개의 주석 마커("`/*`" 및 "`*/`")와 설명 텍스트를 제거합니다.

    주석 처리가 해제된 코드를 사용하면 새 파라미터인 `time`을 함수에 전달할 수 있습니다. `time`을 업데이트된 함수에 전달하면 이 함수는 현재 `hour`, `minute` 및 `second`를 반환합니다.

1.  `myDateTimeFunction.js`을(를) 저장합니다. 이 템플릿은 다음과 같습니다.

   ```
   'use strict';
   
   exports.handler = function(event, context, callback) {
   
     if (event.body) {
       event = JSON.parse(event.body);
     }
   
     var sc; // Status code
     var result = ""; // Response payload
   
     switch(event.option) {
       case "date":
         switch(event.period) {
           case "yesterday":
             result = setDateResult("yesterday");
             sc = 200;
             break;
           case "today":
             result = setDateResult();
             sc = 200;
             break;
           case "tomorrow":
             result = setDateResult("tomorrow");
             sc = 200;
             break;
           default:
             result = {
               "error": "Must specify 'yesterday', 'today', or 'tomorrow'."
             };
             sc = 400;
             break;
         }
         break;
         case "time":
           var d = new Date();
           var h = d.getHours();
           var mi = d.getMinutes();
           var s = d.getSeconds();
   
           result = {
             "hour": h,
             "minute": mi,
             "second": s
           };
           sc = 200;
           break;
   
         default:
           result = {
             "error": "Must specify 'date' or 'time'."
           };
           sc = 400;
         break;
     }
   
     const response = {
       statusCode: sc,
       headers: { "Content-type": "application/json" },
       body: JSON.stringify( result )
     };
   
     callback(null, response);
   
     function setDateResult(option) {
   
       var d = new Date(); // Today
       var mo; // Month
       var da; // Day
       var y; // Year
   
       switch(option) {
         case "yesterday":
           d.setDate(d.getDate() - 1);
           break;
         case "tomorrow":
           d.setDate(d.getDate() + 1);
         default:
          break;
       }
   
       mo = d.getMonth() + 1; // Months are zero offset (0-11)
       da = d.getDate();
       y = d.getFullYear();
   
       result = {
         "month": mo,
         "day": da,
         "year": y
       };
   
       return result;
     }
   };
   ```

# 3단계: 업데이트된 Lambda 함수 배포
<a name="tutorial-lambda-sam-deploy-update"></a>

 이 단계에서는 업데이트된 `myDateTimeFunction.js`을(를) 사용하여 Lambda 함수의 배포를 업데이트하고 시작합니다. CodeDeploy 또는 AWS Lambda 콘솔에서 배포 진행 상황을 모니터링할 수 있습니다.

 AWS SAM 템플릿의 `AutoPublishAlias: live` 줄을 사용하면 인프라가 `live`별칭을 사용하는 함수에 대한 업데이트를 감지합니다. 함수를 업데이트하면 함수의 원래 버전에서 업데이트된 버전으로 프로덕션 트래픽을 이동하는 CodeDeploy를 통해 배포가 트리거됩니다.

 **sam package** 및 **sam deploy** 명령은 Lambda 함수의 배포를 업데이트하고 트리거하는 데 사용됩니다. [AWS SAM 애플리케이션 패키징](tutorial-lambda-sam-package.md) 및 [AWS SAM 애플리케이션 배포](tutorial-lambda-sam-deploy.md)에서 이러한 명령을 실행했습니다 

**업데이트된 Lambda 함수를 배포하려면**

1.  `SAM-Tutorial` 디렉터리에서 다음 명령을 실행합니다.

   ```
   sam package \
     --template-file template.yml \
     --output-template-file package.yml  \
     --s3-bucket amzn-s3-demo-bucket
   ```

    그러면 S3 버킷에서 업데이트된 Lambda 함수를 참조하는 새로운 아티팩트 세트가 생성됩니다.

1.  `SAM-Tutorial` 디렉터리에서 다음 명령을 실행합니다.

   ```
   sam deploy \
     --template-file package.yml \
     --stack-name my-date-time-app \
     --capabilities CAPABILITY_IAM
   ```

   스택 이름은 여전히 이므로는 스택 업데이트임을 `my-date-time-app` CloudFormation 인식합니다. 업데이트된 스택을 보려면 CloudFormation 콘솔을 반환하고 탐색 창에서 **스택을** 선택합니다.

**(선택 사항) 배포 중에 트래픽을 보려면(CodeDeploy 콘솔)**

1. [https://console.aws.amazon.com/codedeploy/](https://console.aws.amazon.com/codedeploy/)에서 CodeDeploy 콘솔을 엽니다.

1.  탐색 창에서 **Applications(애플리케이션)**를 확장한 다음 **my-date-time-app-ServerlessDeploymentApplication** 애플리케이션을 선택합니다.

1.  **Deployment groups(배포 그룹)**에서 애플리케이션의 배포 그룹을 선택합니다. 상태는 **In progress(진행 중)**여야 합니다.

1.  **Deployment group history(배포 그룹 기록)**에서 진행 중인 배포를 선택합니다.

   **트래픽 이동** 진행률 표시줄과 이 페이지의 **원본** 및 **대체** 상자에 진행 상황이 표시됩니다.  
![\[CodeDeploy 콘솔의 트래픽 전환 진행률 섹션입니다.\]](http://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/images/lambda-tutorial-codedeploy-console-20-percent-deployed.png)

**(선택 사항) 배포 중에 트래픽을 보려면(Lambda 콘솔)**

1. [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) AWS Lambda 콘솔을 엽니다.

1.  탐색 창에서 `my-date-time-app-myDateTimeFunction` 함수를 선택합니다. 콘솔에서는 이름에 ID가 포함되므로 `my-date-time-app-myDateTimeFunction-123456ABCDEF`와 비슷하게 보입니다.

1.  **별칭**을 선택한 다음 **라이브**를 선택합니다.

원래 함수 버전(버전 1)과 업데이트된 함수 버전(버전 2) 옆에 있는 가중치는 이 AWS Lambda 콘솔 페이지가 로드될 때 얼마나 많은 트래픽이 각 버전에 제공되는지를 표시합니다. 이 페이지에서 가중치는 시간 경과에 따라 업데이트되지 않습니다. 1분에 한 번 페이지를 새로 고치면 버전 1의 가중치는 10%씩 감소하고 버전 2의 가중치가 100이 될 때까지 버전 2의 가중치는 10%씩 증가합니다.

![\[CodeDeploy 콘솔의 별칭 섹션입니다.\]](http://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/images/lambda-tutorial-lambda-console-20-percent-deployed.png)


# 4단계: 배포 결과 보기
<a name="tutorial-lambda-sam-deploy-view-results"></a>

이 단계에서는 배포의 결과를 봅니다. 배포가 성공하면 업데이트된 Lambda 함수가 프로덕션 트래픽을 수신하는 것을 확인할 수 있습니다. 배포가 실패하면 CloudWatch Logs를 사용하여 배포의 수명 주기 후크 중에 실행된 Lambda 함수에서 확인 테스트의 출력을 볼 수 있습니다.

**Topics**
+ [배포된 함수 테스트](#tutorial-lambda-sam-deploy-test-deployed-function)
+ [CloudWatch Logs에서 후크 이벤트 보기](#tutorial-lambda-view-hook-events)

## 배포된 함수 테스트
<a name="tutorial-lambda-sam-deploy-test-deployed-function"></a>

 **sam deploy** 명령은 `my-date-time-app-myDateTimeFunction` Lambda 함수를 업데이트합니다. 함수 버전은 2로 업데이트되고 `live` 별칭에 추가됩니다.

**Lambda 콘솔에서 업데이트를 보려면**

1. [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) AWS Lambda 콘솔을 엽니다.

1.  탐색 창에서 `my-date-time-app-myDateTimeFunction` 함수를 선택합니다. 콘솔에서는 이름에 ID가 포함되므로 `my-date-time-app-myDateTimeFunction-123456ABCDEF`와 비슷하게 보입니다.

1.  **Qualifiers(한정자)**를 선택한 다음 **Aliases(별칭)**를 선택합니다. 배포가 완료된(약 10분) 후, `live` 별칭에서 **Version: 2(버전 2)**가 보여야 합니다.  
![\[CodeDeploy 콘솔의 별칭 섹션입니다.\]](http://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/images/lambda-tutorial-function-version.png)

1.  **Function code(함수 코드)**에서 함수의 소스 코드를 봅니다. 변경 내용이 나타나야 합니다.

1.  (선택 사항) [2단계: Lambda 함수 업데이트](tutorial-lambda-sam-update-function.md)의 테스트 명령을 사용하여 업데이트된 함수를 테스트할 수 있습니다. 다음 페이로드가 있는 새 테스트 이벤트를 생성한 다음, 결과에 현재 시간, 분 및 초가 포함되어 있는지 확인합니다.

   ```
   {
       "option": "time"
     }
   ```

    AWS CLI 를 사용하여 업데이트된 함수를 테스트하려면 다음 명령을 실행한 다음 `out.txt`를 열어 결과에 현재 시간, 분 및 초가 포함되어 있는지 확인합니다.

   ```
   aws lambda invoke --function your-function-arn --payload "{\"option\": \"time\"}" out.txt 
   ```
**참고**  
 배포가 완료되기 전에 AWS CLI 를 사용하여 함수를 테스트하면 예상치 못한 결과가 발생할 수 있습니다. 이 결과는 CodeDeploy가 1분마다 트래픽의 10%를 업데이트된 버전으로 증분식으로 이동하기 때문입니다. 배포 중에 일부 트래픽은 여전히 원래 버전을 가리키므로, `aws lambda invoke`가 원래 버전을 사용할 수 있습니다. 10분 후에 배포가 완료되고 모든 트래픽이 함수의 새 버전을 가리킵니다.

## CloudWatch Logs에서 후크 이벤트 보기
<a name="tutorial-lambda-view-hook-events"></a>

 `BeforeAllowTraffic` 후크 중에 CodeDeploy는 `CodeDeployHook_beforeAllowTraffic` Lambda 함수를 실행합니다. `AfterAllowTraffic` 후크 중에 CodeDeploy는 `CodeDeployHook_afterAllowTraffic` Lambda 함수를 실행합니다. 각 함수는 새 `time` 파라미터를 사용하여 함수의 업데이트된 버전을 호출하는 평가 테스트를 실행합니다. Lambda 함수의 업데이트가 성공하면 `time` 옵션으로 인해 오류가 발생하지 않고 확인이 성공합니다. 함수가 업데이트되지 않은 경우 인식되지 않는 파라미터로 인해 오류가 발생하고 확인이 실패합니다. 이러한 확인 테스트는 데모용일 뿐입니다. 각자 고유의 테스트를 작성하여 배포를 확인합니다. CloudWatch Logs 콘솔을 사용하여 확인 테스트를 볼 수 있습니다.

**CodeDeploy 후크 이벤트를 보려면**

1. [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)에서 CloudWatch 콘솔을 엽니다.

1.  탐색 창에서 **로그**를 선택합니다.

1.  로그 그룹 목록에서 **/aws/lambda/CodeDeployHook\$1beforeAllowTraffic** 또는 **/aws/lambda/CodeDeployHook\$1afterAllowTraffic**을 선택합니다.

1.  로그 스트림을 선택합니다. 하나만 보여야 합니다.

1.  이벤트를 확장하여 세부 정보를 확인합니다.  
![\[CodeDeployHook 로그 그룹의 로그 스트림입니다.\]](http://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/images/lambda-tutorial-cloudwatch.png)

# 5단계: 정리
<a name="tutorial-lambda-clean-up"></a>

이 자습서에서 사용한 리소스에 대한 추가 요금이 부과되지 않도록 AWS SAM 템플릿에서 생성한 리소스와 Lambda 검증 함수에서 생성한 CloudWatch 로그를 삭제합니다.

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

1. 에 로그인 AWS Management Console 하고 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/) CloudFormation 콘솔을 엽니다.

1. **Stacks(스택)** 열에서 `my-date-time-app` 스택을 선택한 다음 **Delete(삭제)**를 선택합니다.

1. 메시지가 나타나면 **스택 삭제**를 선택합니다. 에서 생성한 Lambda 함수, CodeDeploy 애플리케이션 및 배포 그룹, IAM 역할 AWS SAM 이 삭제됩니다.

**CloudWatch Logs에서 로그를 삭제하려면**

1. [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)에서 CloudWatch 콘솔을 엽니다.

1.  탐색 창에서 **로그**를 선택합니다.

1.  로그 그룹 목록에서 **/aws/lambda/CodeDeployHook\$1beforeAllowTraffic** 옆의 버튼을 선택합니다.

1.  **Actions(작업)**에서 **Delete log group(로그 그룹 삭제)**을 선택한 다음 **Yes, Delete(예, 삭제합니다)**를 선택합니다.

1.  로그 그룹 목록에서 **/aws/lambda/CodeDeployHook\$1afterAllowTraffic** 옆의 버튼을 선택합니다.

1.  **Actions(작업)**에서 **Delete log group(로그 그룹 삭제)**을 선택한 다음 **Yes, Delete(예, 삭제합니다)**를 선택합니다.