콘텐츠로 이동

CDK Infrastructure

AWS CDK는 코드로 클라우드 인프라를 정의하고 AWS CloudFormation을 통해 프로비저닝하는 프레임워크입니다.

TypeScript 인프라 생성기는 TypeScript로 작성된 AWS CDK 인프라 애플리케이션을 생성합니다. 생성된 애플리케이션에는 Checkov 보안 검사를 통한 보안 모범 사례가 포함되어 있습니다.

두 가지 방법으로 새 인프라 프로젝트를 생성할 수 있습니다:

Terminal window
pnpm nx g @aws/nx-plugin:ts#infra
어떤 파일이 변경될지 확인하기 위해 드라이 런을 수행할 수도 있습니다
Terminal window
pnpm nx g @aws/nx-plugin:ts#infra --dry-run
매개변수타입기본값설명
name 필수string-애플리케이션의 이름입니다.
directory stringpackages새 애플리케이션의 디렉토리입니다.
subDirectory string-프로젝트가 배치되는 하위 디렉토리입니다. 기본값은 프로젝트 이름입니다.
stageConfig boolean다중 환경 CDK 배포를 위한 중앙 집중식 스테이지 구성(자격 증명, 계정, 리전)을 활성화합니다.
preferInstallDependencies booleantrue생성기 실행 후 의존성 설치를 선호할지 여부입니다. 여러 생성기를 일괄 실행할 때 설치를 연기하려면 false로 설정하세요 (후속 생성기가 Nx 프로젝트 그래프를 계산할 수 있도록 필요한 경우 설치는 여전히 실행됩니다); 마지막에 한 번만 설치합니다.

생성기는 <directory>/<name> 디렉토리에 다음과 같은 프로젝트 구조를 생성합니다:

  • 디렉터리src
    • main.ts Application entry point instantiating CDK stages to deploy
    • 디렉터리stages CDK Stage definitions
      • application-stage.ts Defines a collection of stacks to deploy in a stage
    • 디렉터리stacks CDK Stack definitions
      • application-stack.ts Main application stack
  • cdk.json CDK configuration
  • package.json Project manifest defining the project’s package name and dependencies
  • project.json Project configuration and build targets
  • checkov.yml Checkov configuration file

stageConfig 옵션을 설정하면, 생성기는 중앙 집중식 자격 증명 관리를 위한 두 개의 공유 패키지도 생성합니다(아직 존재하지 않는 경우):

  • 디렉터리packages/common
    • 디렉터리infra-config Stage configuration types and credential mappings
      • 디렉터리src
        • stages.types.ts Type definitions for stage credentials and config
        • stages.config.ts Your stage-to-credential mappings (edit this)
        • index.ts Re-exports for importing from other packages
    • 디렉터리scripts Centralized deploy/destroy scripts
      • 디렉터리src
        • infra-deploy.ts Deploy bin script
        • infra-destroy.ts Destroy bin script
        • 디렉터리stage-credentials/ Shared logic (credential lookup, CDK command building)

src/stacks/application-stack.ts 내부에서 CDK 인프라 작성을 시작할 수 있습니다. 예를 들어:

src/stacks/application-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Bucket } from 'aws-cdk-lib/aws-s3'
import { Construct } from 'constructs';
export class ApplicationStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Declare your infrastructure here
new Bucket(this, 'MyBucket');
}
}

CDK는 Stages를 사용하여 특정 환경에 함께 배포되어야 하는 스택을 그룹화합니다. 생성된 src/main.ts는 자체 개발 및 테스트를 위한 샌드박스 스테이지를 생성합니다:

src/main.ts
new ApplicationStage(app, 'my-app-sandbox', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
},
});
// Define other instances of stages, such as beta and prod, below

env 속성은 CDK에게 어떤 AWS 계정과 리전에 배포할지 알려줍니다. CDK_DEFAULT_ACCOUNTCDK_DEFAULT_REGION은 활성 AWS 자격 증명에서 CDK CLI에 의해 자동으로 해석됩니다. 자세한 내용은 CDK 환경 문서를 참조하세요.

샌드박스 스테이지는 deploy-sandboxdestroy-sandbox 타겟이 작동하는 스테이지입니다.

stageConfig로 생성한 경우, main.ts는 중앙 집중식 구성 파일에서 계정과 리전을 읽으며, 구성이 설정되지 않은 경우 환경 변수로 폴백합니다:

