TypeScript DynamoDB
이 생성기는 Amazon DynamoDB를 기반으로 하는 새로운 TypeScript DynamoDB 프로젝트를 생성하며, 타입 안전 엔티티 모델링을 위해 ElectroDB를 사용합니다. AWS CDK 또는 Terraform을 사용하여 DynamoDB 테이블을 프로비저닝하고 관리하는 데 필요한 애플리케이션 코드와 인프라를 생성하며, 단일 테이블 설계 지원과 DynamoDB Local을 통한 로컬 개발 환경을 내장하고 있습니다.
사용법
섹션 제목: “사용법”TypeScript DynamoDB 프로젝트 생성하기
섹션 제목: “TypeScript DynamoDB 프로젝트 생성하기”이 제너레이터 실행@aws/nx-plugin:ts#dynamodb
pnpm nx g @aws/nx-plugin:ts#dynamodb yarn nx g @aws/nx-plugin:ts#dynamodb npx nx g @aws/nx-plugin:ts#dynamodb bunx nx g @aws/nx-plugin:ts#dynamodb- 설치 Nx Console VSCode Plugin 아직 설치하지 않았다면
- VSCode에서 Nx 콘솔 열기
- 클릭
Generate (UI)"Common Nx Commands" 섹션에서 - 검색
@aws/nx-plugin - ts#dynamodb - 필수 매개변수 입력
- 클릭
Generate
명령 구성하기8
필수
name필수string생성할 DynamoDB 프로젝트의 이름
directorystring기본값:packages프로젝트를 저장할 디렉토리입니다.
frameworkenum기본값:electrodbDynamoDB 엔티티에 사용할 프레임워크입니다.
electrodbinfraenum기본값:dynamodbDynamoDB 테이블을 위해 프로비저닝할 인프라입니다.
dynamodbnoneiacenum기본값:inherit선호하는 IaC 공급자입니다. 기본적으로 초기 선택에서 상속됩니다.
inheritcdkterraformsubDirectorystring프로젝트가 배치되는 하위 디렉토리입니다. 기본값은 프로젝트 이름입니다.
tableNamestringDynamoDB 테이블 이름입니다. 지정하지 않으면 자동으로 생성됩니다.
preferInstallDependenciesboolean기본값:true생성기 실행 후 의존성 설치를 선호할지 여부입니다. 여러 생성기를 일괄 실행할 때 설치를 연기하려면 false로 설정하세요 (후속 생성기가 Nx 프로젝트 그래프를 계산할 수 있도록 필요한 경우 설치는 여전히 실행됩니다). 마지막에 한 번만 설치하세요.
생성기 출력
섹션 제목: “생성기 출력”생성기는 <directory>/<name> 디렉토리에 다음과 같은 프로젝트 구조를 생성합니다:
디렉터리src
- index.ts Project entry point and exports
- client.ts DynamoDB client singleton and table name resolution
디렉터리entities
- example.ts Example ElectroDB entity definition
- index.ts Entity exports
- config.json Table configuration including GSI definitions and local development settings
- package.json Project manifest defining the project’s package name and dependencies
- project.json Project configuration and build targets
로컬 개발 스크립트는 모든 DynamoDB 프로젝트(TypeScript 및 Python 모두)에서 공유되며 다음 위치에 한 번 생성됩니다:
디렉터리packages/common/scripts/src/dynamodb
- create-local-table.ts Creates the DynamoDB table in the local DynamoDB Local instance
- pull-image.ts Pulls the DynamoDB Local image
- start-container.ts Starts the DynamoDB Local container
인프라
섹션 제목: “인프라”이 생성기는 선택한 iac를 기반으로 코드형 인프라를 제공하므로, 관련 CDK constructs 또는 Terraform 모듈을 포함하는 packages/common에 프로젝트를 생성합니다.
공통 코드형 인프라 프로젝트는 다음과 같이 구성됩니다:
디렉터리packages/common/constructs
디렉터리src
디렉터리app/ 프로젝트/생성기에 특정한 인프라를 위한 Constructs
- …
디렉터리core/
app의 constructs에서 재사용되는 일반 constructs- …
- index.ts
app에서 constructs를 내보내는 진입점
- project.json 프로젝트 빌드 타겟 및 구성
디렉터리packages/common/terraform
디렉터리src
디렉터리app/ 프로젝트/생성기에 특정한 인프라를 위한 Terraform 모듈
- …
디렉터리core/
app의 모듈에서 재사용되는 일반 모듈- …
- project.json 프로젝트 빌드 타겟 및 구성
디렉터리packages/common/constructs/src
디렉터리app
디렉터리dynamodb
- <name>.ts 테이블에 특정한 인프라
디렉터리core
- dynamodb.ts 범용 DynamoDB 테이블 구성
디렉터리packages/common/terraform/src
디렉터리app
디렉터리dynamodb
디렉터리<name>
- <name>.tf 테이블에 특정한 모듈
디렉터리core
디렉터리dynamodb
- dynamodb.tf 범용 DynamoDB 모듈
아키텍처
섹션 제목: “아키텍처”배포된 프로젝트는 테이블 자체를 프로비저닝하며, 연결된 모든 프로젝트가 이를 읽고 씁니다:
로컬 개발
섹션 제목: “로컬 개발”로컬 DynamoDB 시작하기
섹션 제목: “로컬 DynamoDB 시작하기”생성기는 DynamoDB Local 인스턴스를 시작하고 테이블을 생성하는 dev 타겟을 구성합니다. 프로젝트의 dev 타겟을 사용하세요:
pnpm nx dev <project-name>yarn nx dev <project-name>npx nx dev <project-name>bunx nx dev <project-name>이것은 자동으로:
- DynamoDB Local 이미지를 가져옵니다 (
pull-image타겟) - 컨테이너를 시작합니다
config.json에 정의된 인덱스로 로컬 테이블을 생성합니다
데이터 모델링
섹션 제목: “데이터 모델링”생성된 프로젝트는 단일 DynamoDB 테이블에서 타입 안전 엔티티 모델링을 위해 ElectroDB를 사용하며, DynamoDB의 단일 테이블 설계를 따릅니다. 생성된 예제 엔티티를 시작점으로 사용하여 src/entities/ 아래에 엔티티 파일을 추가하거나 업데이트하세요.
엔티티 정의 예제:
import { Entity } from 'electrodb';import { getDynamoDBClient, resolveTableName } from '../client.js';
export const createExampleEntity = async () => new Entity( { model: { entity: 'example', version: '1', service: 'MyTable', }, attributes: { id: { type: 'string', required: true, }, createdAt: { type: 'string', required: true, default: () => new Date().toISOString(), readOnly: true, }, updatedAt: { type: 'string', required: true, default: () => new Date().toISOString(), watch: '*', set: () => new Date().toISOString(), }, }, indexes: { primary: { pk: { field: 'pk', composite: ['id'], }, sk: { field: 'sk', composite: [], }, }, }, }, { client: getDynamoDBClient(), table: await resolveTableName() }, );자세한 내용은 ElectroDB 엔티티 문서를 참조하세요.
DynamoDB 클라이언트 사용하기
섹션 제목: “DynamoDB 클라이언트 사용하기”생성된 src/client.ts는 두 가지 주요 유틸리티를 내보냅니다:
getDynamoDBClient()— 캐시된 싱글톤DynamoDBClient를 반환합니다.LOCAL_DEV=true일 때는 로컬 DynamoDB Local 인스턴스에 연결하고, 그렇지 않으면 기본 자격 증명 체인을 사용하여 AWS 클라이언트를 생성합니다.resolveTableName()— DynamoDB 테이블 이름을 반환합니다.LOCAL_DEV=true일 때는 로컬 테이블 이름 상수를 반환하고, 그렇지 않으면RUNTIME_CONFIG_APP_ID환경 변수를 사용하여 AWS AppConfig에서 이름을 가져와 후속 호출을 위해 캐시합니다.
로컬 DynamoDB 중지하기
섹션 제목: “로컬 DynamoDB 중지하기”dev를 중지하면 (예: Ctrl+C로) DynamoDB Local 컨테이너가 자동으로 제거되지만, 명명된 볼륨은 보존되므로 재시작 시에도 데이터가 유지됩니다.
글로벌 보조 인덱스 추가/제거
섹션 제목: “글로벌 보조 인덱스 추가/제거”GSI는 프로젝트 루트의 config.json에서 tableConfig.globalSecondaryIndexes 키 아래에 정의됩니다. GSI 키에 대한 단일 테이블 설계 명명 규칙을 따라 각 GSI에 대한 항목을 추가하세요:
{ ... "tableConfig": { "globalSecondaryIndexes": [ { "indexName": "gsi1pk-gsi1sk-index", "partitionKey": "gsi1pk", "sortKey": "gsi1sk" }, { "indexName": "gsi2pk-gsi2sk-index", "partitionKey": "gsi2pk", "sortKey": "gsi2sk" } ] }}sortKey 필드는 해시 키만 사용하는 GSI의 경우 선택 사항입니다.
이 구성 파일은 모든 소비자가 읽는 단일 진실 공급원입니다:
- 로컬 개발 —
dev는config.json을 읽고 GSI 목록과 일치하도록 로컬 테이블을 생성하거나 업데이트합니다 - CDK — 구성체는 합성 시점에
config.json을 읽으므로 GSI 변경 사항이 다음cdk deploy에 반영됩니다 - Terraform — 모듈은 plan/apply 시점에
config.json을 읽습니다
배포당 하나의 GSI
섹션 제목: “배포당 하나의 GSI”테이블에 연결하기
섹션 제목: “테이블에 연결하기”모든 TypeScript 프로젝트에서 DynamoDB 패키지에서 엔티티 팩토리를 가져와 직접 사용할 수 있습니다:
import { createExampleEntity } from '@my-scope/my-table';
const entity = await createExampleEntity();const result = await entity.query.primary({ id: '123' }).go();내부적으로 createExampleEntity()는 resolveTableName()을 호출하여 런타임에 AWS AppConfig에서 테이블 이름을 가져옵니다.
테이블 배포하기
섹션 제목: “테이블 배포하기”DynamoDB 생성기는 선택한 iac에 따라 CDK 또는 Terraform 인프라를 생성합니다.
CDK 구성은 common/constructs에 생성됩니다. 사용 예시:
import { MyTable } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props);
const table = new MyTable(this, 'Table'); }}다음과 같은 DynamoDB 테이블을 프로비저닝합니다:
pk(파티션 키)와sk(정렬 키), 둘 다String타입config.json에 정의된 Global Secondary Indexes- 온디맨드 (
PAY_PER_REQUEST) 과금 - 자동 키 로테이션이 활성화된 고객 관리형 KMS 암호화
- 특정 시점 복구 활성화
- 삭제 보호 활성화
- AWS AppConfig의
dynamodb네임스페이스 아래 Runtime Config에 등록된 테이블 이름
Terraform 모듈은 common/terraform에 생성됩니다. 사용 예시:
module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table"}다음과 같은 DynamoDB 테이블을 프로비저닝합니다:
pk(파티션 키)와sk(정렬 키), 둘 다String타입config.json에 정의된 Global Secondary Indexes- 온디맨드 (
PAY_PER_REQUEST) 과금 - 자동 키 로테이션이 활성화된 고객 관리형 KMS 암호화
- 특정 시점 복구 활성화
- 삭제 보호 활성화 및
prevent_destroy라이프사이클 가드 - AWS AppConfig의
dynamodb네임스페이스 아래 Runtime Config에 등록된 테이블 이름
core/runtime-config/appconfig 모듈은 기본적으로 dynamodb 네임스페이스를 노출하므로, 추가 구성 없이 테이블 이름이 배포됩니다. 해당 모듈에 namespaces를 명시적으로 전달하는 경우, 목록에 dynamodb를 유지하세요. 그렇지 않으면 구성 프로필이 생성되지 않아 생성된 테이블 클라이언트가 테이블 이름을 확인할 수 없습니다.
삭제 보호
섹션 제목: “삭제 보호”테이블은 두 개의 독립적인 가드로 보호되므로, 둘 중 하나만 끄는 것으로는 데이터를 삭제할 수 없습니다:
deletionProtection, DynamoDB에 의해 적용됩니다.RemovalPolicy.RETAIN, CloudFormation에 의해 적용되며, 스택에서 제거될 때 테이블을 그대로 유지합니다.
deletion_protection_enabled, DynamoDB에 의해 적용됩니다.common/terraform/src/core/dynamodb/dynamodb.tf의 테이블에 있는lifecycle { prevent_destroy = true }, Terraform에 의해 적용되며, 테이블을 삭제하려는 모든 플랜을 실패시킵니다.
테이블 삭제하기
섹션 제목: “테이블 삭제하기”단기 개발 또는 프리뷰 스택과 같이 테이블 삭제가 예상되는 환경에서는 보호를 비활성화하세요.
import { RemovalPolicy } from 'aws-cdk-lib';import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { deletionProtection: false, removalPolicy: RemovalPolicy.DESTROY,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" deletion_protection_enabled = false}prevent_destroy는 리터럴이어야 합니다 — Terraform은 변수를 참조하는 것을 허용하지 않습니다 — 따라서 main.tf에서 끌 수 없습니다. 또한 common/terraform/src/core/dynamodb/dynamodb.tf의 테이블에서 lifecycle 블록을 제거하세요:
resource "aws_dynamodb_table" "table" { # ...
lifecycle { prevent_destroy = true }}과금 모드
섹션 제목: “과금 모드”테이블은 기본적으로 온디맨드 (PAY_PER_REQUEST) 과금을 사용합니다. 예측 가능한 고처리량 워크로드의 경우 프로비저닝된 용량으로 전환하세요.
import { BillingMode } from 'aws-cdk-lib/aws-dynamodb';import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { billingMode: BillingMode.PROVISIONED, readCapacity: 5, writeCapacity: 5,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" billing_mode = "PROVISIONED"}특정 시점 복구
섹션 제목: “특정 시점 복구”특정 시점 복구는 기본적으로 활성화되어 있으며, 지난 35일 동안의 임의 시점으로 테이블을 복원할 수 있습니다.
특정 시점 복구 비활성화
섹션 제목: “특정 시점 복구 비활성화”import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: false },});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" point_in_time_recovery_enabled = false}암호화
섹션 제목: “암호화”테이블은 기본적으로 고객 관리형 KMS 키로 암호화되며, 자동으로 생성됩니다. 암호화를 다르게 관리하는 경우 AWS 관리형 키, AWS 소유 키로 전환하거나 자체 KMS 키를 가져올 수 있습니다.
AWS 관리형 키 사용
섹션 제목: “AWS 관리형 키 사용”AWS가 대신 관리하는 공유 aws/dynamodb KMS 키를 사용합니다. 계정의 KMS 콘솔에서 볼 수 있고 요청당 과금되지만, 생성, 로테이션 또는 삭제할 키가 없습니다.
import { TableEncryption } from 'aws-cdk-lib/aws-dynamodb';import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { encryption: TableEncryption.AWS_MANAGED,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" encryption = "AWS_MANAGED"}AWS 소유 키 사용
섹션 제목: “AWS 소유 키 사용”AWS가 완전히 소유하고 관리하는 키를 사용합니다 — 무료이며, 계정에 키가 전혀 표시되지 않습니다. 규정 준수 이유로 고객 또는 계정에 표시되는 키가 필요하지 않은 경우 가장 간단한 옵션입니다.
import { TableEncryption } from 'aws-cdk-lib/aws-dynamodb';import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { encryption: TableEncryption.DEFAULT,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" encryption = "DEFAULT"}CUSTOMER_MANAGED에서 전환
섹션 제목: “CUSTOMER_MANAGED에서 전환”이미 배포된 테이블에서 단일 terraform apply로 encryption을 CUSTOMER_MANAGED에서 (AWS_MANAGED 또는 DEFAULT로) 변경하면 실패합니다: Terraform이 테이블을 업데이트하기 전에 고객 관리형 키를 삭제하고, DynamoDB는 키가 이미 삭제 대기 중이기 때문에 업데이트를 거부합니다.
먼저 AWS CLI를 통해 테이블의 암호화를 직접 업데이트한 다음 Terraform이 따라잡고 고아가 된 키를 정리하도록 하여 이 문제를 해결하세요:
# For AWS_MANAGED:aws dynamodb update-table --table-name <table-name> \ --sse-specification Enabled=true,SSEType=KMS,KMSMasterKeyId=alias/aws/dynamodb
# For DEFAULT:aws dynamodb update-table --table-name <table-name> --sse-specification Enabled=false
# Then wait for this to report ENABLED (or for SSEDescription to disappear, for DEFAULT):aws dynamodb describe-table --table-name <table-name> --query Table.SSEDescription.Status그런 다음 Terraform 구성에서 encryption을 업데이트하고 평소처럼 terraform apply를 실행하세요 — 이제 Terraform은 이미 사용되지 않는 키만 삭제하면 되며, 더 이상 의존하는 것이 없습니다.
자체 KMS 키 사용
섹션 제목: “자체 KMS 키 사용”자동으로 생성되는 대신 기존 고객 관리형 키를 제공합니다. 키는 자체 키 정책에서 DynamoDB 서비스에 필요한 권한을 이미 부여해야 합니다.
import { Key } from 'aws-cdk-lib/aws-kms';import { MyTable } from '@my-scope/common-constructs';
const key = Key.fromKeyArn(this, 'Key', 'arn:aws:kms:us-east-1:111111111111:key/my-key-id');
const table = new MyTable(this, 'Table', { encryptionKey: key,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" kms_key_arn = "arn:aws:kms:us-east-1:111111111111:key/my-key-id"}암호화 키 로테이션
섹션 제목: “암호화 키 로테이션”테이블이 자체 고객 관리형 KMS 키를 생성하는 경우(기본값이며, 자체 키를 제공하지 않은 경우에만 해당), 해당 키는 기본적으로 자동 키 로테이션이 활성화됩니다. 보안 정책이 외부에서 로테이션을 관리하는 경우 비활성화하세요.
암호화 키 로테이션 비활성화
섹션 제목: “암호화 키 로테이션 비활성화”import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { enableKeyRotation: false,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" enable_key_rotation = false}connection 생성기를 사용하여 이 프로젝트를 워크스페이스의 다른 프로젝트와 통합하세요. 다음 연결은 이 프로젝트와 관련이 있습니다: