AWS CDK를 사용하여 Lambda 함수 배포 - AWS Lambda

AWS CDK를 사용하여 Lambda 함수 배포

AWS Cloud Development Kit (AWS CDK)는 사용자가 선택한 프로그래밍 언어를 사용하여 AWS 클라우드 인프라를 정의하는 데 사용할 수 있는 코드형 인프라(IaC) 프레임워크입니다. 자체 클라우드 인프라를 정의하려면 먼저 하나 이상의 스택을 포함하는 앱(CDK 지원 언어 중 하나로)을 작성해야 합니다. 그런 다음 합성하여 AWS CloudFormation 템플릿을 만들고 리소스를 AWS 계정에 배포합니다. 이 주제의 단계에 따라 Amazon API Gateway 엔드포인트에서 이벤트를 반환하는 Lambda 함수를 배포하세요.

CDK에 포함된 AWS Construct Library는 AWS 서비스가 제공하는 리소스를 모델링하는 데 사용할 수 있는 모듈을 제공합니다. 많이 사용되는 서비스의 라이브러리는 스마트 기본값과 모범 사례를 통해 큐레이트된 구조를 제공합니다. aws_lambda 모듈을 사용하여 단 몇 줄의 코드로 함수와 지원하는 리소스를 정의할 수 있습니다.

사전 조건

이 지침을 시작하기 전에 다음 명령을 실행하여 AWS CDK를 설치합니다.

npm install -g aws-cdk

1단계: AWS CDK 프로젝트 설정

새 AWS CDK 앱에 대한 디렉터리를 생성하고 프로젝트를 초기화합니다.

JavaScript
mkdir hello-lambda cd hello-lambda cdk init --language javascript
TypeScript
mkdir hello-lambda cd hello-lambda cdk init --language typescript
Python
mkdir hello-lambda cd hello-lambda cdk init --language python

프로젝트가 시작되면 프로젝트의 가상 환경을 활성화하고 AWS CDK의 기준선 종속성을 설치합니다.

source .venv/bin/activate python -m pip install -r requirements.txt
Java
mkdir hello-lambda cd hello-lambda cdk init --language java

이 Maven 프로젝트를 Java 통합 개발 환경(IDE)으로 가져옵니다. 예를 들어 Eclipse에서 파일, 가져오기, Maven, 기존 Maven 프로젝트를 사용합니다.

C#
mkdir hello-lambda cd hello-lambda cdk init --language csharp
참고

AWS CDK 애플리케이션 템플릿은 프로젝트 디렉토리의 이름을 사용하여 소스 파일 및 클래스의 이름을 생성합니다. 이 예에서 디렉터리 이름은 hello-lambda입니다. 다른 프로젝트 디렉터리 이름을 사용하는 경우 앱이 이 지침과 일치하지 않습니다.

AWS CDK v2에는 aws-cdk-lib라는 단일 패키지에 모든 AWS 서비스에 대한 안정적인 구성이 포함되어 있습니다. 이 패키지는 프로젝트를 초기화하거나 종속 항목으로 설치됩니다. 특정 프로그래밍 언어로 작업하는 경우 프로젝트를 처음 빌드할 때 패키지가 설치됩니다.

2단계: AWS CDK 스택 삭제

CDK 스택은 AWS 리소스를 정의하는 하나 이상의 구문의 모음입니다. 각 CDK 스택은 CDK 앱의 AWS CloudFormation 스택을 나타냅니다.

CDK를 정의하려면 선호하는 프로그래밍 언어에 대한 지침을 따르세요. 이 스택은 다음을 정의합니다.

  • 함수의 논리명: MyFunction

  • code 속성에 지정된 함수 코드의 위치. 자세한 내용은 AWS Cloud Development Kit (AWS CDK) API ReferenceHandler Code를 참조하세요.

  • REST API의 논리명: HelloApi

  • API Gateway 엔드포인트의 논리명: ApiGwEndpoint

