CDK AWS v2 개발자 안내서입니다. 이전 CDK v1은 2022년 6월 1일에 유지 관리에 들어갔으며 2023년 6월 1일에 지원이 종료되었습니다.
기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
식별자 및 AWS CDK
AWS 클라우드 개발 키트(AWS CDK) 앱을 빌드할 때 다양한 유형의 식별자와 이름을 사용합니다. AWS CDK를 효과적으로 사용하고 오류를 방지하려면 식별자 유형을 이해하는 것이 중요합니다.
식별자는 생성된 범위 내에서 고유해야 하며 AWS CDK 애플리케이션에서 전역적으로 고유할 필요는 없습니다.
동일한 범위 내에서 동일한 값을 가진 식별자를 생성하려고 하면 AWS CDK에서 예외가 발생합니다.
구문 ID
가장 일반적인 식별자인 id는 구문 객체를 인스턴스화할 때 두 번째 인수로 전달되는 식별자입니다. 이 식별자는 모든 식별자와 마찬가지로 구문 객체를 인스턴스화할 때 첫 번째 인수인 생성 범위 내에서만 고유하면 됩니다.
앱에 식별자가 MyBucket인 2개의 구문이 있는 예를 살펴보겠습니다. 첫 번째는 식별자가 Stack1인 스택의 범위에 정의됩니다. 두 번째는 식별자가 Stack2인 스택의 범위에 정의됩니다. 서로 다른 범위로 정의되므로 충돌이 발생하지 않으며 문제없이 동일한 앱에서 공존할 수 있습니다.
예
- TypeScript
-
import { App, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
class MyStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps = {}) {
super(scope, id, props);
new s3.Bucket(this, 'MyBucket');
}
}
const app = new App();
new MyStack(app, 'Stack1');
new MyStack(app, 'Stack2');
- JavaScript
-
const { App , Stack } = require('aws-cdk-lib');
const s3 = require('aws-cdk-lib/aws-s3');
class MyStack extends Stack {
constructor(scope, id, props = {}) {
super(scope, id, props);
new s3.Bucket(this, 'MyBucket');
}
}
const app = new App();
new MyStack(app, 'Stack1');
new MyStack(app, 'Stack2');
- Python
-
from aws_cdk import App, Construct, Stack, StackProps
from constructs import Construct
from aws_cdk import aws_s3 as s3
class MyStack(Stack):
def __init__(self, scope: Construct, id: str, **kwargs):
super().__init__(scope, id, **kwargs)
s3.Bucket(self, "MyBucket")
app = App()
MyStack(app, 'Stack1')
MyStack(app, 'Stack2')
- Java
-
// MyStack.java
package com.myorg;
import software.amazon.awscdk.App;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.constructs.Construct;
import software.amazon.awscdk.services.s3.Bucket;
public class MyStack extends Stack {
public MyStack(final Construct scope, final String id) {
this(scope, id, null);
}
public MyStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
new Bucket(this, "MyBucket");
}
}
// Main.java
package com.myorg;
import software.amazon.awscdk.App;
public class Main {
public static void main(String[] args) {
App app = new App();
new MyStack(app, "Stack1");
new MyStack(app, "Stack2");
}
}
- C#
-
using Amazon.CDK;
using constructs;
using Amazon.CDK.AWS.S3;
public class MyStack : Stack
{
public MyStack(Construct scope, string id, IStackProps props) : base(scope, id, props)
{
new Bucket(this, "MyBucket");
}
}
class Program
{
static void Main(string[] args)
{
var app = new App();
new MyStack(app, "Stack1");
new MyStack(app, "Stack2");
}
}
경로
AWS CDK 애플리케이션의 구문은 App 클래스에 기반한 계층 구조를 형성합니다. 지정된 구문, 상위 구문, 차상위 구문 등부터 구문 트리의 루트까지의 ID 컬렉션을 경로라고 합니다.
AWS CDK는 일반적으로 템플릿의 경로를 문자열로 표시합니다. 레벨의 ID는 일반적으로 스택인 루트 App 인스턴스 바로 아래의 노드에서 시작하는 슬래시로 구분됩니다. 예를 들어 이전 코드 예제에서 두 Amazon S3 버킷 리소스의 경로는 Stack1/MyBucket 및 Stack2/MyBucket입니다.
다음 예와 같이 프로그래밍 방식으로 모든 구문의 경로에 액세스할 수 있습니다. 이는 myConstruct 또는 my_construct(Python 개발자가 작성)의 경로를 가져옵니다. IDs는 생성된 범위 내에서 고유해야 하므로 해당 경로는 AWS CDK 애플리케이션 내에서 항상 고유합니다.
예
- TypeScript
-
const path: string = myConstruct.node.path;
- JavaScript
-
const path = myConstruct.node.path;
- Python
-
path = my_construct.node.path
- Java
-
String path = myConstruct.getNode().getPath();
- C#
-
string path = myConstruct.Node.Path;
고유 ID
AWS CloudFormation에서는 템플릿의 모든 논리적 IDs가 고유해야 합니다. 따라서 AWS CDK는 애플리케이션의 각 구문에 대해 고유 식별자를 생성할 수 있어야 합니다. 리소스에는 전역적으로 고유한 경로(스택에서 특정 리소스까지의 모든 범위 이름)가 있습니다. 따라서 AWS CDK는 경로의 요소를 연결하고 8자리 해시를 추가하여 필요한 고유 식별자를 생성합니다. (해시는 A/B/C 및와 같이 동일한 AWS CloudFormation 식별자를 생성하는 고유한 경로를 구분A/BC하는 데 필요합니다. AWS CloudFormation 식별자는 영숫자이며 슬래시 또는 기타 구분 문자를 포함할 수 없습니다.) AWS CDK는이 문자열을 구문의 고유 ID라고 합니다.
일반적으로 AWS CDK 앱은 고유 IDs에 대해 알 필요가 없습니다. 그러나 다음 예와 같이 프로그래밍 방식으로 모든 구문의 고유 ID에 액세스할 수 있습니다.
예
- TypeScript
-
const uid: string = Names.uniqueId(myConstruct);
- JavaScript
-
const uid = Names.uniqueId(myConstruct);
- Python
-
uid = Names.unique_id(my_construct)
- Java
-
String uid = Names.uniqueId(myConstruct);
- C#
-
string uid = Names.Uniqueid(myConstruct);
주소는 CDK 리소스를 고유하게 구분하는 또 다른 종류의 고유 식별자입니다. 경로의 SHA-1 해시에서 파생되어 사람이 읽을 수 없습니다. 그러나 길이가 일정하고 비교적 짧기 때문에(항상 42개의 16진수 문자) ’전통적’ 고유 ID가 너무 길 수 있는 상황에서 유용합니다. 일부 구문은 고유한 ID 대신 synthesized AWS CloudFormation 템플릿의 주소를 사용할 수 있습니다. 다시 말해, 앱은 일반적으로 해당 구문의 주소를 알 필요가 없지만 다음과 같이 구문의 주소를 검색할 수 있습니다.
예
- TypeScript
-
const addr: string = myConstruct.node.addr;
- JavaScript
-
const addr = myConstruct.node.addr;
- Python
-
addr = my_construct.node.addr
- Java
-
String addr = myConstruct.getNode().getAddr();
- C#
-
string addr = myConstruct.Node.Addr;
논리적 ID
AWS CDK는 앱을 AWS CloudFormation 템플릿으로 합성할 때 각 리소스에 대한 논리적 ID를 생성합니다. AWS CloudFormation은 논리적 IDs를 사용하여 템플릿 내의 리소스를 식별하고 배포 전반에서 추적합니다. 논리적 IDs 생성되는 방법을 이해하면 CDK 코드를 리팩터링할 때 의도하지 않은 리소스 교체를 방지하는 데 도움이 됩니다.
논리적 IDs 방법
AWS CDK는 다음 알고리즘을 사용하여 구문 경로에서 논리적 IDs를 생성합니다.
결과 형식은 다음과 같습니다.
<human-readable-portion><8-character-hash>
예를 들어 VPC 프라이빗 서브넷 라우팅 테이블은 논리적 ID를 생성할 수 있습니다VPCPrivateSubnet2RouteTable0A19E10E.
논리적 ID 생성에는 다음 규칙이 적용됩니다.
-
최대 길이는 255자입니다. 사람이 읽을 수 있는 부분은 240자로 제한됩니다.
-
8자 해시는 동일한 문자열에 A/BC 연결된 A/B/C 및와 같은 경로가 서로 다른 논리적 IDs를 생성하도록 합니다.
-
스택의 직접 하위 항목인 리소스(단일 구성 요소 경로)는 이름이 255자 이하인 한 해시 없이 직접 이름을 사용합니다.
논리적 ID 경로 구성 요소 휴리스틱
AWS CDK는 논리적 IDs의 사람이 읽을 수 있는 부분을 생성할 때 경로 구성 요소에 다음 휴리스틱을 적용합니다.
-
Default - 완전히 제거됨
-
경로 구성 요소가 인 경우 DefaultCDK는 사람이 읽을 수 있는 부분과 해시 입력 모두에서 제거합니다. 즉, 새 구문 내에 기존 구문을 래핑하고 내부 구문의 이름을 지정하면 원래 래핑되지 않은 구문과 정확히 동일한 논리적 ID가 Default 생성됩니다. 이는 배포된 리소스 ID를 변경하지 않고 플랫 코드를 상위 수준 구문으로 안전하게 리팩터링하기 위한 주요 메커니즘입니다.
-
Resource - 사람이 읽을 수 있는 부분에서만 숨김
-
경로 구성 요소가 인 경우 CDKResource는 사람이 읽을 수 있는 부분에서 이를 생략하지만 해시 계산에 여전히 포함합니다. L1(CloudFormation) 구문은 규칙에 따라를 구문 IDResource로 사용합니다. 이렇게 하면 고유성을 잃지 않고 논리적 IDs 더 짧게 유지할 수 있습니다.
- 연속 구성 요소 복제 - 중복 제거됨
-
이전 경로 구성 요소 이름이 현재 구성 요소 이름으로 끝나는 경우 CDK는 현재 구성 요소를 건너뜁니다. 이렇게 하면 논리적 IDs.
리팩터링 시 논리적 IDs 보존Default하는 데 사용
플랫 스택을 상위 수준 구문으로 리팩터링할 때를 기본 리소스의 구문 IDDefault로 사용하여 논리적 ID를 유지할 수 있습니다. 이렇게 하면 AWS CloudFormation이 배포 중에 리소스를 대체하지 않습니다.
다음 예제에서는 직접 정의된 리소스가 있는 스택을 보여줍니다.
예
- TypeScript
-
export class MyStack extends cdk.Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
new s3.Bucket(this, 'DataBucket');
new lambda.Function(this, 'ProcessFunction', { /* ... */ });
}
}
- JavaScript
-
class MyStack extends cdk.Stack {
constructor(scope, id) {
super(scope, id);
new s3.Bucket(this, 'DataBucket');
new lambda.Function(this, 'ProcessFunction', { /* ... */ });
}
}
- Python
-
from aws_cdk import (
Stack,
aws_s3 as s3,
aws_lambda as _lambda,
)
from constructs import Construct
class MyStack(Stack):
def __init__(self, scope: Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
s3.Bucket(self, "DataBucket")
_lambda.Function(self, "ProcessFunction", # ...
)
- Java
-
package com.myorg;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.s3.Bucket;
import software.amazon.awscdk.services.lambda.Function;
public class MyStack extends Stack {
public MyStack(final Construct scope, final String id) {
this(scope, id, null);
}
public MyStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
new Bucket(this, "DataBucket");
Function.Builder.create(this, "ProcessFunction")
// ...
.build();
}
}
- C#
-
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.S3;
using Amazon.CDK.AWS.Lambda;
namespace MyApp
{
public class MyStack : Stack
{
public MyStack(Construct scope, string id, StackProps props = null) : base(scope, id, props)
{
new Bucket(this, "DataBucket");
new Function(this, "ProcessFunction", new FunctionProps
{
// ...
});
}
}
}
- Go
-
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
"github.com/aws/aws-cdk-go/awscdk/v2/awss3"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
type MyStackProps struct {
awscdk.StackProps
}
func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack {
stack := awscdk.NewStack(scope, &id, &props.StackProps)
awss3.NewBucket(stack, jsii.String("DataBucket"), &awss3.BucketProps{})
awslambda.NewFunction(stack, jsii.String("ProcessFunction"), &awslambda.FunctionProps{
// ...
})
return stack
}
버킷의 경로는 이며 MyStack/DataBucket/Resource논리적 ID를 생성합니다DataBucket<hash>.
버킷을 상위 수준 구문으로 추출하고 내부 구문의 이름을 지정하여 동일한 논리적 ID를 유지할 수 있습니다Default.
예
- TypeScript
-
class DataPipeline extends Construct {
constructor(scope: Construct, id: string) {
super(scope, id);
new s3.Bucket(this, 'Default'); // 'Default' is hidden from logical ID
new lambda.Function(this, 'ProcessFunction', { /* ... */ });
}
}
export class MyStack extends cdk.Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
new DataPipeline(this, 'DataBucket');
}
}
- JavaScript
-
class DataPipeline extends Construct {
constructor(scope, id) {
super(scope, id);
new s3.Bucket(this, 'Default'); // 'Default' is hidden from logical ID
new lambda.Function(this, 'ProcessFunction', { /* ... */ });
}
}
class MyStack extends cdk.Stack {
constructor(scope, id) {
super(scope, id);
new DataPipeline(this, 'DataBucket');
}
}
- Python
-
from aws_cdk import (
Stack,
aws_s3 as s3,
aws_lambda as _lambda,
)
from constructs import Construct
class DataPipeline(Construct):
def __init__(self, scope: Construct, id: str) -> None:
super().__init__(scope, id)
s3.Bucket(self, "Default") # 'Default' is hidden from logical ID
_lambda.Function(self, "ProcessFunction", # ...
)
class MyStack(Stack):
def __init__(self, scope: Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
DataPipeline(self, "DataBucket")
- Java
-
package com.myorg;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.s3.Bucket;
import software.amazon.awscdk.services.lambda.Function;
public class DataPipeline extends Construct {
public DataPipeline(final Construct scope, final String id) {
super(scope, id);
new Bucket(this, "Default"); // 'Default' is hidden from logical ID
Function.Builder.create(this, "ProcessFunction")
// ...
.build();
}
}
public class MyStack extends Stack {
public MyStack(final Construct scope, final String id) {
this(scope, id, null);
}
public MyStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
new DataPipeline(this, "DataBucket");
}
}
- C#
-
using Amazon.CDK;
using Constructs;
using Amazon.CDK.AWS.S3;
using Amazon.CDK.AWS.Lambda;
namespace MyApp
{
public class DataPipeline : Construct
{
public DataPipeline(Construct scope, string id) : base(scope, id)
{
new Bucket(this, "Default"); // 'Default' is hidden from logical ID
new Function(this, "ProcessFunction", new FunctionProps
{
// ...
});
}
}
public class MyStack : Stack
{
public MyStack(Construct scope, string id, StackProps props = null) : base(scope, id, props)
{
new DataPipeline(this, "DataBucket");
}
}
}
- Go
-
package main
import (
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
"github.com/aws/aws-cdk-go/awscdk/v2/awss3"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
type DataPipeline struct {
constructs.Construct
}
func NewDataPipeline(scope constructs.Construct, id string) constructs.Construct {
this := constructs.NewConstruct(scope, &id)
// 'Default' is hidden from logical ID
awss3.NewBucket(this, jsii.String("Default"), &awss3.BucketProps{})
awslambda.NewFunction(this, jsii.String("ProcessFunction"), &awslambda.FunctionProps{
// ...
})
return this
}
type MyStackProps struct {
awscdk.StackProps
}
func NewMyStack(scope constructs.Construct, id string, props *MyStackProps) awscdk.Stack {
stack := awscdk.NewStack(scope, &id, &props.StackProps)
NewDataPipeline(stack, "DataBucket")
return stack
}
버킷의 경로는 이제 입니다MyStack/DataBucket/Default/Resource. Default는 사람이 읽을 수 있는 부분과 해시 입력 모두에서 제거되므로 논리적 ID는 원본과 DataBucket<hash> 동일하게 유지됩니다.
구성 범위Default당 ID가 있는 하위 항목은 하나만 가질 수 있습니다. 동일한 수준에서 여러 리소스가 필요한 경우 설명이 포함된 IDs 제공합니다. 이 Default 패턴은 하나의 기본 리소스가 있는 단일 책임 구성에서 가장 잘 작동합니다.
제한 사항 및 고려 사항
논리적 IDs
-
Default 구성 ID의 범위당 하나의 하위 항목만 할당할 수 있습니다.
-
배포 후 구문 ID를 변경하면 논리적 ID가 변경되어 AWS CloudFormation에서 리소스를 대체합니다. 배포하기 전에 cdk diff를 사용하여 변경 사항을 확인합니다.
-
논리적 IDs가 이미 변경된 경우 cdk refactor 명령을 사용하여 이전 논리적 IDs를 새 ID에 매핑할 수 있습니다. 자세한 내용은 CDK 코드 리팩터링 시 배포된 리소스 보존을 참조하세요.
-
논리적 IDs 합성된 템플릿에 표시되는 방법에 대한 자세한 내용은AWS CloudFormation 템플릿에서 생성된 논리적 IDs 참조하세요.
논리적 ID 안정성
리소스가 생성된 후에는 리소스의 논리적 ID를 변경하지 마세요. AWS CloudFormation은 논리적 ID로 리소스를 식별합니다. 따라서 리소스의 논리적 ID를 변경하면 AWS CloudFormation은 새 논리적 ID로 새 리소스를 생성한 다음 기존 리소스를 삭제합니다. 리소스 유형에 따라 서비스 중단, 데이터 손실 또는 둘 다 발생할 수 있습니다.