서버리스 리소스 이름 파라미터화하기
서버리스 리소스 이름 파라미터화
여러 환경을 배포할 때, 특히 동일한 AWS 계정 내에 여러 환경을 배포하거나 여러 AWS 계정에 걸쳐 배포하는 경우, 리소스 이름이 환경 간에 충돌하지 않도록 해야 합니다. 예를 들어, checkout-api
서비스에서 checkout
이라는 이름의 Lambda 함수가 있다고 가정해 보겠습니다. 두 명의 개발자가 각각 다른 기능을 개발 중이고, 한 명은 featureA
환경에 배포하고 다른 한 명은 featureB
환경에 배포한다면, 두 환경 모두 Dev
AWS 계정에 배포될 경우, 한 환경만 성공적으로 배포될 수 있습니다. 두 번째 환경은 checkout
이라는 이름의 Lambda 함수가 이미 존재한다는 오류를 발생시킬 것입니다.
AWS 리소스는 특정 범위 내에서 고유한 이름을 가져야 하며, 이 범위는 리소스 유형에 따라 다릅니다. 일반적으로 사용되는 서버리스 리소스에 대한 규칙은 다음과 같습니다:
- 계정 및 리전 내에서 고유: Lambda 함수, API Gateway 프로젝트, SNS 토픽 등
- 계정 내에서 고유 (모든 리전에 걸쳐): IAM 사용자/역할
- 전역적으로 고유: S3 버킷
고유성을 보장하기 위한 가장 좋은 방법은 리소스 이름에 스테이지 이름을 파라미터로 포함시키는 것입니다. 예를 들어, featureA
스테이지에서는 Lambda 함수 이름을 checkout-featureA
로, featureB
스테이지에서는 checkout-featureB
로, dev
스테이지에서는 checkout-dev
로 지정할 수 있습니다.
다행히 Serverless Framework는 이미 몇 가지 기본 리소스에 대해 파라미터화를 지원합니다:
리소스 | 스키마 | 예시 |
---|---|---|
Lambda 함수 | $serviceName-$stage-$functionName |
notes-app-ext-notes-api-dev-get |
API Gateway 프로젝트 | $stage-$serviceName |
dev-notes-app-ext-notes-api |
CloudWatch 로그 그룹 | /aws/lambda/$serviceName-$stage-$functionName |
/aws/lambda/notes-app-ext-notes-api-dev-get |
IAM 역할 | $serviceName-$stage-$region-lambdaRole |
notes-app-ext-notes-api-dev-us-east-1-lambdaRole |
S3 버킷 | $stackName-$resourceName-$hash |
notes-app-ext-notes-api-serverlessdeploymentbuck-19fhidl3prw0m |
여기서 주의할 점은 다음과 같습니다:
- 리소스 이름은
$serviceName
으로 파라미터화되어 여러 서비스를 배포할 때 리소스 이름이 충돌하지 않도록 합니다. - IAM 역할은 Lambda 함수가 사용하는 역할입니다. IAM 역할 이름은 계정 내에서 리전 간에 고유해야 하므로
$region
으로 파라미터화됩니다. - S3 버킷은 Serverless Framework가 배포 아티팩트를 저장하는 데 사용됩니다. 이름이 지정되지 않으며, 이 경우 CloudFormation은 현재 스택 이름(
$stackName
)을 기반으로 고유한 이름을 자동으로 할당합니다.
serverless.yml
에서 정의하는 다른 모든 리소스에 대해서는 우리가 직접 파라미터화를 해야 합니다.
리소스 이름을 파라미터화해야 하는 몇 가지 예시를 살펴보겠습니다.
billing-api
서비스의 SNS 토픽 이름
resources:
Resources:
NotePurchasedTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: ${self:custom.stage}-note-purchased
CDK에서 SST를 사용해 리소스 파라미터화하기
CDK에서는 SST를 사용해 스택 이름을 자동으로 파라미터화합니다. 또한 특정 리소스 이름을 파라미터화하기 위해 헬퍼 메서드를 사용합니다.
예를 들어, 리소스 저장소의 stacks/index.js
파일에서 다음과 같이 작성할 수 있습니다.
export default function main(app) {
new DynamoDBStack(app, "dynamodb");
const s3 = new S3Stack(app, "s3");
new CognitoStack(app, "cognito", { bucketArn: s3.bucket.bucketArn });
}
여기서 스택 이름은 dynamodb
, s3
, cognito
로 지정되었습니다. 하지만 이 스택들이 배포될 때는 다음과 같이 배포됩니다.
dev-notes-ext-infra-dynamodb
dev-notes-ext-infra-s3
dev-notes-ext-infra-cognito
여기서 dev
는 배포할 스테이지이고, notes-ext-infra
는 sst.json
에 지정된 SST 앱의 이름입니다.
CloudFormation exports와 같은 특정 리소스의 경우 app.logicalPrefixedName
헬퍼 메서드를 사용합니다. stacks/DynamoDBStack.js
에서의 예제는 다음과 같습니다.
new CfnOutput(this, "TableName", {
value: table.tableName,
exportName: app.logicalPrefixedName("ExtTableName"),
});
app.logicalPrefixedName
은 스테이지 이름과 앱 이름을 접두사로 붙여 export 이름을 생성합니다.
리소스를 파라미터화하면 여러 환경에 앱을 배포할 때 이름 충돌 없이 배포할 수 있습니다. 이제 앱을 배포해 봅시다!
For help and discussion
Comments on this chapter