이 지침의 모든 CDK 스택은 Lambda 함수에 Node.js 런타임을 사용한다는 점에 유의하세요. CDK 스택과 Lambda 함수에 다양한 프로그래밍 언어를 사용하여 각 언어의 장점을 활용할 수 있습니다. 예를 들어 CDK 스택에 TypeScript를 사용하여 인프라 코드에 정적 입력의 이점을 활용할 수 있습니다. Lambda 함수에 JavaScript를 사용하여 동적으로 입력되는 언어의 유연성과 빠른 개발의 이점을 활용할 수 있습니다.

JavaScript

lib/hello-lambda-stack.js 파일을 열고 내용을 다음으로 바꿉니다.

const { Stack } = require('aws-cdk-lib'); const lambda = require('aws-cdk-lib/aws-lambda'); const apigw = require('aws-cdk-lib/aws-apigateway'); class HelloLambdaStack extends Stack { /** * * @param {Construct} scope * @param {string} id * @param {StackProps=} props */ constructor(scope, id, props) { super(scope, id, props); const fn = new lambda.Function(this, 'MyFunction', { code: lambda.Code.asset('lib/lambda-handler'), runtime: lambda.Runtime.NODEJS_LATEST, handler: 'index.handler' }); const endpoint = new apigw.LambdaRestApi(this, 'MyEndpoint', { handler: fn, restApiName: "HelloApi" }); } } module.exports = { HelloLambdaStack }
TypeScript

lib/hello-lambda-stack.ts 파일을 열고 내용을 다음으로 바꿉니다.

