블로그 릴레이 - CDK 에서 다른 리전에서 만들어진 리소스를 참조하는 방법

블로그 릴레이 - CDK 에서 다른 리전에서 만들어진 리소스를 참조하는 방법

안녕하세요 생산지원 그룹 리테일 어플리케이션부의 김승연입니다. 본 블로그는 당사의 한국어 블로그 릴레이의 2025년 스물세 번째 블로그입니다. 이번 블로그의 주제는 「CDK 에서 다른 리전에서 만들어진 리소스를 참조하는방법」 입니다.
2025.07.05

안녕하세요 생산지원 그룹 리테일 어플리케이션부의 김승연입니다.

본 블로그는 당사의 한국어 블로그 릴레이의 2025년 스물세 번째 블로그입니다.
이번 블로그의 주제는 「CDK 에서 다른 리전에서 만들어진 리소스를 참조하는방법」 입니다.

결론

결론부터 말하면 CDK에서는 다른 리전에서 만들어진 리소스를 참조할 수 있는 옵션을 제공하고 있습니다.

https://www.npmjs.com/package/aws-cdk-lib

You can enable the Stack property crossRegionReferences in order to access resources in a different stack and region. With this feature flag enabled it is possible to do something like creating a CloudFront distribution in us-east-2 and an ACM certificate in us-east-1.

예시

아래 예시는 Amazon CloudFront + Amazon S3 + AWS WAF 구성으로 리소스를 작성할 때의 예입니다.

두 개의 서로 다른 Region에서 만들어진 Stack이 있다면, 아래와 같이 WebSecurityStack에서 만들어진 AWS WAF의 Web ACL 의 ARN 값을 WebStack에 Props으로 전달 할 수 있습니다.

bin/iac.ts

...

const webSecurityStackResult = new WebSecurityStack(app,'WebSecurityStack',{
    env: {
      account: process.env.CDK_DEFAULT_ACCOUNT,
      region: 'us-east-1', // 버지니아
    },
  }
);

new WebStack(app, 'WebStack', {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: 'ap-northeast-2' //서울
  },
  webAclArn: webSecurityStackResult.webAcl.attrArn,
  crossRegionReferences: true,
});

AWS WAF

lib/stacks/web-security-stack.ts

...
export class WebSecurityStack extends cdk.Stack {
  public readonly webAcl: wafv2.CfnWebACL;

  constructor(scope: Construct, id: string, props: WebSecurityStackProps) {
    super(scope, id, props);

    // Whitelist IP Set
    const allowedIpSet = new wafv2.CfnIPSet(this, 'AllowedIPSet', {
      name: 'allowed-ips',
      scope: 'CLOUDFRONT',
      ipAddressVersion: 'IPV4',
      addresses: [],
    });

    this.webAcl = new wafv2.CfnWebACL(this, 'WebACL', {
      name: 'web-acl',
      scope: 'CLOUDFRONT',
      defaultAction: { block: {} },
      visibilityConfig: {
        metricName: 'web-acl-metric',
        sampledRequestsEnabled: true,
        cloudWatchMetricsEnabled: true, 
      },
      rules: [
        {
          name: 'allow-whitelisted-ips',
          priority: 1,
          statement: {
            ipSetReferenceStatement: {
              arn: allowedIpSet.attrArn,
            },
          },
          action: { allow: {} },
          visibilityConfig: {
            metricName: 'allow-whitelisted-ips-metric',
            sampledRequestsEnabled: true
            cloudWatchMetricsEnabled: true
          },
        },
      ],
    });
  }
}

Amazon CloudFront + Amazon S3

lib/stacks/web-stack.ts

...
export class WebStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: WebStackProps) {
    super(scope, id, props);

    const hostingBucket = new s3.Bucket(this, 'HostingBucket', {
      bucketName: '...',
      publicReadAccess: false,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });

    const distribution = new cloudfront.Distribution(this, 'Distribution', {
      defaultRootObject: 'index.html',
      webAclId: props.webAclArn, // NOTE: WAF ACL ARN 지정
      errorResponses: [
        {
          ttl: cdk.Duration.seconds(300),
          httpStatus: 404,
          responseHttpStatus: 200,
          responsePagePath: '/index.html',
        },
      ],
      defaultBehavior: {
        allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD,
        cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD,
        cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
        viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        origin: cloudfrontOrigins.S3BucketOrigin.withOriginAccessControl(hostingBucket),
        responseHeadersPolicy: new cloudfront.ResponseHeadersPolicy(this, 'ResponseHeaderPolicy', {
          securityHeadersBehavior: {
            contentTypeOptions: { override: true },
            referrerPolicy: {
              referrerPolicy: cloudfront.HeadersReferrerPolicy.SAME_ORIGIN,
              override: true,
            },
            frameOptions: {
              frameOption: cloudfront.HeadersFrameOption.DENY,
              override: true,
            },
            strictTransportSecurity: {
              accessControlMaxAge: cdk.Duration.seconds(63072000),
              includeSubdomains: true,
              preload: true,
              override: true,
            },
            xssProtection: {
              protection: true,
              modeBlock: true,
              override: true,
            },
          },
        }),
      },
    });

    new s3Deployment.BucketDeployment(this, 'Deployment', {
      sources: [],
      destinationBucket: hostingBucket,
      distribution: distribution,
      distributionPaths: ['/*'],
    });
  }
}

보충

이번에 소개한 옵션은 상당히 편리한 기능이지만, 아래의 설명을 볼 때 이후 업데이트 등이 활발할 것으로 보이기 때문에 향후 업데이트에 주의를 기울어야 할 것 같습니다.

https://www.npmjs.com/package/aws-cdk-lib

This feature is currently experimental

참고자료

https://www.npmjs.com/package/aws-cdk-lib

문의 사항은 클래스메소드 코리아로!

클래스메소드 코리아에서는 다양한 세미나 및 이벤트를 진행하고 있습니다.
진행중인 이벤트는 아래 페이지를 참고해주세요.

https://classmethod.kr/board/library

AWS에 대한 상담 및 클래스 메소드 멤버스에 관한 문의사항은 아래 메일로 연락주시면 감사드립니다!
Info@classmethod.kr

この記事をシェアする

facebookのロゴhatenaのロゴtwitterのロゴ

© Classmethod, Inc. All rights reserved.