Serverless에서 DynamoDB 설정하기
서버리스에서 DynamoDB 설정하기
우리의 Serverless Framework 앱에서, 이전에 AWS 콘솔을 통해 DynamoDB 테이블을 생성했습니다. 여러 앱이나 환경을 만들 때 이 방법은 번거로울 수 있습니다. 이상적으로는 이를 프로그래밍적으로 할 수 있기를 원합니다. 이번 섹션에서는 코드로서의 인프라를 사용하여 이를 수행하는 방법을 살펴보겠습니다.
리소스 생성하기
Serverless Framework는 CloudFormation을 지원하여 인프라를 코드로 구성할 수 있게 도와줍니다. CloudFormation은 AWS 콘솔을 사용하지 않고 YAML이나 JSON을 통해 AWS 리소스를 정의하는 방법입니다. 이에 대해 이번 섹션에서 자세히 다룰 예정입니다.
리소스를 추가할 디렉토리를 생성해 보겠습니다.
$ mkdir resources/
resources/dynamodb-table.yml
에 다음 내용을 추가합니다.
Resources:
NotesTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:custom.tableName}
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
- AttributeName: noteId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: noteId
KeyType: RANGE
# 용량을 자동 조정으로 설정
BillingMode: PAY_PER_REQUEST
여기서 무엇을 하고 있는지 간단히 살펴보겠습니다.
-
NotesTable
이라는 이름의 DynamoDB 테이블 리소스를 정의합니다. -
테이블 이름은
${self:custom.tableName}
이라는 커스텀 변수에서 가져옵니다. 이 변수는serverless.yml
에서 동적으로 생성됩니다. 이에 대해 아래에서 자세히 살펴볼 예정입니다. -
테이블의 두 속성인
userId
와noteId
를 구성하고, 이를 기본 키로 지정합니다. -
마지막으로, 테이블의 읽기/쓰기 용량을 몇 가지 커스텀 변수를 통해 프로비저닝합니다. 이 부분도 곧 정의할 예정입니다.
리소스 추가하기
이제 프로젝트에 이 리소스를 참조하도록 추가해 보겠습니다.
serverless.yml
파일 하단에 다음 resources:
블록을 추가합니다.
# CloudFormation 템플릿을 사용해 리소스 생성
resources:
# DynamoDB
- ${file(resources/dynamodb-table.yml)}
serverless.yml
파일 상단의 provider:
블록 위에 다음 custom:
블록을 추가합니다.
custom:
# serverless 명령어 실행 시 전달된 stage 값을 사용하거나,
# provider 섹션에 설정된 값으로 대체
stage: ${opt:stage, self:provider.stage}
# 로컬 테스트 시 사용할 테이블 이름 설정
tableName: ${self:custom.stage}-notes
여기서 몇 가지 중요한 내용을 추가했습니다.
-
먼저
stage
라는 커스텀 변수를 생성했습니다. 이미provider:
블록에stage: dev
가 설정되어 있는데, 왜 커스텀 변수가 필요한지 궁금할 수 있습니다. 이는serverless deploy --stage $STAGE
명령어를 통해 전달된 stage 값을 사용하고, stage가 설정되지 않은 경우 provider 블록의 값으로 대체하기 위함입니다.${opt:stage, self:provider.stage}
는 Serverless Framework에게 먼저opt:stage
(커맨드라인으로 전달된 값)를 찾고, 그다음self:provider.stage
(provider 블록의 값)로 대체하도록 지시합니다. -
테이블 이름은 배포하는 stage에 따라 동적으로 설정됩니다.
${self:custom.stage}-notes
. 이렇게 동적으로 설정하는 이유는 새로운 stage(환경)에 배포할 때마다 별도의 테이블을 생성하기 위함입니다. 예를 들어dev
에 배포하면dev-notes
라는 DynamoDB 테이블이 생성되고,prod
에 배포하면prod-notes
테이블이 생성됩니다. 이를 통해 다양한 환경에서 사용하는 리소스(및 데이터)를 명확히 분리할 수 있습니다. -
마지막으로
BillingMode
에PAY_PER_REQUEST
설정을 사용합니다. 이는 DynamoDB에게 요청당 비용을 지불하고 On-Demand Capacity 옵션을 사용하도록 지시합니다. On-Demand 모드에서는 데이터베이스가 진정한 서버리스가 됩니다. 이 옵션은 특히 시작 단계에서 워크로드가 예측 불가능하거나 안정적이지 않을 때 매우 비용 효율적입니다. 반면, 필요한 용량을 정확히 알고 있다면 Provisioned Capacity 모드가 더 저렴할 수 있습니다.
위 내용이 지금은 복잡하고 어려워 보일 수 있습니다. 하지만 전체 설정을 쉽게 자동화하고 복제할 수 있도록 준비하는 과정입니다. Serverless Framework(및 내부의 CloudFormation)은 serverless.yml
을 기반으로 리소스를 완전히 관리합니다. 이는 테이블 이름에 오타가 있는 경우, 기존 테이블이 삭제되고 새 테이블이 생성된다는 의미입니다. 서버리스 리소스(예: DynamoDB 테이블)를 실수로 삭제하는 것을 방지하려면 DeletionPolicy: Retain
플래그를 설정해야 합니다. 이에 대한 자세한 내용은 Seed 블로그 포스트에서 확인할 수 있습니다.
이제 생성할 DynamoDB 리소스를 참조하도록 빠르게 수정해 보겠습니다.
환경 변수를 새로 생성된 테이블 이름으로 업데이트합니다. environment:
블록을 다음으로 교체합니다.
# 이 환경 변수들은 함수에서 process.env로 사용 가능
environment:
tableName: ${self:custom.tableName}
stripeSecretKey: ${env:STRIPE_SECRET_KEY}
serverless.yml
파일의 iamRoleStatements:
블록을 다음으로 교체합니다.
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:DescribeTable
- dynamodb:Query
- dynamodb:Scan
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
# IAM 역할 권한을 특정 stage의 테이블로 제한
Resource:
- "Fn::GetAtt": [ NotesTable, Arn ]
들여쓰기를 정확히 복사해야 합니다. 이 두 블록은 provider
블록 아래에 속하므로 그에 맞게 들여쓰기 해야 합니다.
여기서 몇 가지 흥미로운 작업을 수행했습니다.
-
environment:
블록은 Serverless Framework에게 Lambda 함수에서process.env
로 사용할 수 있는 변수를 설정하도록 지시합니다. 예를 들어,process.env.tableName
은 이 stage의 DynamoDB 테이블 이름으로 설정됩니다. 나중에 데이터베이스에 연결할 때 이 값이 필요합니다. -
tableName
의 경우, 위에서 설정한 커스텀 변수를 참조합니다. -
iamRoleStatements:
의 경우, 연결할 테이블을 명시적으로 지정합니다. 이 블록은 AWS에게 Lambda 함수가 접근할 수 있는 리소스를 제한하도록 지시합니다.
다음으로, 파일 업로드를 위한 S3 버킷을 추가해 보겠습니다.
For help and discussion
Comments on this chapter