AWS CDK에서 Stack은 CloudFormation의 Stack과 1:1로 매핑되는 배포 단위입니다.
CDK 명령어로 cdk deploy를 실행할 때 대상이 되는 것은 항상 Stack이다. 특정 리소스 하나만 배포하는 것이 아니라 그 리소스가 속한 Stack 전체가 하나의 트랜잭션으로 배포된다.
하나의 Stack은 하나의 AWS 계정과 리전에 귀속된다.
AWS CloudFormation의 제약을 그대로 따른다. 하나의 Stack에는 최대 500개의 리소스만 포함할 수 있다. (대규모 프로젝트에서 Stack 분할이 필요한 이유이다.)
서로 다른 Stack끼리 데이터를 주고받을 때 두 가지 방식이 있다.
모든 것을 한 Stack에 담지 마세요. 보통 다음과 같이 분리합니다.
동일한 Stack 클래스를 사용하여 개발(Dev)과 운영(Prod) 환경을 다르게 구성한다.
public class MyCdkApp {
public static void main(final String[] args) {
software.amazon.awscdk.App app = new software.amazon.awscdk.App();
// [환경별 매개변수화]
// 계정 ID와 리전 정보를 객체로 정의하여 환경을 분리합니다.
Environment devEnv = Environment.builder()
.account("123456789012")
.region("ap-northeast-2")
.build();
Environment prodEnv = Environment.builder()
.account("987654321098")
.region("us-east-1")
.build();
// 개발 환경 배포
NetworkStack devNetwork = new NetworkStack(app, "DevNetworkStack",
StackProps.builder().env(devEnv).build());
new AppStack(app, "DevAppStack",
StackProps.builder().env(devEnv).build(), devNetwork.getVpc());
// 운영 환경 배포 (다른 사양 적용 가능)
new NetworkStack(app, "ProdNetworkStack",
StackProps.builder().env(prodEnv).build());
app.synth();
}
}
/**
* 네트워크 인프라 스택 (네트워크 정보를 Export하는 역할)
*/
public class NetworkStack extends Stack {
private final IVpc vpc;
public NetworkStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
// VPC 생성 (L2 Construct)
this.vpc = Vpc.Builder.create(this, "MyVPC")
.maxAzs(2)
.build();
// [CloudFormation Export 방식]
// 다른 스택에서 참조할 수 있도록 VPC ID를 Export합니다.
// 배포 시 CloudFormation의 'Outputs' 탭에 나타납니다.
CfnOutput.Builder.create(this, "VpcIdOutput")
.value(this.vpc.getVpcId())
.exportName("MySharedVpcId") // 이것이 Export 이름이 됩니다.
.build();
}
public IVpc getVpc() {
return this.vpc;
}
}
/**
* 애플리케이션 스택 (네트워크 정보를 Import하여 사용하는 역할)
*/
public class AppStack extends Stack {
public AppStack(final Construct scope, final String id, final StackProps props, IVpc vpc) {
super(scope, id, props);
// 1. 직접 객체를 넘겨받는 방식 (CDK가 내부적으로 ImportValue를 생성)
System.out.println("참조된 VPC ID: " + vpc.getVpcId());
// 2. 만약 다른 프로젝트의 스택이라면 아래와 같이 이름을 지정해 가져옵니다.
// IVpc importedVpc = Vpc.fromLookup(this, "ImportedVPC", VpcLookupOptions.builder()
// .vpcId(Fn.importValue("MySharedVpcId"))
// .build());
}
}
terminationProtection: true 설정을 했는가?Project, Stage 등)를 일괄 적용했는가?cdk diff를 통해 변경 사항을 확인하는 습관을 가졌는가?