CDK 프로젝트에서 인터페이스 AwsSdkCall을 사용해 AWS SDK를 호출하는 방법은 무엇입니까?
인터페이스 AwsSdkCall을 사용해 AWS Cloud Development Kit(AWS CDK) 프로젝트에서 AWS SDK를 호출하려고 합니다.
간략한 설명
다음 스택 배포 상황에 해당하는 경우 AWS Software Development Kit(AWS SDK) 호출을 사용할 수 있습니다.
- 스택을 만들고 업데이트할 때 동적으로 구성을 검색합니다.
- AWS CloudFormation이 반환 값에서 지원하지 않는 리소스의 속성을 검색합니다.
- AWS CloudFormation이 지원하지 않는 작은 패치 또는 구성 변경 사항을 적용합니다.
Create, Delete 또는 Update와 같은 다양한 CloudFormation 스택 작업 이벤트에서 AWS SDK 호출을 트리거할 수 있습니다. 배포 파이프라인에 대한 액세스 권한 및 도구를 설정하지 않아도 AWS SDK를 호출할 수 있습니다. AWS SDK 런타임은 AWS CDK가 설정합니다. 사용자 지정 리소스 뒤에서 AWS Lambda 함수에 대한 액세스 권한을 사용자 지정 및 제한할 수 있습니다.
해결 방법
참고: 다음 예시에서는 TypeScript를 사용합니다. 각자 사용 중인 프로그래밍 언어에 해당하는 구문을 사용해야 합니다.
AwsSdkCall을 사용해 AWS SDK를 호출하려면 다음 파라미터를 사용하십시오.
- Service의 경우, 호출하려는 AWS 서비스를 사용합니다. 값은 대소문자를 구분합니다.
- Action의 경우, 호출하려는 API 또는 작업을 사용합니다. 이것은 일반적으로 카멜 표기법 패턴을 따르며, 값은 대소문자를 구분합니다.
- Parameters의 경우, API 또는 작업을 호출할 때 전달하는 선택 사항 파라미터를 사용합니다. 파라미터를 변수로 선언한 다음 API 페이로드에 대한 JSON 객체와 비슷한 인터페이스에 해당 변수를 전달할 수 있습니다. 자세한 내용은 JavaScript용 AWS SDK를 참조하십시오.
예시 1: 동적으로 구성 검색
다음 예시에서는 스택을 만드는 중에 AWS Systems Manager Parameter Store에서 Amazon Machine Image ID를 검색합니다. 여기에는 점 표기법을 사용하여 SDK 응답 구조를 탐색하는 getResponseField 메서드로 API 호출의 응답을 참조하는 방법을 표시했습니다.
import * as cdk from "aws-cdk-lib/core"; import { Construct } from "constructs"; import * as cr from "aws-cdk-lib/custom-resources"; export class Example1Stack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const getAmiId = new cr.AwsCustomResource(this, "GetAMIId", { onCreate: { service: "SSM", action: "getParameter", parameters: { Name: "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64", }, physicalResourceId: cr.PhysicalResourceId.of("get-ami-id"), }, policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE, }), }); new cdk.CfnOutput(this, "ImageId", { value: getAmiId.getResponseField("Parameter.Value"), }); } }
예시 2: CloudFormation에서 사용할 수 없는 리소스 속성 검색
CloudFormation은 Fn::GetAtt를 통해 모든 리소스 속성을 노출하지 않습니다. CloudFormation이 필요한 값을 반환하지 않는 경우, SDK 호출을 사용해 서비스 API에서 직접 검색하십시오. 이 방법을 사용하면 스택 내보내기, SSM 파라미터 또는 Secrets Manager에 저장하지 않았고 CloudFormation 및 그 속성 외부에 존재하는 리소스를 검색할 수 있습니다.
예를 들어 AWS::Organizations::Organization은 Id 및 ManagementAccountId를 반환 값으로 노출하지만, CloudFormation은 대부분의 조직을 만들지 않습니다. describeOrganization에 대해 SDK를 호출하면 스택에 조직을 포함할 필요 없이 멤버 계정에서 해당 값을 검색할 수 있습니다.
import * as cdk from "aws-cdk-lib/core"; import { Construct } from "constructs"; import * as cr from "aws-cdk-lib/custom-resources"; export class Example2Stack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const orgInfo = new cr.AwsCustomResource(this, "DescribeOrg", { onCreate: { service: "Organizations", action: "describeOrganization", physicalResourceId: cr.PhysicalResourceId.of("describe-org"), outputPaths: ["Organization.Id", "Organization.MasterAccountId"], }, policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE, }), }); new cdk.CfnOutput(this, "OrgId", { value: orgInfo.getResponseField("Organization.Id"), }); new cdk.CfnOutput(this, "ManagementAccountId", { value: orgInfo.getResponseField("Organization.MasterAccountId"), }); } }
참고: 이 예시에서는 응답을 필요한 필드로만 제한하기 위해 outputPaths를 사용합니다. 이렇게 하면 CloudFormation의 응답 한도인 4,096바이트에 도달하지 않게 방지해 줍니다.
예시 3: CloudFormation이 지원하지 않는 구성 변경 사항 적용
일부 작업에는 상응하는 CloudFormation 리소스 또는 속성이 없습니다. 예를 들어 CloudFormation은 DynamoDB 테이블을 만들 수는 있지만, 해당 테이블에 항목을 삽입할 수는 없습니다. 이 문제를 해결하려면 AwsSdkCall을 사용해 배포 시점에 첫 데이터를 시드합니다.
다음 예시에서는 onCreate를 사용하므로 스택을 처음 만들 때만 항목을 삽입합니다. 스택 업데이트 시에 항목도 업데이트하려면 onUpdate에 동일한 호출을 추가하십시오.
import * as cdk from "aws-cdk-lib/core"; import { Construct } from "constructs"; import * as cr from "aws-cdk-lib/custom-resources"; import * as dynamodb from "aws-cdk-lib/aws-dynamodb"; export class Example3Stack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const table = new dynamodb.Table(this, "ConfigTable", { partitionKey: { name: "PK", type: dynamodb.AttributeType.STRING }, }); new cr.AwsCustomResource(this, "SeedData", { onCreate: { service: "DynamoDB", action: "putItem", parameters: { TableName: table.tableName, Item: { PK: { S: "CONFIG" }, version: { S: "1.0" }, enabled: { BOOL: true }, }, }, physicalResourceId: cr.PhysicalResourceId.of("seed-data"), }, policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: [table.tableArn], }), }); } }
복잡한 권한 처리 상황
policy 속성을 사용하면 사용자 지정 리소스 뒤의 Lambda 함수에 권한을 부여합니다. **fromSdkCalls()**를 사용하면 각 API 호출을 상응하는 IAM 권한으로 자동으로 변환합니다. 가능한 경우, ANY_RESOURCE(예시 3)를 사용하지 말고 권한의 범위를 특정 리소스 ARN으로만 지정하십시오.
상황에 따라 **fromSdkCalls()**가 필요한 모든 권한을 생성하지 않을 수 있습니다. 예를 들어 예시 3의 DynamoDB 테이블이 고객 관리형 KMS 키를 사용하는 경우, **fromSdkCalls()**는 dynamodb:PutItem만 생성하고 KMS 권한은 전혀 추가하지 않습니다. 암호화된 테이블에 항목을 작성하려면 DynamoDB에 kms:Encrypt, kms:Decrypt 및 kms:GenerateDataKey가 있어야 하기 때문에 해당 배포는 실패합니다. **fromStatements()**를 사용해 정확한 권한을 지정할 수 있습니다.
예를 들면 다음과 같습니다.
import * as cdk from "aws-cdk-lib/core"; import { Construct } from "constructs"; import * as cr from "aws-cdk-lib/custom-resources"; import * as dynamodb from "aws-cdk-lib/aws-dynamodb"; import * as kms from "aws-cdk-lib/aws-kms"; import * as iam from "aws-cdk-lib/aws-iam"; export class Example4Stack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const encryptionKey = new kms.Key(this, "TableKey"); const table = new dynamodb.Table(this, "ConfigTable", { partitionKey: { name: "PK", type: dynamodb.AttributeType.STRING }, encryption: dynamodb.TableEncryption.CUSTOMER_MANAGED, encryptionKey, }); new cr.AwsCustomResource(this, "SeedData", { onCreate: { service: "DynamoDB", action: "putItem", parameters: { TableName: table.tableName, Item: { PK: { S: "CONFIG" }, version: { S: "1.0" }, enabled: { BOOL: true }, }, }, physicalResourceId: cr.PhysicalResourceId.of("seed-data"), }, policy: cr.AwsCustomResourcePolicy.fromStatements([ new iam.PolicyStatement({ actions: ["dynamodb:PutItem"], resources: [table.tableArn], }), new iam.PolicyStatement({ actions: ["kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey"], resources: [encryptionKey.keyArn], }), ]), }); } }
- 언어
- 한국어

This article was reviewed and updated on 2026-06-01.