import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as apigw from "aws-cdk-lib/aws-apigateway"; import * as lambda from "aws-cdk-lib/aws-lambda"; import * as path from 'node:path'; export class HelloLambdaStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps){ super(scope, id, props) const fn = new lambda.Function(this, 'MyFunction', { runtime: lambda.Runtime.NODEJS_LATEST, handler: 'index.handler', code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')), }); const endpoint = new apigw.LambdaRestApi(this, `ApiGwEndpoint`, { handler: fn, restApiName: `HelloApi`, }); } }
Python

/hello-lambda/hello_lambda/hello_lambda_stack.py 파일을 열고 내용을 다음으로 바꿉니다.

from aws_cdk import ( Stack, aws_apigateway as apigw, aws_lambda as _lambda ) from constructs import Construct class HelloLambdaStack(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) fn = _lambda.Function( self, "MyFunction", runtime=_lambda.Runtime.NODEJS_LATEST, handler="index.handler", code=_lambda.Code.from_asset("lib/lambda-handler") ) endpoint = apigw.LambdaRestApi( self, "ApiGwEndpoint", handler=fn, rest_api_name="HelloApi" )
Java

/hello-lambda/src/main/java/com/myorg/HelloLambdaStack.java 파일을 열고 내용을 다음으로 바꿉니다.

package com.myorg; import software.constructs.Construct; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; import software.amazon.awscdk.services.apigateway.LambdaRestApi; import software.amazon.awscdk.services.lambda.Function; public class HelloLambdaStack extends Stack { public HelloLambdaStack(final Construct scope, final String id) { this(scope, id, null); } public HelloLambdaStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); Function hello = Function.Builder.create(this, "MyFunction") .runtime(software.amazon.awscdk.services.lambda.Runtime.NODEJS_LATEST) .code(software.amazon.awscdk.services.lambda.Code.fromAsset("lib/lambda-handler")) .handler("index.handler") .build(); LambdaRestApi api = LambdaRestApi.Builder.create(this, "ApiGwEndpoint") .restApiName("HelloApi") .handler(hello) .build(); } }
C#

src/HelloLambda/HelloLambdaStack.cs 파일을 열고 내용을 다음으로 바꿉니다.

using Amazon.CDK; using Amazon.CDK.AWS.APIGateway; using Amazon.CDK.AWS.Lambda; using Constructs; namespace HelloLambda { public class HelloLambdaStack : Stack { internal HelloLambdaStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { var fn = new Function(this, "MyFunction", new FunctionProps { Runtime = Runtime.NODEJS_LATEST, Code = Code.FromAsset("lib/lambda-handler"), Handler = "index.handler" }); var api = new LambdaRestApi(this, "ApiGwEndpoint", new LambdaRestApiProps { Handler = fn }); } } }

3단계: Lambda 함수 코드 생성

  1. 프로젝트 루트(hello-lambda)에서 Lambda 함수 코드에 대한 /lib/lambda-handler 디렉터리를 생성합니다. 이 디렉터리는 AWS CDK 스택의 code 속성에 지정됩니다.

  2. index.js 디렉터리에서 /lib/lambda-handler라는 파일을 새로 생성합니다. 다음 코드를 파일에 붙여 넣습니다. 함수는 API 요청에서 특정 속성을 추출하여 JSON 응답으로 반환합니다.

    exports.handler = async (event) => { // Extract specific properties from the event object const { resource, path, httpMethod, headers, queryStringParameters, body } = event; const response = { resource, path, httpMethod, headers, queryStringParameters, body, }; return { body: JSON.stringify(response, null, 2), statusCode: 200, }; };

4단계: AWS CDK 스택 배포

  1. 프로젝트의 루트에서 cdk synth 명령을 실행합니다.

    cdk synth

    이 명령은 CDK 스택에서 AWS CloudFormation 템플릿을 합성합니다. 템플릿은 다음과 유사한 약 400줄의 YAML 파일입니다.

    참고

    다음 오류가 발생하면 현재 위치가 프로젝트 디렉터리의 루트인지 확인합니다.

    --app is required either in command-line, in cdk.json or in ~/.cdk.json
    예 AWS CloudFormation 템플릿
    Resources: MyFunctionServiceRole3C357FF2: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com Version: "2012-10-17" ManagedPolicyArns: - Fn::Join: - "" - - "arn:" - Ref: AWS::Partition - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Metadata: aws:cdk:path: HelloLambdaStack/MyFunction/ServiceRole/Resource MyFunction1BAA52E7: Type: AWS::Lambda::Function Properties: Code: S3Bucket: Fn::Sub: cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region} S3Key: ab1111111cd32708dc4b83e81a21c296d607ff2cdef00f1d7f48338782f92l3901.zip Handler: index.handler Role: Fn::GetAtt: - MyFunctionServiceRole3C357FF2 - Arn Runtime: nodejs20.x ...
  2. cdk deploy 명령을 실행합니다.

    cdk deploy

    리소스가 생성되는 동안 기다립니다. 최종 출력에는 API Gateway 엔드포인트의 URL이 포함됩니다. 예시

    Outputs: HelloLambdaStack.ApiGwEndpoint77F417B1 = https://abcd1234.execute-api.us-east-1.amazonaws.com/prod/

5단계: 함수 테스트

Lambda 함수를 간접적으로 호출하려면 API Gateway 엔드포인트를 복사하여 웹 브라우저에 붙여넣거나 curl 명령을 실행합니다.

curl -s https://abcd1234.execute-api.us-east-1.amazonaws.com/prod/

응답은 원래 이벤트 객체에서 선택한 속성을 JSON으로 표현한 것으로, API Gateway 엔드포인트에 대한 요청 정보를 담고 있습니다. 예시

{ "resource": "/", "path": "/", "httpMethod": "GET", "headers": { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding": "gzip, deflate, br, zstd", "Accept-Language": "en-US,en;q=0.9", "CloudFront-Forwarded-Proto": "https", "CloudFront-Is-Desktop-Viewer": "true", "CloudFront-Is-Mobile-Viewer": "false", "CloudFront-Is-SmartTV-Viewer": "false", "CloudFront-Is-Tablet-Viewer": "false", "CloudFront-Viewer-ASN": "16509", "CloudFront-Viewer-Country": "US", "Host": "abcd1234.execute-api.us-east-1.amazonaws.com", ...

6단계: 리소스 정리

API Gateway 엔드포인트는 공개적으로 액세스할 수 있습니다. 예상치 못한 요금이 부과되지 않도록 하려면 cdk destroy 명령을 실행하여 스택과 모든 관련 리소스를 삭제하세요.

cdk destroy

다음 단계

선택한 언어로 AWS CDK 앱을 작성하는 방법에 대한 내용은 다음을 참조하세요.

TypeScript

TypeScript에서 AWS CDK 작업

JavaScript

JavaScript에서 AWS CDK 작업

Python

Python에서 AWS CDK 작업

Java

Java에서 AWS CDK 작업

C#

C#에서 AWS CDK 작업

Go

Go에서 AWS CDK 작업