src/main.ts (with stageConfig)
import { resolveStage } from '@my-scope/common-infra-config';
// Looks up the stage under this project (packages/infra), falling back to
// shared stages. Returns undefined when no config exists for the stage.
const sandboxConfig = resolveStage('packages/infra', 'my-app-sandbox');
new ApplicationStage(app, 'my-app-sandbox', {
env: {
account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT,
region: sandboxConfig?.region ?? process.env.CDK_DEFAULT_REGION,
},
});

다른 환경에 배포하기 위해 더 많은 스테이지를 추가할 수 있습니다. 예를 들어, 별도의 AWS 계정을 대상으로 하는 betaprod 스테이지:

src/main.ts
new ApplicationStage(app, 'project-beta', {
env: {
account: '123456789012',
region: 'us-west-2',
},
});
new ApplicationStage(app, 'project-prod', {
env: {
account: '098765432109',
region: 'us-west-2',
},
});

스테이지는 하나 이상의 스택을 그룹화합니다. 스테이지 내부에 필요한 만큼 많은 스택을 추가할 수 있습니다:

src/stages/application-stage.ts
import { Stage, StageProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { BackendStack } from '../stacks/backend-stack.js';
import { FrontendStack } from '../stacks/frontend-stack.js';
export class ApplicationStage extends Stage {
constructor(scope: Construct, id: string, props?: StageProps) {
super(scope, id, props);
new BackendStack(this, 'Backend', {
crossRegionReferences: true,
})
new FrontendStack(this, 'Frontend', {
crossRegionReferences: true,
});
}
}

여러 스테이지가 서로 다른 AWS 계정을 대상으로 하는 경우, 특히 스테이지 수가 증가함에 따라 자격 증명을 수동으로 관리하는 것은 오류가 발생하기 쉽습니다.

stageConfig 옵션은 두 개의 공유 패키지를 생성하여 이 문제를 해결합니다:

  • packages/common/infra-config — 각 스테이지를 AWS 자격 증명, 계정 및 리전에 매핑하는 단일 구성 파일입니다. 이는 워크스페이스의 모든 패키지에서 가져올 수 있으므로, CDK main.ts가 동일한 신뢰할 수 있는 소스에서 계정과 리전을 읽을 수 있습니다.
  • packages/common/scripts — 자동 자격 증명 해석으로 CDK를 래핑하는 infra-deployinfra-destroy 명령입니다. deploy를 실행하면 스크립트가 구성을 읽고, CDK 자식 프로세스에 대한 올바른 AWS 환경 변수를 설정하고, cdk deploy를 실행합니다. 셸 환경은 절대 수정되지 않습니다.

packages/common/infra-config/src/stages.config.ts를 편집하여 스테이지를 AWS 자격 증명에 매핑합니다:

packages/common/infra-config/src/stages.config.ts
import type { StagesConfig } from './stages.types.js';
const config: StagesConfig = {
projects: {
// The key is the project path relative to the workspace root.
// This matches the path in project.json and in deploy commands.
'packages/infra': {
stages: {
// Stage names must match the CDK stage identifiers in main.ts
// (the first argument to `new ApplicationStage(app, 'my-app-dev', ...)`).
'my-app-dev': {
credentials: { type: 'profile', profile: 'dev-account' },
region: 'us-east-1',
},
'my-app-prod': {
credentials: {
type: 'assumeRole',
assumeRole: 'arn:aws:iam::123456789012:role/DeployRole',
},
region: 'us-west-2',
account: '123456789012',
},
},
},
},
shared: {
// Shared stages are available to all infra projects.
// Project-specific entries take priority over shared ones.
stages: {
sandbox: {
credentials: { type: 'profile', profile: 'personal-sandbox' },
region: 'us-east-1',
},
},
},
};
export default config;

예를 들어 배포할 때:

Terminal window
pnpm nx deploy infra my-app-dev/*

배포 스크립트는:

  1. 명령 인수에서 스테이지 이름 my-app-dev를 추출합니다
  2. 구성에서 자격 증명을 조회합니다: 먼저 projects['packages/infra'] 아래에서, 그 다음 shared 아래에서
  3. 찾으면 CDK 자식 프로세스에 대해서만 AWS_PROFILE을 설정합니다(또는 IAM 역할을 가정합니다)
  4. 찾지 못하면 환경에 있는 AWS 자격 증명으로 폴백합니다

이는 구성이 없는 기존 워크플로우가 계속 작동함을 의미합니다 — 스크립트는 일치하는 항목을 찾을 때만 자격 증명을 적용합니다.

두 가지 자격 증명 전략이 지원됩니다:

  • profile~/.aws/config의 명명된 AWS CLI 프로필을 사용합니다. 스크립트는 CDK 프로세스에 대해 AWS_PROFILE을 설정합니다.
  • assumeRole — 지정된 역할 ARN으로 STS AssumeRole을 호출하고 임시 자격 증명을 CDK에 전달합니다. 선택적으로 AssumeRole 호출을 위한 소스 자격 증명으로 profile을, 교차 계정 신뢰 정책을 위한 externalId를, 그리고 초 단위의 sessionDuration을 지정할 수 있습니다.

각 스테이지 구성에는 필수 region과 선택적 account가 포함됩니다:

  • region (필수) — 배포할 AWS 리전입니다(예: us-east-1, eu-west-2).
  • account (선택) — AWS 계정 ID입니다. 생략하면 CDK가 배포 시점에 활성 자격 증명에서 이를 추론합니다. CDK가 계정과 리전을 해석하는 방법은 CDK 환경 문서를 참조하세요.

생성된 main.ts는 구성에서 이러한 값을 읽어 CDK 합성 및 배포가 동일한 환경 설정을 사용하도록 합니다:

src/main.ts
const sandboxConfig = resolveStage('packages/infra', 'my-app-sandbox');
new ApplicationStage(app, 'my-app-sandbox', {
env: {
account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT,
region: sandboxConfig?.region ?? process.env.CDK_DEFAULT_REGION,
},
});

공유 스테이지(shared.stages 아래)는 워크스페이스의 모든 인프라 프로젝트에 적용됩니다. 이는 여러 프로젝트가 동일한 샌드박스 계정에 배포될 때 유용합니다 — 각 프로젝트마다 반복하는 대신 자격 증명을 한 번만 정의합니다.

프로젝트별 스테이지(projects['packages/infra'].stages 아래)는 해당 프로젝트에만 적용됩니다. 동일한 스테이지 이름에 대해 둘 다 존재하는 경우, 프로젝트별 항목이 우선합니다.

tRPC API 또는 FastAPI 생성기를 사용하여 API를 생성한 경우, packages/common/constructs에 이미 배포할 수 있는 일부 구성 요소가 있음을 알 수 있습니다.

예를 들어, my-api라는 tRPC API를 생성한 경우, 구성 요소를 가져와서 인스턴스화하여 배포에 필요한 모든 인프라를 추가할 수 있습니다:

src/stacks/application-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { MyApi } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Add infrastructure for your API
new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
});
}
}

React Website 생성기를 사용한 경우, packages/common/constructs에 이미 배포할 수 있는 구성 요소가 있음을 알 수 있습니다. 예를 들어:

src/stacks/application-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { MyWebsite } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Add infrastructure for your website
new MyWebsite(this, 'MyWebsite');
}
}

build 타겟의 일부로, 기본 컴파일, 린트 및 테스트 타겟을 실행하는 것 외에도, 인프라 프로젝트가 CloudFormation으로 _합성_됩니다. 이는 synth 타겟을 실행하여 독립적으로 실행할 수도 있습니다:

Terminal window
pnpm nx synth <my-infra>

합성된 클라우드 어셈블리는 루트 dist 폴더의 dist/packages/<my-infra-project>/cdk.out 아래에서 찾을 수 있습니다.

프로젝트에 checkov 타겟이 추가되어 Checkov를 사용하여 인프라에 대한 보안 검사를 실행합니다.

Terminal window
pnpm nx checkov <my-infra>

보안 테스트 결과는 루트 dist 폴더의 dist/packages/<my-infra-project>/checkov 아래에서 찾을 수 있습니다.

리소스에 대해 특정 규칙을 억제하려는 경우가 있을 수 있습니다. 두 가지 방법으로 이를 수행할 수 있습니다:

주어진 구성 요소에 대한 규칙 억제

섹션 제목: “주어진 구성 요소에 대한 규칙 억제”
import { suppressRules } from '@my-scope/common-constructs';
// suppresses the CKV_AWS_XXX for the given construct.
suppressRules(construct, ['CKV_AWS_XXX'], 'Reason');

하위 구성 요소에 대한 규칙 억제

섹션 제목: “하위 구성 요소에 대한 규칙 억제”
import { suppressRules } from '@my-scope/common-constructs';
// Supresses the CKV_AWS_XXX for the construct or any of its descendants if it is an instance of Bucket
suppressRules(construct, ['CKV_AWS_XXX'], 'Reason', (construct) => construct instanceof Bucket);

AWS 계정에 CDK 애플리케이션을 처음 배포하는 경우, 부트스트랩이 필요합니다. 부트스트랩은 CDK가 배포를 관리하는 데 필요한 리소스(자산용 S3 버킷, IAM 역할 등)를 생성합니다.

먼저, AWS 계정에 대한 자격 증명을 구성했는지 확인하세요.

다음으로, 배포할 각 계정 및 리전에 대해 부트스트랩 명령을 실행합니다:

Terminal window
npx cdk bootstrap aws://<account-id>/<region>

자세한 내용은 CDK 부트스트랩 문서를 참조하세요.

프로젝트에는 각각 다른 상황에 적합한 세 가지 배포 타겟이 있습니다:

타겟사용 용도
deploy-sandbox개발 중 자체 샌드박스 스테이지 배포. 스테이지 인수가 필요하지 않습니다.
deploy원하는 스테이지 또는 스택을 지정하여 모든 스테이지 배포.
deploy-ci사전 합성된 클라우드 어셈블리를 사용하여 CI/CD 파이프라인에서 배포.

먼저, AWS 자격 증명이 구성되어 있는지 확인하세요. stageConfig로 생성하고 packages/common/infra-config/src/stages.config.ts에서 스테이지 자격 증명을 구성한 경우, 배포 명령이 대상 스테이지에 대한 올바른 자격 증명을 자동으로 해석하고 적용합니다. 그렇지 않으면 환경에 AWS 자격 증명이 설정되어 있는지 확인하세요(예: AWS_PROFILE 또는 환경 변수를 통해). 사용 가능한 옵션은 AWS 자격 증명 문서를 참조하세요.

deploy-sandbox 타겟은 main.ts가 선언하는 샌드박스 스테이지를 배포하므로, 스테이지 이름을 기억할 필요가 없습니다:

Terminal window
pnpm nx deploy-sandbox <my-infra>

이는 개발하는 동안 AWS에서 애플리케이션의 자체 복사본을 실행하는 가장 빠른 방법입니다.

deploy 타겟은 지정한 스테이지 또는 스택을 배포합니다. 샌드박스 이외의 스테이지나 단일 스택을 배포하는 데 사용하세요:

Terminal window
pnpm nx deploy <my-infra> <my-infra>-sandbox/*

main.ts에 정의된 모든 스테이지를 지정할 수 있습니다. 개별 스택을 배포하려면 전체 스택 이름을 제공하세요:

Terminal window
pnpm nx deploy <my-infra> <my-infra>-sandbox/Application

CI/CD 파이프라인의 일부로 AWS에 배포하는 경우 deploy-ci 타겟을 사용하세요.

Terminal window
pnpm nx deploy-ci <my-infra> my-stage/*

이 타겟은 즉석에서 합성하는 대신 사전 합성된 클라우드 어셈블리를 배포한다는 점에서 일반 deploy 타겟과 약간 다릅니다. 이는 패키지 버전 변경으로 인한 잠재적인 비결정성을 방지하여, 모든 파이프라인 스테이지가 동일한 클라우드 어셈블리를 사용하여 배포하도록 보장합니다.

프로젝트에는 배포 타겟을 반영하는 세 가지 해체 타겟이 있습니다:

타겟사용 용도
destroy-sandbox자체 샌드박스 스테이지 해체. 스테이지 인수가 필요하지 않습니다.
destroy원하는 스테이지 또는 스택을 지정하여 모든 스테이지 해체.
destroy-ci사전 합성된 클라우드 어셈블리를 사용하여 CI/CD 파이프라인에서 해체.

destroy-sandbox 타겟은 main.ts가 선언하는 샌드박스 스테이지를 해체하므로, 스테이지 이름을 기억할 필요가 없습니다:

Terminal window
pnpm nx destroy-sandbox <my-infra>

해체는 되돌릴 수 없으므로, CDK는 삭제하려는 스택을 확인하도록 요청합니다. --force를 전달하여 확인을 건너뛸 수 있으며, 이는 터미널이 연결되지 않은 경우(예: 스크립트에서) 원하는 동작입니다:

Terminal window
pnpm nx destroy-sandbox <my-infra> --force

destroy 타겟은 지정한 스테이지 또는 스택을 해체합니다:

Terminal window
pnpm nx destroy <my-infra> <my-infra>-sandbox/*

개별 스택을 해체하려면 전체 스택 이름을 제공하세요:

Terminal window
pnpm nx destroy <my-infra> <my-infra>-sandbox/Application

CDK에 대한 자세한 내용은 CDK 개발자 가이드API 참조를 참조하세요.