

# CloudFormation 템플릿 작업
<a name="template-guide"></a>

AWS CloudFormation 템플릿은 스택의 일부로 생성, 업데이트 또는 삭제하려는 AWS 리소스를 정의합니다. 템플릿에는 여러 섹션이 있지만 [Resources](resources-section-structure.md) 섹션은 하나 이상의 리소스를 선언해야 하는 유일한 필수 섹션입니다.

다음 방법을 사용하여 템플릿을 생성할 수 있습니다.
+ **AWS Infrastructure Composer** - 템플릿 디자인을 위한 시각적 인터페이스입니다.
+ **텍스트 편집기** - JSON 또는 YAML 구문으로 직접 템플릿을 작성합니다.
+ **IaC 생성기** - 계정에 프로비저닝된 리소스 중 현재 CloudFormation에서 관리하지 않는 리소스에서 템플릿을 생성합니다. IaC 생성기는 사용자 리전의 Cloud Control API에서 지원하는 다양한 리소스 유형과 함께 작동합니다.

이 섹션에서는 CloudFormation 템플릿의 다양한 섹션을 사용하는 방법과 스택 템플릿 생성을 시작하는 방법에 대한 포괄적인 가이드를 제공합니다. 다음과 같은 주제를 다룹니다.

**Topics**
+ [템플릿이 저장되는 위치](#where-they-get-stored)
+ [템플릿 유효성 검사](#template-validation)
+ [템플릿 시작하기](#getting-started)
+ [샘플 템플릿](#sample-templates)
+ [템플릿 형식](template-formats.md)
+ [템플릿 섹션](template-anatomy.md)
+ [Infrastructure Composer](infrastructure-composer-for-cloudformation.md)
+ [AWS CloudFormation 언어 서버](ide-extension.md)
+ [IaC 생성기](generate-IaC.md)
+ [다른 서비스에 저장된 값 가져오기](dynamic-references.md)
+ [AWS 값 가져오기](pseudo-parameter-reference.md)
+ [스택 출력 가져오기](using-cfn-stack-exports.md)
+ [런타임 시 기존 리소스 지정](cloudformation-supplied-parameter-types.md)
+ [연습](walkthroughs.md)
+ [템플릿 코드 조각](template-snippets.md)
+ [Windows 기반 스택](cfn-windows-stacks.md)
+ [CloudFormation 제공 리소스 유형 사용](cloudformation-supplied-resource-types.md)
+ [모듈을 사용하여 재사용 가능한 리소스 구성 생성](modules.md)

## 템플릿이 저장되는 위치
<a name="where-they-get-stored"></a>

**Amazon S3 버킷**  
CloudFormation 템플릿을 Amazon S3 버킷에 저장할 수 있습니다. 스택을 생성하거나 업데이트할 때 직접 업로드하는 대신 템플릿의 S3 URL을 지정할 수 있습니다.

AWS Management Console 또는 AWS CLI를 통해 템플릿을 직접 업로드하는 경우 S3 버킷이 자동으로 생성됩니다. 자세한 내용은 [CloudFormation 콘솔에서 스택 생성](cfn-console-create-stack.md) 섹션을 참조하세요.

**Git 리포지토리**  
[Git 동기화](git-sync.md)를 사용하면 Git 리포지토리에 템플릿을 저장할 수 있습니다. 스택을 생성하거나 업데이트할 때 직접 업로드하거나 S3 URL을 참조하는 대신 템플릿이 포함된 Git 리포지토리 위치와 브랜치를 지정할 수 있습니다. CloudFormation은 지정된 리포지토리와 브랜치를 자동으로 모니터링하여 템플릿 변경을 확인합니다. 자세한 내용은 [Git 동기화를 사용하여 리포지토리 소스 코드에서 스택 생성](git-sync-create-stack-from-repository-source-code.md) 섹션을 참조하세요.

## 템플릿 유효성 검사
<a name="template-validation"></a>

**구문 유효성 검사**  
[validate-template](service_code_examples.md#validate-template-sdk) CLI 명령을 사용하거나 콘솔에서 템플릿을 지정하여 템플릿의 JSON 또는 YAML 구문을 확인할 수 있습니다. 콘솔은 유효성 검사를 자동으로 수행합니다. 자세한 내용은 [CloudFormation 콘솔에서 스택 생성](cfn-console-create-stack.md) 섹션을 참조하세요.

하지만 이러한 방법은 템플릿의 구문만 확인하고 리소스에 지정한 속성 값은 확인하지 않습니다.

**추가 유효성 검사 도구**  
더 복잡한 유효성 검사 및 모범 사례 검사의 경우 다음과 같은 추가 도구를 사용할 수 있습니다.
+ [CloudFormation Linter(cfn-lint)](https://github.com/aws-cloudformation/cfn-lint) - [CloudFormation 리소스 공급자 스키마](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/resource-type-schemas.html)를 기준으로 템플릿 유효성을 검사합니다. 리소스 속성의 유효한 값과 모범 사례를 검사하는 것이 포함됩니다.
+ [CloudFormation Rain(rain fmt)](https://github.com/aws-cloudformation/rain) - CloudFormation 템플릿을 일관된 표준으로 형식을 지정하거나 템플릿을 JSON에서 YAML로(또는 YAML에서 JSON으로) 형식을 재지정합니다. YAML을 사용할 때 주석을 보존하고 가능한 경우 내장 함수 사용을 짧은 구문으로 전환합니다.

## 템플릿 시작하기
<a name="getting-started"></a>

CloudFormation 템플릿 생성을 시작하려면 다음 단계를 따릅니다.

1. **리소스 선택** - EC2 인스턴스, VPC, 보안 그룹 등과 같이 스택에 포함하려는 AWS 리소스를 식별합니다.

1. **템플릿 작성** - 리소스와 속성을 정의하여 JSON 또는 YAML 형식으로 템플릿을 작성합니다.

1. **템플릿 저장** - `.json`, `.yaml`, `.txt` 등의 파일 확장자를 사용하여 템플릿을 로컬에 저장합니다.

1. **템플릿 유효성 검사** - [템플릿 유효성 검사](#template-validation) 섹션에서 설명하는 방법을 사용하여 템플릿의 유효성을 검사합니다.

1. **스택 생성** - 유효성 검사가 완료된 템플릿을 사용하여 스택을 생성합니다.

### CloudFormation 템플릿 참조 사용 계획
<a name="additional-resources"></a>

템플릿을 작성할 때 [AWS 리소스 및 속성 유형 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-template-resource-type-ref.html)에서 다양한 리소스 유형에 대한 자세한 구문에 대한 설명서를 찾을 수 있습니다.

스택 템플릿에는 런타임까지 사용할 수 없는 속성 값을 할당하는 내재 함수와 리소스의 동작을 제어하는 특수 속성이 필요한 경우가 많습니다. 템플릿을 작성할 때 다음 리소스를 참조하여 지침을 확인하세요.
+ [내장 함수 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference.html) - 일반적으로 사용되는 일부 내장 함수는 다음과 같습니다.
  + `Ref` - 리소스의 파라미터 또는 물리적 ID 값을 가져옵니다.
  + `Sub` - 문자열의 자리 표시자를 실제 값으로 대체합니다.
  + `GetAtt` - 템플릿의 리소스에서 속성 값을 반환합니다.
  + `Join` - 값 세트를 단일 문자열로 결합합니다.
+ [리소스 속성 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-product-attribute-reference.html) - 일반적으로 사용되는 일부 특수 속성은 다음과 같습니다.
  + `DependsOn` - 이 속성을 사용하면 한 리소스 다음에 다른 리소스 하나를 생성하도록 지정할 수 있습니다.
  + `DeletionPolicy` - 이 속성을 사용하면 CloudFormation에서 리소스 삭제를 처리하는 방법을 지정할 수 있습니다.

## 샘플 템플릿
<a name="sample-templates"></a>

CloudFormation은 시작하는 데 사용할 수 있는 오픈 소스 스택 템플릿을 제공합니다. 자세한 내용은 GitHub 웹 사이트의 [CloudFormation Sample Templates](https://github.com/aws-cloudformation/aws-cloudformation-templates)를 참조하세요.

이러한 템플릿은 프로덕션에 바로 사용할 수 있는 것이 아니라는 점에 유의하세요. 시간을 내어 이러한 프레임워크의 작동 방식을 알아보고, 필요에 맞게 조정하고, 회사의 규정 준수 기준을 충족하는지 확인해야 합니다.

이 리포지토리의 각 템플릿은 [CloudFormation Linter](https://github.com/aws-cloudformation/cfn-lint)(cfn-lint) 검사를 통과했으며, Center for Internet Security (CIS) Top 20를 기반으로 하는 기본 AWS CloudFormation Guard 규칙 세트(샘플을 단일 사용 사례에 집중하는 것이 합당한 일부 규칙 제외)도 통과했습니다.

# CloudFormation 템플릿 형식
<a name="template-formats"></a>

JSON 또는 YAML 형식으로 CloudFormation 템플릿을 작성할 수 있습니다. 두 형식 모두 용도는 같지만 가독성과 복잡성 측면에서 분명한 이점을 제공합니다.
+ **JSON** - JSON은 시스템이 쉽게 구문 분석하고 생성할 수 있는 가벼운 데이터 교환 형식입니다. 하지만 특히 복잡한 구성의 경우 사람이 읽고 쓰는 데 번거로울 수 있습니다. JSON에서 템플릿은 중첩된 중괄호 `{}`와 대괄호 `[]`를 사용하여 리소스, 파라미터 및 기타 구성 요소를 정의하는 구조입니다. 구문에서 모든 요소를 명시적으로 선언해야 하므로 템플릿이 장황해질 수 있지만 구조화된 형식을 엄격하게 준수할 수 있습니다.
+ **YAML** - YAML은 JSON보다 사람이 읽기 쉬우면서 장황하지 않도록 설계되었습니다. 중첩을 나타내는 데 중괄호와 대괄호 대신 들여쓰기를 사용하므로 리소스 및 파라미터의 계층 구조를 보다 쉽게 시각화할 수 있습니다. YAML은 명확성과 사용 편의성 때문에 선호되는 경우가 많으며, 특히 복잡한 템플릿을 다룰 때 선호됩니다. 하지만 YAML이 들여쓰기에 의존하기에 띄어쓰기가 일정하지 않을 경우 오류가 발생할 수 있으므로 정확성을 유지하기 위해 세심한 주의를 기울여야 합니다.

## 템플릿 구조
<a name="template-structure"></a>

CloudFormation 템플릿은 여러 섹션으로 나뉘며 각 섹션은 특정 유형의 정보를 유지하도록 설계되어 있습니다. 일부 섹션은 특정 순서로 선언해야 하지만 나머지 섹션은 순서가 중요하지 않습니다. 하지만 템플릿을 작성할 때 한 섹션의 값이 이전 섹션의 값을 참조할 수도 있으므로 다음 예제의 논리적 순서를 사용하는 것이 유용할 수 있습니다.

템플릿을 작성할 때 `Resources` 섹션과 같이 중복된 주요 섹션을 사용해서는 안 됩니다. CloudFormation은 이러한 템플릿을 수락할 수 있지만 템플릿을 처리할 때 정의되지 않은 동작을 하고 리소스를 잘못 프로비저닝하거나 설명할 수 없는 오류를 반환할 수 있습니다.

### JSON
<a name="template-structure.json"></a>

다음 예제에서는 사용 가능한 모든 섹션이 있는 JSON 형식의 템플릿 구조를 보여줍니다.

```
{
  "AWSTemplateFormatVersion" : "version date",

  "Description" : "JSON string",

  "Metadata" : {
    template metadata
  },

  "Parameters" : {
    set of parameters
  },
  
  "Rules" : {
    set of rules
  },

  "Mappings" : {
    set of mappings
  },

  "Conditions" : {
    set of conditions
  },

  "Transform" : {
    set of transforms
  },

  "Resources" : {
    set of resources
  },
  
  "Outputs" : {
    set of outputs
  }
}
```

### YAML
<a name="template-structure.yaml"></a>

다음 예제에서는 사용 가능한 모든 섹션이 있는 YAML 형식의 템플릿 구조를 보여줍니다.

```
---
AWSTemplateFormatVersion: version date

Description:
  String

Metadata:
  template metadata

Parameters:
  set of parameters

Rules:
  set of rules

Mappings:
  set of mappings

Conditions:
  set of conditions

Transform:
  set of transforms

Resources:
  set of resources

Outputs:
  set of outputs
```

## 설명
<a name="template-comments"></a>

JSON 형식의 템플릿에서는 주석이 지원되지 않습니다. JSON은 설계상 주석 구문을 포함하지 않으므로 JSON 구조 내에서 직접 주석을 추가할 수 없습니다. 하지만 설명 노트나 문서를 포함해야 하는 경우 메타데이터 추가를 고려할 수 있습니다. 자세한 내용은 [Metadata 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-metadata.html)을 참조하세요.

YAML 형식의 템플릿에서는 `#` 기호를 사용하여 인라인 주석을 포함할 수 있습니다.

다음 예제에서는 인라인 설명이 있는 YAML 템플릿을 보여 줍니다.

```
AWSTemplateFormatVersion: 2010-09-09
Description: A sample CloudFormation template with YAML comments.
# Resources section
Resources:
  MyEC2Instance: 
    Type: AWS::EC2::Instance
    Properties: 
      # Linux AMI
      ImageId: ami-1234567890abcdef0 
      InstanceType: t2.micro
      KeyName: MyKey
      BlockDeviceMappings:
        - DeviceName: /dev/sdm
          Ebs:
            VolumeType: io1
            Iops: 200
            DeleteOnTermination: false
            VolumeSize: 20
```

## 사양
<a name="template-formats.supported-specifications"></a>

CloudFormation은 다음과 같은 JSON 및 YAML 사양을 지원합니다.

JSON  
CloudFormation은 ECMA-404 JSON 표준을 따릅니다. JSON 형식에 대한 자세한 내용은 [http://www.json.org](http://www.json.org)를 참조하십시오.

YAML  
CloudFormation은 몇 가지 예외가 있지만 YAML 버전 1.1 사양을 지원합니다. CloudFormation은 다음과 같은 기능을 지원하지 않습니다.  
+ `binary`, `omap`, `pairs`, `set` 및 `timestamp` 태그
+ 에일리어스
+ 해시 병합
YAML에 대한 자세한 내용은 [http://yaml.org/](https://yaml.org/)를 참조하세요.

## 자세히 알아보기
<a name="template-formats.learnmore"></a>

템플릿에서 지정하는 각 리소스에 대해 JSON 또는 YAML의 특정 구문 규칙을 사용하여 해당 속성과 값을 정의합니다. 각 형식의 템플릿 구문에 대한 자세한 내용은 [CloudFormation 템플릿 섹션](template-anatomy.md) 단원을 참조하십시오.

# CloudFormation 템플릿에서 정규식 사용
<a name="cfn-regexes"></a>

템플릿 [파라미터](parameters-section-structure.md)를 생성할 때 `AllowedPattern` 속성의 경우와 같이 CloudFormation 템플릿 내의 수많은 장소에서 정규식(일반적으로 regex라고 함)을 사용할 수 있습니다.

CloudFormation의 정규식은 Java regex 구문을 따릅니다. Java regex 구문과 그 구조에 대한 포괄적인 설명은 [java.util.regex.Pattern](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html)을 참조하세요.

CloudFormation 템플릿을 JSON 구문으로 작성하는 경우 백슬래시를 추가하여 정규 표현식에서 백슬래시 문자(\$1)를 이스케이프해야 합니다. 이는 JSON이 백슬래시를 이스케이프 문자로 해석하기 때문이며, 정규식에서 백슬래시를 리터럴 백슬래시로 처리하려면 이스케이프해야 합니다.

예를 들어, 숫자 문자를 일치시키기 위해 정규식에 `\d`를 포함시키는 경우 JSON 템플릿에서는 `\\d`로 작성해야 합니다.

다음 예제에서 `AllowedPattern` 속성은 4자리 연속 문자(`\d{4}`)와 일치하는 정규식을 지정합니다. 하지만 정규식은 JSON 템플릿에 정의되어 있으므로 추가 백슬래시(`\\d`)로 백슬래시 문자를 이스케이프해야 합니다.

```
{
  "Parameters": {
    "MyParameter": {
      "Type": "String",
      "AllowedPattern": "\\d{4}"
    }
  }
}
```

CloudFormation 템플릿을 YAML 구문으로 작성하는 경우 정규식을 작은따옴표(“)로 묶어야 합니다. 추가 이스케이프는 필요하지 않습니다.

```
Parameters:
  MyParameter:
    Type: String
    AllowedPattern: '\d{4}'
```

**참고**  
CloudFormation의 정규식은 `AllowedPattern`과 같은 특정 컨텍스트에서 검증 목적으로만 지원됩니다. 패턴 일치가 아닌 정확한 문자열 비교만 수행하는 `Fn::Equals`와 같은 CloudFormation 내장 함수에서는 패턴 일치 작업으로 지원되지 않습니다.

# CloudFormation 템플릿 섹션
<a name="template-anatomy"></a>

모든 CloudFormation 템플릿은 하나 이상의 섹션으로 구성되며, 각 섹션에는 특정한 목적이 있습니다.

**Resources** 섹션은 모든 CloudFormation 템플릿에 필요하고 템플릿의 핵심을 구성합니다. 이 섹션은 Amazon EC2 인스턴스 또는 Amazon S3 버킷 같은 스택 리소스 및 해당 속성을 지정합니다. 각 리소스는 고유한 논리적 ID, 유형 및 특정 구성 세부 정보로 정의됩니다.

**Parameters** 섹션은 선택 사항이지만 템플릿을 보다 유연하게 만드는 데 중요한 역할을 합니다. 이를 통해 사용자는 스택을 생성하거나 업데이트할 때 런타임에서 값을 전달할 수 있습니다. `Resources` 및 `Outputs` 섹션에서 이러한 파라미터를 참조할 수 있으므로 템플릿 자체를 변경하지 않고도 사용자 지정할 수 있습니다. 예를 들어, 파라미터를 사용하여 배포마다 달라지는 인스턴스 유형이나 환경 설정을 지정할 수 있습니다.

선택 사항이기도 한 **Outputs** 섹션에서는 스택의 속성을 볼 때 반환되는 값을 정의합니다. Outputs는 리소스 식별자 또는 URL과 같은 유용한 정보를 제공하며, 이러한 정보는 운영 목적이나 다른 스택과의 통합에 활용할 수 있습니다. 이 섹션을 통해 사용자는 템플릿에 의해 생성된 리소스에 대한 중요한 세부 정보를 검색하고 사용할 수 있습니다.

기타 선택 사항인 섹션에는 조건부 값을 관리하는 조회 테이블과 같은 기능을 하는 **Mappings**이 있습니다. 매핑을 사용하면 키-값 페어를 정의하고 `Resources` 및 `Outputs` 섹션의 `Fn::FindInMap` 내장 함수와 함께 이를 사용할 수 있습니다. 이는 AWS 리전 또는 환경 등의 조건에 따라 구성을 조정해야 하는 시나리오에 유용합니다.

**Metadata** 및 **Rules** 섹션은 자주 사용되지 않지만 추가 기능을 제공합니다. `Metadata`는 템플릿에 대한 추가 정보를 포함할 수 있고, `Rules`는 스택 생성 또는 업데이트 중에 파라미터 또는 파라미터 조합의 유효성을 검사하여 특정 기준을 충족하는지 확인합니다. **Conditions** 섹션에서는 환경 유형과 같은 조건에 따라 특정 리소스가 생성되는지 또는 속성에 값이 할당되는지 제어하여 유연성을 더욱 높입니다.

마지막으로 **Transform** 섹션은 템플릿 처리 중 매크로를 적용하는 데 사용됩니다. 서버리스 애플리케이션(Lambda 애플리케이션이라고도 함)의 경우 사용할 [AWS Serverless Application Model(AWS SAM)](https://github.com/awslabs/serverless-application-specification)의 버전을 지정합니다. 변환을 지정할 경우 AWS SAM 구문을 사용하여 템플릿에 리소스를 선언할 수 있습니다. 이 모델은 사용할 수 있는 구문과 처리 방식을 정의합니다. 또한 `AWS::Include` 변환을 사용하여 기본 CloudFormation 템플릿과는 별도로 저장되는 템플릿 스니펫을 포함시킬 수 있습니다.

다음 주제에서는 각 섹션 사용에 대한 자세한 정보와 예제를 제공합니다.

**Topics**
+ [Resources](resources-section-structure.md)
+ [Parameters](parameters-section-structure.md)
+ [Outputs](outputs-section-structure.md)
+ [Mappings](mappings-section-structure.md)
+ [Metadata](metadata-section-structure.md)
+ [Rules](rules-section-structure.md)
+ [Conditions](conditions-section-structure.md)
+ [Transform](transform-section-structure.md)
+ [포맷 버전](format-version-structure.md)
+ [Description](template-description-structure.md)

# CloudFormation 템플릿 Resources 구문
<a name="resources-section-structure"></a>

`Resources` 섹션은 CloudFormation 템플릿의 필수 최상위 섹션입니다. CloudFormation에서 스택의 일부로 프로비저닝 및 구성하려는 AWS 리소스를 선언합니다.

## 구문
<a name="resources-section-structure-syntax"></a>

`Resources` 섹션에서는 다음 구문을 사용합니다.

### JSON
<a name="resources-section-structure-syntax.json"></a>

```
"Resources" : {
    "LogicalResourceName1" : {
        "Type" : "AWS::ServiceName::ResourceType",
        "Properties" : {
            "PropertyName1" : "PropertyValue1",
            ...
        }
    },

    "LogicalResourceName2" : {
        "Type" : "AWS::ServiceName::ResourceType",
        "Properties" : {
            "PropertyName1" : "PropertyValue1",
            ...
        }
    }
}
```

### YAML
<a name="resources-section-structure-syntax.yaml"></a>

```
Resources:
  LogicalResourceName1:
    Type: AWS::ServiceName::ResourceType
    Properties:
      PropertyName1: PropertyValue1
      ...

  LogicalResourceName2:
    Type: AWS::ServiceName::ResourceType
    Properties:
      PropertyName1: PropertyValue1
      ...
```

## 논리적 ID(**논리명이라고도 함)
<a name="resources-section-logical-id"></a>

CloudFormation 템플릿 내에서 리소스는 논리적 이름으로 식별됩니다. 이 이름은 영숫자(A-Z, a-z, 0-9)여야 하며 템플릿 내에서 고유해야 합니다. 논리명은 템플릿의 다른 섹션에 있는 리소스를 참조하는 데 사용됩니다.

## 리소스 유형
<a name="resources-section-resource-type"></a>

각 리소스에는 `Type` 속성이 있어야 하며, 이 속성은 AWS 리소스의 종류를 정의합니다. `Type` 속성은 `AWS::ServiceName::ResourceType` 형식을 갖습니다. 예를 들어, Amazon S3 버킷의 `Type` 속성은 `AWS::S3::Bucket`입니다.

지원되는 리소스 유형의 전체 목록은 [AWS 리소스 및 속성 유형 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-template-resource-type-ref.html)를 참조하세요.

## 리소스 속성
<a name="resources-section-resource-properties"></a>

리소스 속성은 특정 리소스 유형에 대한 구성 세부 정보를 정의하기 위해 지정할 수 있는 추가 옵션입니다. 일부 속성은 필수이고, 선택 사항인 속성도 있습니다. 일부 속성에는 기본값이 있으므로 해당 속성을 지정하는 것은 선택 사항입니다.

각 리소스 유형에 지원되는 속성에 대한 자세한 내용은 [AWS 리소스 및 속성 유형 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-template-resource-type-ref.html)의 주제를 참조하세요.

속성값은 리터럴 문자열, 문자열 목록, 부울, 동적 참조, 파라미터 참조, 가상 참조 또는 함수가 반환하는 값 중 하나일 수 있습니다. 다음 예제에서는 다양한 속성 값 유형을 선언하는 방법을 보여줍니다.

### JSON
<a name="resource-properties-example.json"></a>

```
"Properties" : {
    "String" : "A string value",
    "Number" : 123,
    "LiteralList" : [ "first-value", "second-value" ],
    "Boolean" : true
}
```

### YAML
<a name="resource-properties-example.yaml"></a>

```
Properties:
  String: A string value 
  Number: 123
  LiteralList:
    - first-value
    - second-value
  Boolean: true
```

## 물리적 ID
<a name="resources-section-physical-id"></a>

논리적 ID 외에도, 특정 리소스에는 EC2 인스턴스 ID 또는 S3 버킷 이름 같은 해당 리소스에 대해 실제 할당된 이름인 물리적 ID도 지정됩니다. 물리적 ID를 사용하여 CloudFormation 템플릿 외부에 있는 리소스를 식별할 수 있지만 이는 리소스가 생성된 후에만 가능합니다. 예를 들어 EC2 인스턴스에 논리적 ID `MyEC2Instance`의 리소스를 제공한다고 가정하겠습니다. CloudFormation에서 인스턴스를 생성할 때 CloudFormation은 자동적으로 물리적 ID(예: `i-1234567890abcdef0`)를 생성하여 인스턴스에 할당합니다. 이 물리적 ID를 사용하면 Amazon EC2 콘솔에서 인스턴스를 식별하고 인스턴스의 속성(예: DNS 이름)을 볼 수 있습니다.

Amazon S3 버킷과 기타 여러 리소스의 경우 사용자가 명시적으로 지정하지 않으면 CloudFormation이 리소스에 대한 고유한 물리명을 자동으로 생성합니다. 이 물리명은 CloudFormation 스택의 이름, CloudFormation 템플릿에 지정된 리소스의 논리명, 고유 ID의 조합을 기반으로 합니다. 예를 들어, `MyStack`이라는 스택에 논리명이 `MyBucket`인 Amazon S3 버킷이 있는 경우 CloudFormation은 `MyStack-MyBucket-abcdefghijk1`이라는 물리적 이름으로 버킷의 이름을 지정할 수 있습니다.

사용자 지정 이름을 지원하는 리소스의 경우, 물리적 이름을 할당하면 리소스를 보다 신속하게 식별할 수 있습니다. 예를 들면 로그를 저장하는 S3 버킷에 `MyPerformanceLogs` 이름을 지정할 수 있습니다. 자세한 내용은 [이름 유형](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-name.html)을 참조하세요.

## 참조 리소스
<a name="using-cross-resource-references"></a>

다른 리소스의 이름이나 속성을 기반으로 한 리소스의 속성을 설정해야 하는 경우가 있습니다. 예를 들어, S3 버킷이 지원하는 CloudFront 배포 또는 EC2 보안 그룹을 사용하는 EC2 인스턴스를 생성할 수 있습니다. 이러한 모든 리소스는 동일한 CloudFormation 템플릿에서 생성할 수 있습니다.

CloudFormation은 다른 리소스 및 해당 속성을 참조하는 데 사용할 수 있는 내장 함수를 제공합니다. 이러한 함수를 사용하면 리소스 간에 종속성을 생성하고 한 리소스에서 다른 리소스로 값을 전달할 수 있습니다.

### `Ref` 함수
<a name="resource-properties-ref"></a>

`Ref` 함수는 대체로 동일한 CloudFormation 템플릿 내에 정의된 리소스의 식별 속성을 검색하는 데 사용됩니다. 반환되는 내용은 리소스 유형에 따라 달라집니다. 대부분의 리소스는 리소스의 물리명을 반환합니다. 하지만 일부 리소스 유형의 경우 `AWS::EC2::EIP` 리소스의 IP 주소나 Amazon SNS 주제의 Amazon 리소스 이름(ARN) 등의 다른 값을 반환할 수 있습니다.

다음 예제는 속성에서 `Ref` 함수의 사용 방법을 설명합니다. 각 예제에서 `Ref` 함수는 템플릿의 다른 곳에서 선언된 `LogicalResourceName` 리소스의 실제 이름을 반환합니다. YAML 예제의 `!Ref` 구문 예제는 `Ref` 함수를 보다 간단하게 작성하는 방법입니다.

#### JSON
<a name="resource-properties-ref-example.json"></a>

```
"Properties" : {
    "PropertyName" : { "Ref" : "LogicalResourceName" }
}
```

#### YAML
<a name="resource-properties-ref-example.yaml"></a>

```
Properties:
  PropertyName1:
    Ref: LogicalResourceName
  PropertyName2: !Ref LogicalResourceName
```

`Ref` 함수에 대한 더 자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-ref.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-ref.html)를 참조하세요.

### `Fn::GetAtt` 함수
<a name="resource-properties-getatt"></a>

`Ref` 함수는 리소스에 대해 반환되는 파라미터나 값이 정확히 원하는 값인 경우에 유용합니다. 그러나 리소스의 다른 속성이 필요할 수 있습니다. 예를 들어 S3 오리진을 사용하여 CloudFront 배포를 생성하려는 경우 DNS 스타일 주소를 사용하여 버킷 위치를 지정해야 합니다. 일부 리소스에는 템플릿에서 사용할 수 있는 값이 지정되는 추가 속성이 있습니다. 이러한 속성을 가져오려면 `Fn::GetAtt` 함수를 사용합니다.

다음 예제는 속성에서 `GetAtt` 함수의 사용 방법을 설명합니다. `Fn::GetAtt` 함수는 두 개 파라미터, 리소스의 논리적 이름, 그리고 검색할 속성의 이름을 사용합니다. YAML 예제의 `!GetAtt` 구문 예제는 `GetAtt` 함수를 보다 간단하게 작성하는 방법입니다.

#### JSON
<a name="resource-properties-getatt-example.json"></a>

```
"Properties" : {
    "PropertyName" : {
        "Fn::GetAtt" : [ "LogicalResourceName", "AttributeName" ]
    }
}
```

#### YAML
<a name="resource-properties-getatt-example.yaml"></a>

```
Properties:
  PropertyName1:
    Fn::GetAtt:
      - LogicalResourceName
      - AttributeName
  PropertyName2: !GetAtt LogicalResourceName.AttributeName
```

`GetAtt` 함수에 대한 더 자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-getatt.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-getatt.html)를 참조하세요.

## 예제
<a name="resources-section-structure-examples"></a>

다음 예제는 리소스를 선언하는 방법과 CloudFormation 템플릿이 동일한 템플릿 내에 정의된 다른 리소스와 기존 AWS 리소스를 참조하는 방법을 보여줍니다.

**Topics**
+ [사용자 지정 이름을 사용하여 단일 리소스 선언](#resources-section-structure-examples-single-resource)
+ [`Ref` 함수로 다른 리소스 참조](#resources-section-structure-examples-ref)
+ [`Fn::GetAtt` 함수를 사용하여 리소스 속성 참조](#resources-section-structure-examples-getatt)

### 사용자 지정 이름을 사용하여 단일 리소스 선언
<a name="resources-section-structure-examples-single-resource"></a>

다음 예제에서는 논리명이 `MyBucket`인 `AWS::S3::Bucket` 유형의 단일 리소스를 선언합니다. `BucketName` 속성이 *amzn-s3-demo-bucket*으로 설정되는데, 이를 원하는 S3 버킷 이름으로 바꿔야 합니다.

이 리소스 선언을 사용하여 스택을 생성할 경우 CloudFormation에서는 기본 설정으로 Amazon S3 버킷을 생성합니다. Amazon EC2 인스턴스나 Auto Scaling 그룹 같은 기타 리소스의 경우 CloudFormation은 추가 정보를 요구합니다.

#### JSON
<a name="resources-section-structure-examples-single-resource.json"></a>

```
{
    "Resources": {
        "MyBucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {
                "BucketName": "amzn-s3-demo-bucket"
            }
        }
    }
}
```

#### YAML
<a name="resources-section-structure-examples-single-resource.yaml"></a>

```
Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: amzn-s3-demo-bucket
```

### `Ref` 함수로 다른 리소스 참조
<a name="resources-section-structure-examples-ref"></a>

다음 예제는 EC2 인스턴스와 보안 그룹을 정의하는 리소스 선언을 보여줍니다. `Ec2Instance` 리소스는 `Ref` 함수를 사용하여 해당 `SecurityGroupIds` 속성의 일부로 `InstanceSecurityGroup` 리소스를 참조합니다. 템플릿에 선언되지 않은 기존 보안 그룹(`sg-12a4c434`)도 포함됩니다. 리터럴 문자열을 사용하여 기존 AWS 리소스를 참조합니다.

#### JSON
<a name="resources-section-structure-examples-ref.json"></a>

```
{
    "Resources": {
        "Ec2Instance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "SecurityGroupIds": [
                    {
                        "Ref": "InstanceSecurityGroup"
                    },
                    "sg-12a4c434"
                ],
                "KeyName": "MyKey",
                "ImageId": "ami-1234567890abcdef0"
            }
        },
        "InstanceSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": "Enable SSH access via port 22",
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 22,
                        "ToPort": 22,
                        "CidrIp": "0.0.0.0/0"
                    }
                ]
            }
        }
    }
}
```

#### YAML
<a name="resources-section-structure-examples-ref.yaml"></a>

```
Resources:
  Ec2Instance:
    Type: AWS::EC2::Instance
    Properties:
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
        - sg-12a4c434
      KeyName: MyKey
      ImageId: ami-1234567890abcdef0
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable SSH access via port 22
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
```

### `Fn::GetAtt` 함수를 사용하여 리소스 속성 참조
<a name="resources-section-structure-examples-getatt"></a>

다음 예제에서는 CloudFront 배포 리소스와 S3 버킷을 정의하는 리소스 선언을 보여줍니다. `MyDistribution` 리소스는 버킷의 `DomainName` 속성을 가져오는 `Fn::GetAtt` 함수를 사용하여 `MyBucket` 리소스의 DNS 이름을 지정합니다. `Fn::GetAtt` 함수는 두 파라미터를 어레이 형태로 나열합니다. 여러 파라미터를 사용하는 함수의 경우 어레이를 사용하여 파라미터를 지정합니다.

#### JSON
<a name="resources-section-structure-examples-getatt.json"></a>

```
{
  "Resources": {
    "MyBucket": {
      "Type": "AWS::S3::Bucket"
    },
    "MyDistribution": {
      "Type": "AWS::CloudFront::Distribution",
      "Properties": {
        "DistributionConfig": {
          "Origins": [
            {
              "DomainName": {
                "Fn::GetAtt": [
                  "MyBucket",
                  "DomainName"
                ]
              },
              "Id": "MyS3Origin",
              "S3OriginConfig": {}
            }
          ],
          "Enabled": "true",
          "DefaultCacheBehavior": {
            "TargetOriginId": "MyS3Origin",
            "ForwardedValues": {
              "QueryString": "false"
            },
            "ViewerProtocolPolicy": "allow-all"
          }
        }
      }
    }
  }
}
```

#### YAML
<a name="resources-section-structure-examples-getatt.yaml"></a>

```
Resources:
  MyBucket:
    Type: AWS::S3::Bucket
  MyDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - DomainName: !GetAtt 
              - MyBucket
              - DomainName
            Id: MyS3Origin
            S3OriginConfig: {}
        Enabled: 'true'
        DefaultCacheBehavior:
          TargetOriginId: MyS3Origin
          ForwardedValues:
            QueryString: 'false'
          ViewerProtocolPolicy: allow-all
```

# CloudFormation 템플릿 Parameters 구문
<a name="parameters-section-structure"></a>

선택 사항인 `Parameters` 단원을 사용하여 템플릿을 사용자 지정합니다. 파라미터를 통해 스택을 생성하거나 업데이트 할 때마다 템플릿에 사용자 지정 값을 입력할 수 있습니다. 템플릿에 파라미터를 사용하여 특정 시나리오에 맞게 조정할 수 있는 재사용 가능하고 유연한 템플릿을 만들 수 있습니다.

적절한 유형의 파라미터를 정의하여 콘솔로 스택을 생성할 때 기존 리소스의 식별자 목록에서 선택할 수 있습니다. 자세한 내용은 [CloudFormation에서 제공하는 파라미터 유형을 사용하여 런타임 시 기존 리소스 지정](cloudformation-supplied-parameter-types.md) 섹션을 참조하세요.

파라미터는 스택 리소스의 속성 값을 지정하는 데 주로 사용되는 방법입니다. 그러나 리전에 따라 달라지는 설정이 있거나 다른 조건이나 종속성으로 인해 사용자가 파악하기 어려운 설정이 있을 수 있습니다. 이러한 경우 원하는 결과를 얻기 위해 보다 간단한 값을 지정할 수 있도록(또는 전혀 지정할 필요가 없도록) 템플릿에 몇 가지 논리를 추가하는 것이 좋습니다(예: 매핑 사용). 자세한 내용은 [CloudFormation 템플릿 Mappings 구문](mappings-section-structure.md) 섹션을 참조하세요.

## 구문
<a name="parameters-section-structure-syntax"></a>

다음 일반 구문을 사용하는 템플릿의 `Parameters` 섹션에서 파라미터를 선언합니다.

### JSON
<a name="parameters-section-structure-syntax.json"></a>

```
"Parameters" : {
  "ParameterLogicalID" : {
    "Description": "Information about the parameter",
    "Type" : "DataType",
    "Default" : "value",
    "AllowedValues" : ["value1", "value2"]
  }
}
```

### YAML
<a name="parameters-section-structure-syntax.yaml"></a>

```
Parameters:
  ParameterLogicalID:
    Description: Information about the parameter
    Type: DataType
    Default: value
    AllowedValues:
      - value1
      - value2
```

파라미터에는 해당 값과 값에 대한 구속 조건을 정의하는 속성 목록이 포함됩니다. 유일한 필수 속성은 `Type`(`String`, `Number` 또는 CloudFormation에서 제공하는 파라미터 유형일 수 있음)입니다. 사용자가 지정해야 하는 값의 종류에 대해 설명하는 `Description` 속성을 추가할 수도 있습니다. 파라미터의 이름과 설명은 **스택 생성** 마법사에서 템플릿을 사용할 때 **파라미터 지정** 페이지에 나타납니다.

**참고**  
기본적으로 CloudFormation 콘솔에는 입력 파라미터가 논리적 ID에 따라 영문자순으로 나열됩니다. 이 기본 순서를 재정의하고 관련 파라미터를 함께 그룹화하려면 템플릿의 `AWS::CloudFormation::Interface` 메타데이터 키를 사용할 수 있습니다. 자세한 내용은 [`AWS::CloudFormation::Interface` 메타데이터를 사용하여 CloudFormation 파라미터 구성](aws-cloudformation-interface.md) 섹션을 참조하세요.

기본값이 있는 파라미터의 경우 CloudFormation에서는 사용자가 다른 값을 지정하지 않을 경우 기본값이 사용됩니다. 기본 속성을 생략하는 경우 사용자가 해당 파라미터에 대한 값을 지정해야 합니다. 그러나 사용자에게 값을 입력하도록 요구한다고 해서 해당 값의 유효성이 보장되는 것은 아닙니다. 파라미터 값을 검증하려는 경우 제약을 선언하거나 AWS 특정 유형을 지정할 수 있습니다.

기본값이 없는 파라미터의 경우 사용자는 스택 생성 시 키 이름 값을 지정해야 합니다. 지정하지 않을 경우 CloudFormation에서 스택을 생성할 수 없으며 다음 예외가 발생합니다.

```
Parameters: [KeyName] must have values
```

## 속성
<a name="parameters-section-structure-properties"></a>

`AllowedPattern`  
`String` 또는 `CommaDelimitedList` 유형에 허용할 패턴을 나타내는 정규식입니다. `String` 파라미터 유형에 적용할 경우 패턴이 제공된 전체 파라미터값과 일치해야 합니다. `CommaDelimitedList` 파라미터 유형에 적용할 경우 패턴이 목록의 각 값과 일치해야 합니다.  
*필수 항목 여부*: 아니요

`AllowedValues`  
파라미터에 허용되는 값 목록을 포함하는 어레이입니다. `String` 파라미터 유형에 적용할 경우 파라미터값은 허용된 값 중 하나여야 합니다. `CommaDelimitedList` 파라미터 유형에 적용할 경우 목록의 각 값은 지정된 허용된 값 중 하나여야 합니다.  
*필수 항목 여부*: 아니요  
YAML을 사용하면서 `AllowedValues`에 `Yes` 및 `No` 문자열을 사용하려는 경우 작은따옴표를 사용하여 YAML 구문 분석기가 이러한 부울 값을 고려하지 않도록 합니다.

`ConstraintDescription`  
제약 위반 시 해당 제약을 설명하는 문자열입니다. 예를 들어 제약 설명이 없으면 `[A-Za-z0-9]+` 패턴이 허용된 파라미터에 사용자가 유효하지 않은 값을 지정할 때 다음과 같은 오류 메시지가 표시됩니다.  
`Malformed input-Parameter MyParameter must match pattern [A-Za-z0-9]+`  
*'문자(대문자 및 소문자)와 숫자만 포함시킬 수 있음'* 같은 제약을 추가, 다음과 같은 사용자 지정 오류 메시지를 표시할 수 있습니다.  
`Malformed input-Parameter MyParameter must only contain uppercase and lowercase letters and numbers`  
*필수 항목 여부*: 아니요

`Default`  
스택 생성 시 지정된 값이 없는 경우에 사용할 템플릿에 적합한 유형의 값입니다. 파라미터에 대한 제약을 정의하는 경우 이러한 제약을 준수하는 값을 지정해야 합니다.  
*필수 항목 여부*: 아니요

`Description`  
파라미터를 설명하는 최대 4000자 문자열입니다.  
*필수 항목 여부*: 아니요

`MaxLength`  
`String` 유형에 허용할 최대 문자 수를 결정하는 정수 값입니다.  
*필수 항목 여부*: 아니요

`MaxValue`  
`Number` 유형에 허용할 최대 숫자 값을 결정하는 숫자 값입니다.  
*필수 항목 여부*: 아니요

`MinLength`  
`String` 유형에 허용할 최소 문자 수를 결정하는 정수 값입니다.  
*필수 항목 여부*: 아니요

`MinValue`  
`Number` 유형에 허용할 최소 숫자 값을 결정하는 숫자 값입니다.  
*필수 항목 여부*: 아니요

`NoEcho`  
콘솔, 명령줄 도구 또는 API에 표시되지 않도록 파라미터값을 마스킹 처리할지 여부입니다. `NoEcho` 속성을 `true`로 설정한 경우, 아래 지정된 위치에 저장된 정보를 제외하고 CloudFormation은 스택 또는 스택 이벤트를 설명하는 모든 호출에 대해 별표(\$1\$1\$1\$1\$1)로 마스킹 처리된 파라미터값을 반환합니다.  
*필수 항목 여부*: 아니요  
`NoEcho` 속성을 사용해도 다음에 저장된 정보는 마스킹되지 않습니다.  
+ `Metadata` 템플릿 섹션. CloudFormation은 `Metadata` 섹션에 포함된 정보를 변환, 수정 또는 삭제하지 않습니다. 자세한 내용은 [메타데이터](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html)를 참조하십시오.
+ `Outputs` 템플릿 섹션. 자세한 내용은 [출력](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html)을 참조하십시오.
+ 리소스 정의의 `Metadata` 속성입니다. 자세한 내용은 [`Metadata` 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-metadata.html)을 참조하세요.
이러한 메커니즘을 사용하여 암호나 보안 정보와 같은 중요한 정보를 포함하지 않는 것이 좋습니다.
AWS Systems Manager Parameter Store 또는 AWS Secrets Manager와 같이 CloudFormation 외부에서 저장 및 관리되는 중요한 정보를 참조하려면 CloudFormation 템플릿에 직접 중요한 정보를 포함하는 대신 스택 템플릿에 있는 동적 파라미터를 사용하는 것이 좋습니다.  
자세한 내용은 [템플릿에 자격 증명을 포함하지 않음](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/security-best-practices.html#creds)을 참조하십시오.
리소스의 기본 식별자의 일부인 리소스 속성에 `NoEcho` 파라미터 또는 민감한 데이터를 포함하지 않는 것이 좋습니다.  
기본 리소스 식별자를 구성하는 속성에 `NoEcho` 파라미터가 포함된 경우 CloudFormation은 기본 리소스 식별자에서 **실제 일반 텍스트값을 사용할 수 있습니다. 이 리소스 ID는 파생된 출력 또는 대상에 나타날 수 있습니다.  
리소스 유형의 기본 식별자를 구성하는 리소스 속성을 확인하려면 [AWS 리소스 및 속성 유형 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-template-resource-type-ref.html)에서 해당 리소스에 대한 리소스 참조 설명서를 참조하세요. **Return values**(반환 값) 섹션에서 `Ref` 함수 반환 값은 리소스 유형의 기본 식별자를 구성하는 리소스 속성을 나타냅니다.

`Type`  <a name="parameters-section-structure-properties-type"></a>
파라미터(`DataType`)의 데이터 유형입니다.  
*필수 항목 여부:* 예  
CloudFormation은 다음과 같은 파라미터 유형을 지원합니다.    
`String`  
리터럴 문자열입니다. `MinLength`, `MaxLength`, `Default`, `AllowedValues` 및 `AllowedPattern` 속성을 사용하여 제약 조건을 선언할 수 있습니다.  
예를 들면 사용자는 `"MyUserName"`을 지정할 수 있습니다.  
`Number`  
정수 또는 부동 소수점. CloudFormation에서 파라미터값이 숫자로 확인되지만, 템플릿 내 다른 곳에서 이 파라미터를 사용하는 경우(예를 들어, `Ref` 내장 함수를 사용하여) 파라미터값이 문자열이 됩니다.  
`MinValue`, `MaxValue`, `Default` 및 `AllowedValues` 속성을 사용하여 제약 조건을 선언할 수 있습니다.  
예를 들면 사용자는 `"8888"`을 지정할 수 있습니다.  
`List<Number>`  
쉼표로 구분된 정수 또는 부동 소수점의 배열. CloudFormation에서 파라미터값이 숫자로 확인되지만, 템플릿 내 다른 곳에서 이 파라미터를 사용하는 경우(예를 들어, `Ref` 내장 함수를 사용하여) 파라미터값이 문자열 목록이 됩니다.  
예를 들어 사용자가 `"80,20"`을 지정하면 `Ref`는 `["80","20"]`이 됩니다.  
`CommaDelimitedList`  
쉼표로 구분된 리터럴 문자열 어레이입니다. 총 문자열 수는 총 쉼표 수보다 하나 더 많아야 합니다. 또한 각 멤버 문자열에는 공백이 삽입됩니다.  
예를 들어 사용자가 `"test,dev,prod"`을 지정하면 `Ref`는 `["test","dev","prod"]`이 됩니다.  
AWS 특정 파라미터 유형  
Amazon EC2 키 페어 이름 및 VPC ID와 같은 AWS 값입니다. 자세한 내용은 [런타임 시 기존 리소스 지정](cloudformation-supplied-parameter-types.md) 섹션을 참조하세요.  
Systems Manager 파라미터 유형  
시스템 관리자 Parameter Store의 기존 파라미터에 해당되는 파라미터. Systems Manager 파라미터 키를 Systems Manager 파라미터 유형 값으로 지정합니다. 그러면 CloudFormation이 Parameter Store에서 스택에 사용할 최신 값을 검색합니다. 자세한 내용은 [런타임 시 기존 리소스 지정](cloudformation-supplied-parameter-types.md) 섹션을 참조하세요.

## 파라미터의 일반 요구 사항
<a name="parameters-section-structure-requirements"></a>

파라미터를 사용할 때는 다음 요구 사항이 적용됩니다.
+ CloudFormation 템플릿에는 최대 200개의 파라미터를 지정할 수 있습니다.
+ 파라미터마다 논리명(논리적 ID)을 지정해야 합니다. 이 이름은 템플릿 내 모든 논리명 간에 고유해야 하며 영숫자로 지정해야 합니다.
+ 파라미터마다 CloudFormation에서 지원하는 파라미터 유형을 할당해야 합니다. 자세한 내용은 [유형](#parameters-section-structure-properties-type)을 참조하십시오.
+ 파라미터마다 런타임에 값을 할당해야 CloudFormation이 스택을 성공적으로 프로비저닝할 수 있습니다. 다른 값이 제공되는 경우를 제외하고, CloudFormation에 대한 기본값을 선택적으로 지정할 수 있습니다.
+ 파라미터는 동일한 템플릿에서 선언하고 참조해야 합니다. 템플릿의 `Resources` 및 `Outputs`의 파라미터를 참조할 수 있습니다.

## 예제
<a name="parameters-section-examples"></a>

**Topics**
+ [단순 문자열 파라미터](#parameters-section-structure-example-1)
+ [암호 파라미터](#parameters-section-structure-example-2)
+ [파라미터 참조](#parameters-section-structure-example-3)
+ [쉼표로 구분된 목록 파라미터](#parameters-section-structure-example-4)
+ [쉼표로 구분된 목록 파라미터에서 값 반환](#parameters-section-structure-example-5)

### 단순 문자열 파라미터
<a name="parameters-section-structure-example-1"></a>

다음 예제는 `String` 유형의 `InstanceTypeParameter`라는 파라미터를 선언합니다. 스택의 Amazon EC2 인스턴스 유형을 지정할 수 있는 파라미터입니다. 스택 생성 또는 업데이트 중 값이 제공되지 않으면 CloudFormation은 기본값인 `t2.micro`를 사용합니다.

#### JSON
<a name="parameters-section-structure-example-1.json"></a>

```
"Parameters" : {
  "InstanceTypeParameter" : {
    "Description" : "Enter t2.micro, m1.small, or m1.large. Default is t2.micro.",
    "Type" : "String",
    "Default" : "t2.micro",
    "AllowedValues" : ["t2.micro", "m1.small", "m1.large"]
  }
}
```

#### YAML
<a name="parameters-section-structure-example-1.yaml"></a>

```
Parameters:
  InstanceTypeParameter:
    Description: Enter t2.micro, m1.small, or m1.large. Default is t2.micro.
    Type: String
    Default: t2.micro
    AllowedValues:
      - t2.micro
      - m1.small
      - m1.large
```

### 암호 파라미터
<a name="parameters-section-structure-example-2"></a>

다음 예제는 기본값 없이 `String` 유형의 `DBPwd`라는 파라미터를 선언합니다. `NoEcho` 속성을 `true`로 설정하면 파라미터값이 스택 설명에 표시되지 않습니다. 지정할 수 있는 최소 길이는 `1`이고, 지정할 수 있는 최대 길이는 `41`입니다. 이 패턴에는 영문자 소문자/대문자와 숫자가 허용됩니다. 이 예제에서는 `AllowedPattern` 속성에 정규식을 사용하는 방법도 보여줍니다.

#### JSON
<a name="parameters-section-structure-example-2.json"></a>

```
"Parameters" : {
  "DBPwd" : {
    "NoEcho" : "true",
    "Description" : "The database admin account password",
    "Type" : "String",
    "MinLength" : "1",
    "MaxLength" : "41",
    "AllowedPattern" : "^[a-zA-Z0-9]*$"
  }
}
```

#### YAML
<a name="parameters-section-structure-example-2.yaml"></a>

```
Parameters: 
  DBPwd: 
    NoEcho: true
    Description: The database admin account password
    Type: String
    MinLength: 1
    MaxLength: 41
    AllowedPattern: ^[a-zA-Z0-9]*$
```

### 파라미터 참조
<a name="parameters-section-structure-example-3"></a>

`Ref` 내장 함수를 사용하여 파라미터를 참조할 수 있고, CloudFormation은 스택 프로비저닝에 이 파라미터값을 사용합니다. 동일한 템플릿의 `Resources` 및 `Outputs`의 파라미터를 참조할 수 있습니다.

다음은 EC2 인스턴스의 `InstanceType` 속성이 `InstanceTypeParameter` 파라미터값을 참조하는 예제입니다.

#### JSON
<a name="parameters-section-structure-example-3.json"></a>

```
"Ec2Instance" : {
  "Type" : "AWS::EC2::Instance",
  "Properties" : {
    "InstanceType" : { "Ref" : "InstanceTypeParameter" },
    "ImageId" : "ami-0ff8a91507f77f867"
  }
}
```

#### YAML
<a name="parameters-section-structure-example-3.yaml"></a>

```
Ec2Instance:
  Type: AWS::EC2::Instance
  Properties:
    InstanceType:
      Ref: InstanceTypeParameter
    ImageId: ami-0ff8a91507f77f867
```

### 쉼표로 구분된 목록 파라미터
<a name="parameters-section-structure-example-4"></a>

`CommaDelimitedList` 파라미터 유형은 단일 속성에 여러 값을 제공해야 할 때 유용할 수 있습니다. 다음 예제는 쉼표로 구분된 3개의 CIDR 블록을 기본값으로 사용하여 `DbSubnetIpBlocks`라는 파라미터를 선언합니다.

#### JSON
<a name="parameters-section-structure-example-4.json"></a>

```
"Parameters" : {
  "DbSubnetIpBlocks": {
    "Description": "Comma-delimited list of three CIDR blocks",
    "Type": "CommaDelimitedList",
    "Default": "10.0.48.0/24, 10.0.112.0/24, 10.0.176.0/24"
  }
}
```

#### YAML
<a name="parameters-section-structure-example-4.yaml"></a>

```
Parameters: 
  DbSubnetIpBlocks: 
    Description: "Comma-delimited list of three CIDR blocks"
    Type: CommaDelimitedList
    Default: "10.0.48.0/24, 10.0.112.0/24, 10.0.176.0/24"
```

### 쉼표로 구분된 목록 파라미터에서 값 반환
<a name="parameters-section-structure-example-5"></a>

파라미터의 쉼표로 구분된 목록에서 특정 값을 참조하려면 템플릿의 `Resources` 섹션에서 `Fn::Select` 내장 함수를 사용합니다. 다음 예제와 같이 원하는 객체의 인덱스 값과 객체 목록을 전달합니다.

#### JSON
<a name="parameters-section-structure-example-5.json"></a>

```
{
    "Parameters": {
        "VPC": {
            "Type": "String",
            "Default": "vpc-123456"
        },
        "VpcAzs": {
            "Type": "CommaDelimitedList",
            "Default": "us-west-2a, us-west-2b, us-west-2c"
        },
        "DbSubnetIpBlocks": {
            "Type": "CommaDelimitedList",
            "Default": "172.16.0.0/26, 172.16.0.64/26, 172.16.0.128/26"
        }
    },
    "Resources": {
        "DbSubnet1": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Fn::Select": [
                      0,
                      { 
                        "Ref": "VpcAzs" 
                      }
                   ]
                },
                "VpcId": {
                    "Ref": "VPC"
                },
                "CidrBlock": {
                    "Fn::Select": [
                        0,
                        { "Ref": "DbSubnetIpBlocks" }
                    ]
                }
            }
        },
        "DbSubnet2": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Fn::Sub": [
                        "${AWS::Region}${AZ}",
                        {
                            "AZ": {
                                "Fn::Select": [
                                    1,
                                    { "Ref": "VpcAzs" }
                                ]
                            }
                        }
                    ]
                },
                "VpcId": {
                    "Ref": "VPC"
                },
                "CidrBlock": {
                    "Fn::Select": [
                        1,
                        { "Ref": "DbSubnetIpBlocks" }
                    ]
                }
            }
        },
        "DbSubnet3": {
            "Type": "AWS::EC2::Subnet",
            "Properties": {
                "AvailabilityZone": {
                    "Fn::Sub": [
                        "${AWS::Region}${AZ}",
                        {
                            "AZ": {
                                "Fn::Select": [
                                    2,
                                    { "Ref": "VpcAzs" }
                                ]
                            }
                        }
                    ]
                },
                "VpcId": {
                    "Ref": "VPC"
                },
                "CidrBlock": {
                    "Fn::Select": [
                        2,
                        { "Ref": "DbSubnetIpBlocks" }
                    ]
                }
            }
        }
    }
}
```

#### YAML
<a name="parameters-section-structure-example-5.yaml"></a>

```
Parameters:
  VPC:
    Type: String
    Default: vpc-123456
  VpcAzs:
    Type: CommaDelimitedList
    Default: us-west-2a, us-west-2b, us-west-2c
  DbSubnetIpBlocks:
    Type: CommaDelimitedList
    Default: 172.16.0.0/26, 172.16.0.64/26, 172.16.0.128/26
Resources:
  DbSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Select
        - 0 
        - !Ref VpcAzs
      VpcId: !Ref VPC
      CidrBlock: !Select
        - 0
        - !Ref DbSubnetIpBlocks
  DbSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Sub
        - ${AWS::Region}${AZ}
        - AZ: !Select
            - 1
            - !Ref VpcAzs
      VpcId: !Ref VPC
      CidrBlock: !Select
        - 1
        - !Ref DbSubnetIpBlocks
  DbSubnet3:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Sub
        - ${AWS::Region}${AZ}
        - AZ: !Select
            - 2
            - !Ref VpcAzs
      VpcId: !Ref VPC
      CidrBlock: !Select
        - 2
        - !Ref DbSubnetIpBlocks
```

## 관련 리소스
<a name="parameters-section-structure-related-resources"></a>

또한 CloudFormation은 동적 참조를 사용하여 속성값을 동적으로 지정할 수 있도록 지원합니다. 예를 들어, Systems Manager Parameter Store에 저장되는 보안 문자열을 참조해야 할 수 있습니다. 자세한 내용은 [동적 참조를 사용하여 다른 서비스에 저장된 값 가져오기](dynamic-references.md) 섹션을 참조하세요.

`Ref` 또는 `Sub` 함수 내에서 가상 파라미터를 사용하여 값을 동적으로 채울 수도 있습니다. 자세한 내용은 [가상 파라미터를 사용하여 AWS 값 가져오기](pseudo-parameter-reference.md) 섹션을 참조하세요.

# CloudFormation 템플릿 Outputs 구문
<a name="outputs-section-structure"></a>

선택 사항인 `Outputs` 섹션은 스택의 출력 값을 선언합니다. 이러한 출력 값은 다양한 방식으로 사용할 수 있습니다.
+ **리소스 관련 중요한 세부 정보 수집** - 출력은 리소스 관련 중요 정보를 편리하게 수집할 수 있는 방법입니다. 예를 들면 스택의 S3 버킷 이름을 출력하면 버킷을 보다 쉽게 찾을 수 있습니다. CloudFormation 콘솔의 **출력** 탭이나 [describe-stacks](service_code_examples.md#describe-stacks-sdk) CLI 명령을 사용하여 출력 값을 볼 수 있습니다.
+ **교차 스택 참조** - 출력 값을 다른 스택으로 가져와서 [교차 스택 참조를 생성](using-cfn-stack-exports.md)할 수 있습니다. 이는 여러 스택에서 리소스 또는 구성을 공유해야 할 때 유용합니다.

**중요**  
CloudFormation은 `Outputs` 섹션에 포함한 정보를 삭제하거나 난독화하지 않습니다. 이 섹션을 사용하여 암호나 보안 암호와 같은 민감한 정보를 출력하지 않는 것이 좋습니다.  
출력값은 스택 작업이 완료된 후에 사용할 수 있습니다. 스택 상태가 `IN_PROGRESS` [상태](view-stack-events.md#cfn-console-view-stack-data-resources-status-codes) 중 하나일 때는 스택 출력 값을 사용할 수 없습니다. 출력값을 항상 사용할 수 있는 것은 아니므로 서비스 런타임과 스택 출력값 간에 종속성을 설정하지 않는 것이 좋습니다.

## 구문
<a name="outputs-section-syntax"></a>

`Outputs` 섹션은 키 이름 `Outputs`로 이루어집니다. 템플릿 안에 최대 60개 출력을 선언할 수 있습니다.

다음 예제에서는 `Outputs` 섹션의 구조를 보여줍니다.

### JSON
<a name="outputs-section-structure-syntax.json"></a>

모든 출력 선언을 괄호 안에 포함합니다. 출력이 여러 개인 경우 쉼표로 구분합니다.

```
"Outputs" : {
  "OutputLogicalID" : {
    "Description" : "Information about the value",
    "Value" : "Value to return",
    "Export" : {
      "Name" : "Name of resource to export"
    }
  }
}
```

### YAML
<a name="outputs-section-structure-syntax.yaml"></a>

```
Outputs:
  OutputLogicalID:
    Description: Information about the value
    Value: Value to return
    Export:
      Name: Name of resource to export
```

### 출력 필드
<a name="outputs-section-structure-output-fields"></a>

`Outputs` 섹션은 다음 필드를 포함할 수 있습니다.

**논리적 ID(**논리명이라고도 함)**  
현재 출력의 식별자입니다. 논리적 ID는 영숫자(`a–z`, `A–Z`, `0–9`)여야 하며 템플릿 내에서 고유해야 합니다.

**`Description` (선택 사항)**  
출력값을 설명하는 `String` 유형입니다. 설명 선언 값은 0\$11023바이트 길이의 리터럴 문자열이어야 합니다. 파라미터나 함수를 사용하여 설명을 지정할 수 없습니다.

**`Value`(필수)**  
[describe-stacks](service_code_examples.md#describe-stacks-sdk) 명령에 의해 반환되는 속성의 값입니다. 출력의 값에는 리터럴, 파라미터 참조, 가상 파라미터, 매핑 값 또는 내장 함수가 포함될 수 있습니다.

**`Export` (선택 사항)**  
교차 스택 참조를 위해 내보낼 리소스 출력의 이름입니다.  
내장 함수를 사용하여 내보내기의 `Name` 값을 사용자 지정할 수 있습니다.  
자세한 내용은 [배포된 CloudFormation 스택에서 내보낸 출력 가져오기](using-cfn-stack-exports.md) 섹션을 참조하세요.

출력과 조건을 연결하려면 템플릿의 [Conditions](conditions-section-structure.md) 섹션에 조건을 정의합니다.

## 예제
<a name="outputs-section-structure-examples"></a>

다음 예제에서는 스택 출력의 작동 방식을 보여줍니다.

**Topics**
+ [스택 출력](#outputs-section-structure-examples-stack-output)
+ [`Fn::Sub`를 사용하여 내보내기 이름 사용자 지정](#outputs-section-structure-examples-cross-stack)
+ [`Fn::Join`를 사용하여 내보내기 이름 사용자 지정](#outputs-section-structure-examples-join-export-name)
+ [`Fn::Join`을 사용하여 구성된 URL 반환](#outputs-section-structure-examples-join-export-url)

### 스택 출력
<a name="outputs-section-structure-examples-stack-output"></a>

다음 예제에서는 `BackupLoadBalancerDNSName` 이름의 출력이 `BackupLoadBalancer` 조건이 true일 때만 논리적 ID가 `CreateProdResources`인 리소스의 DNS 이름을 반환합니다. 이름이 `InstanceID`인 출력은 논리적 ID `EC2Instance`와 함께 EC2 인스턴스의 ID를 반환합니다.

#### JSON
<a name="outputs-section-structure-example.json"></a>

```
"Outputs" : {
  "BackupLoadBalancerDNSName" : {
    "Description": "The DNSName of the backup load balancer",  
    "Value" : { "Fn::GetAtt" : [ "BackupLoadBalancer", "DNSName" ]},
    "Condition" : "CreateProdResources"
  },
  "InstanceID" : {
    "Description": "The Instance ID",  
    "Value" : { "Ref" : "EC2Instance" }
  }
}
```

#### YAML
<a name="outputs-section-structure-example.yaml"></a>

```
Outputs:
  BackupLoadBalancerDNSName:
    Description: The DNSName of the backup load balancer
    Value: !GetAtt BackupLoadBalancer.DNSName
    Condition: CreateProdResources
  InstanceID:
    Description: The Instance ID
    Value: !Ref EC2Instance
```

### `Fn::Sub`를 사용하여 내보내기 이름 사용자 지정
<a name="outputs-section-structure-examples-cross-stack"></a>

다음 예제에서는 `StackVPC`는 VPC의 ID를 반환하고 나서, 스택 이름에 추가된 `VPCID` 이름을 사용하여 교차 스택 참조 값을 내보냅니다.

#### JSON
<a name="outputs-section-structure-cross-stack-example.json"></a>

```
"Outputs" : {
  "StackVPC" : {
    "Description" : "The ID of the VPC",
    "Value" : { "Ref" : "MyVPC" },
    "Export" : {
      "Name" : {"Fn::Sub": "${AWS::StackName}-VPCID" }
    }
  }
}
```

#### YAML
<a name="outputs-section-structure-cross-stack-example.yaml"></a>

```
Outputs:
  StackVPC:
    Description: The ID of the VPC
    Value: !Ref MyVPC
    Export:
      Name: !Sub "${AWS::StackName}-VPCID"
```

`Fn::Sub` 함수에 대한 자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-sub.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-sub.html) 단원을 참조하십시오.

### `Fn::Join`를 사용하여 내보내기 이름 사용자 지정
<a name="outputs-section-structure-examples-join-export-name"></a>

또한 `Fn::Join` 함수를 사용하여 파라미터, 리소스 속성 및 기타 문자열을 기반으로 값을 구성할 수 있습니다.

다음 예제에서는 `Fn::Sub` 함수 대신 `Fn::Join` 함수를 사용하여 내보내기 이름을 사용자 지정합니다. 예제 `Fn::Join` 함수는 콜론을 구분자로 사용하여 스택 이름과 이름 `VPCID`를 연결합니다.

#### JSON
<a name="outputs-section-structure-join-export-name-example.json"></a>

```
"Outputs" : {
  "StackVPC" : {
    "Description" : "The ID of the VPC",
    "Value" : { "Ref" : "MyVPC" },
    "Export" : {
      "Name" : { "Fn::Join" : [ ":", [ { "Ref" : "AWS::StackName" }, "VPCID" ] ] }
    }
  }
}
```

#### YAML
<a name="outputs-section-structure-join-export-name-example.yaml"></a>

```
Outputs:
  StackVPC:
    Description: The ID of the VPC
    Value: !Ref MyVPC
    Export:
      Name: !Join [ ":", [ !Ref "AWS::StackName", VPCID ] ]
```

`Fn::Join` 함수에 대한 자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-join.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-join.html) 단원을 참조하십시오.

### `Fn::Join`을 사용하여 구성된 URL 반환
<a name="outputs-section-structure-examples-join-export-url"></a>

WordPress 사이트를 생성하는 템플릿에 대한 이전 예제에서 `InstallURL`은 `Fn::Join` 함수 호출에서 반환된 문자열로, `http://`, 리소스 `ElasticLoadBalancer`의 DNS 이름, `/wp-admin/install.php`를 연결합니다. 출력 값은 다음과 비슷합니다.

```
http://mywptests-elasticl-1gb51l6sl8y5v-206169572.aws-region.elb.amazonaws.com/wp-admin/install.php
```

#### JSON
<a name="outputs-section-structure-examples-join-export-url.json"></a>

```
{
    "Outputs": {
        "InstallURL": {
            "Value": {
                "Fn::Join": [
                    "",
                    [
                        "http://",
                        {
                            "Fn::GetAtt": [
                                "ElasticLoadBalancer",
                                "DNSName"
                            ]
                        },
                        "/wp-admin/install.php"
                    ]
                ]
            },
            "Description": "Installation URL of the WordPress website"
        }
    }
}
```

#### YAML
<a name="outputs-section-structure-examples-join-export-url.yaml"></a>

```
Outputs:
  InstallURL:
    Value: !Join 
      - ''
      - - 'http://'
        - !GetAtt 
          - ElasticLoadBalancer
          - DNSName
        - /wp-admin/install.php
    Description: Installation URL of the WordPress website
```

`Fn::Join` 함수에 대한 자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-join.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-join.html) 단원을 참조하십시오.

# CloudFormation 템플릿 Mappings 구문
<a name="mappings-section-structure"></a>

선택 사항인 `Mappings` 섹션을 사용하면 특정 조건이나 종속성을 기반으로 값을 지정하는 데 사용할 수 있는 키-값 페어를 만들 수 있습니다.

`Mappings` 섹션의 일반적인 사용 사례 중 하나는 스택이 배포된 AWS 리전을 기반으로 값을 설정하는 것입니다. `AWS::Region` 가상 파라미터를 사용하여 설정할 수 있습니다. `AWS::Region` 가상 파라미터는 CloudFormation에서 스택이 생성되는 리전으로 확인되는 값입니다. 가상 파라미터는 스택 생성 시 CloudFormation에서 확인됩니다.

맵에서 값을 검색하려면 템플릿의 `Resources` 섹션 내에서 `Fn::FindInMap` 내장 함수를 사용하면 됩니다.

## 구문
<a name="mappings-section-structure-syntax"></a>

`Mappings` 섹션에서는 다음 구문을 사용합니다.

### JSON
<a name="mappings-section-structure-syntax.json"></a>

```
"Mappings" : {
  "MappingLogicalName" : {
    "Key1" : {
      "Name" : "Value1"
    },
    "Key2" : {
      "Name" : "Value2"
    },
    "Key3" : {
      "Name" : "Value3"
    }
  }
}
```

### YAML
<a name="mappings-section-structure-syntax.yaml"></a>

```
Mappings: 
  MappingLogicalName: 
    Key1: 
      Name: Value1
    Key2: 
      Name: Value2
    Key3: 
      Name: Value3
```
+ `MappingLogicalName`은 매핑의 논리명입니다.
+ 매핑 내에서 각 맵은 키이며, 그 뒤에는 다른 매핑이 이어집니다.
+ 키는 이름-값 페어의 맵이어야 하며 매핑 내에서 고유해야 합니다.
+ 이름-값 페어는 레이블과, 매핑할 값입니다. 값에 이름을 지정하여 두 개 이상의 값 세트를 키로 매핑할 수 있습니다.
+ 매핑의 키는 문자열이어야 합니다.
+ 값은 `String` 또는 `List` 유형이 될 수 있습니다.

**참고**  
`Mappings` 섹션에는 파라미터, 가상 파라미터 또는 내장 함수를 포함할 수 없습니다.  
매핑의 값이 현재 스택에서 사용되지 않는 경우, 매핑만 업데이트할 수는 없습니다. 리소스를 추가, 수정 또는 삭제하는 변경 내용을 포함해야 합니다.

## 예제
<a name="mappings-section-structure-examples"></a>

**Topics**
+ [기본 매핑](#mappings-section-structure-basic-example)
+ [여러 값을 사용하여 매핑](#mappings-section-structure-multiple-values-example)
+ [매핑에서 값 반환](#mappings-section-structure-return-value-example)
+ [입력 파라미터 및 `Fn::FindInMap`](#mappings-section-structure-input-parameter-example)

### 기본 매핑
<a name="mappings-section-structure-basic-example"></a>

다음 예제에서는 `Mappings` 맵을 사용하는 `RegionToInstanceType` 매핑을 보여줍니다. 이 매핑에는 단일 문자열 값을 포함하는 이름-값 페어로 매핑된 다섯 개 키가 들어 있습니다. 키는 리전 이름입니다. 각 이름-값 페어는 키로 표현되는 리전에서 사용할 수 있는 T 패밀리의 인스턴스 유형입니다. 이름-값 페어에는 이름(이 예제에서는 `InstanceType`)과 값이 지정됩니다.

#### JSON
<a name="mappings-section-structure-basic-example.json"></a>

```
"Mappings" : {
  "RegionToInstanceType" : {
    "us-east-1"      : { "InstanceType" : "t2.micro" },
    "us-west-1"      : { "InstanceType" : "t2.micro" },
    "eu-west-1"      : { "InstanceType" : "t2.micro" },
    "eu-north-1"     : { "InstanceType" : "t3.micro" },
    "me-south-1"     : { "InstanceType" : "t3.micro" }
  }
}
```

#### YAML
<a name="mappings-section-structure-basic-example.yaml"></a>

```
Mappings:
  RegionToInstanceType:
    us-east-1:
      InstanceType: t2.micro
    us-west-1:
      InstanceType: t2.micro
    eu-west-1:
      InstanceType: t2.micro
    eu-north-1:
      InstanceType: t3.micro
    me-south-1:
      InstanceType: t3.micro
```

### 여러 값을 사용하여 매핑
<a name="mappings-section-structure-multiple-values-example"></a>

다음 예제에는 `MyAMI1` 및 `MyAMI2`, 이렇게 두 가지 값 세트로 매핑되는 리전 키가 있습니다.

**참고**  
이 예제에 표시된 AMI ID는 데모용 자리 표시자입니다. 가능하면 `Mappings` 섹션의 대안으로 AWS Systems Manager 파라미터에 대한 동적 참조를 사용하는 것이 좋습니다. 사용하려는 AMI가 변경될 때마다 모든 템플릿을 새 ID로 업데이트하지 않으려면 스택이 생성되거나 업데이트될 때 AWS Systems Manager 파라미터를 사용하여 최신 AMI ID를 검색하세요. 일반적으로 사용되는 AMI의 최신 버전도 Systems Manager의 퍼블릭 파라미터로 사용할 수 있습니다. 자세한 내용은 [동적 참조를 사용하여 다른 서비스에 저장된 값 가져오기](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html)를 참조하세요.

#### JSON
<a name="mappings-section-structure-multiple-values-example"></a>

```
"Mappings" : {
  "RegionToAMI" : {
    "us-east-1"        : { "MyAMI1" : "ami-12345678901234567", "MyAMI2" : "ami-23456789012345678" },
    "us-west-1"        : { "MyAMI1" : "ami-34567890123456789", "MyAMI2" : "ami-45678901234567890" },
    "eu-west-1"        : { "MyAMI1" : "ami-56789012345678901", "MyAMI2" : "ami-67890123456789012" },
    "ap-southeast-1"   : { "MyAMI1" : "ami-78901234567890123", "MyAMI2" : "ami-89012345678901234" },
    "ap-northeast-1"   : { "MyAMI1" : "ami-90123456789012345", "MyAMI2" : "ami-01234567890123456" }
  }
}
```

#### YAML
<a name="mappings-section-structure-multiple-values-example.yaml"></a>

```
Mappings:
  RegionToAMI:
    us-east-1:
      MyAMI1: ami-12345678901234567
      MyAMI2: ami-23456789012345678
    us-west-1:
      MyAMI1: ami-34567890123456789
      MyAMI2: ami-45678901234567890
    eu-west-1:
      MyAMI1: ami-56789012345678901
      MyAMI2: ami-67890123456789012
    ap-southeast-1:
      MyAMI1: ami-78901234567890123
      MyAMI2: ami-89012345678901234
    ap-northeast-1:
      MyAMI1: ami-90123456789012345
      MyAMI2: ami-01234567890123456
```

### 매핑에서 값 반환
<a name="mappings-section-structure-return-value-example"></a>

`Fn::FindInMap` 함수를 사용하여 지정한 키에 따라 명명된 값을 반환할 수 있습니다. 다음 예제 템플릿에는 `FindInMap` 함수를 통해 `InstanceType` 속성이 할당된 Amazon EC2 리소스가 포함되어 있습니다. `FindInMap` 함수는 키를 스택이 생성되는 AWS 리전(`AWS::Region` 가상 파라미터 사용)으로 지정하고 `InstanceType`을 매핑할 값 이름으로 지정합니다. `ImageId`는 Systems Manager 파라미터를 사용하여 최신 Amazon Linux 2 AMI를 동적으로 검색합니다. 가상 parameters에 대한 자세한 내용은 [가상 파라미터를 사용하여 AWS 값 가져오기](pseudo-parameter-reference.md) 단원을 참조하십시오.

#### JSON
<a name="mappings-section-structure-return-value-example.json"></a>

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Mappings" : {
    "RegionToInstanceType" : {
      "us-east-1"      : { "InstanceType" : "t2.micro" },
      "us-west-1"      : { "InstanceType" : "t2.micro" },
      "eu-west-1"      : { "InstanceType" : "t2.micro" },
      "eu-north-1"     : { "InstanceType" : "t3.micro" },
      "me-south-1"     : { "InstanceType" : "t3.micro" }
    }
  },
  "Resources" : {
    "myEC2Instance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}",
        "InstanceType" : { "Fn::FindInMap" : [ "RegionToInstanceType", { "Ref" : "AWS::Region" }, "InstanceType" ]}
      }
    }
  }
}
```

#### YAML
<a name="mappings-section-structure-return-value-example.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Mappings: 
  RegionToInstanceType: 
    us-east-1:
      InstanceType: t2.micro
    us-west-1:
      InstanceType: t2.micro
    eu-west-1:
      InstanceType: t2.micro
    eu-north-1:
      InstanceType: t3.micro
    me-south-1:
      InstanceType: t3.micro
Resources: 
  myEC2Instance: 
    Type: AWS::EC2::Instance
    Properties: 
      ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      InstanceType: !FindInMap [RegionToInstanceType, !Ref 'AWS::Region', InstanceType]
```

### 입력 파라미터 및 `Fn::FindInMap`
<a name="mappings-section-structure-input-parameter-example"></a>

다음 예제 템플릿은 여러 매핑을 사용하여 EC2 인스턴스를 생성하는 방법을 보여줍니다. 템플릿은 중첩 매핑을 사용하여 대상 AWS 리전 및 환경 유형(`Dev` 또는 `Prod`)에 따라 적절한 인스턴스 유형과 보안 그룹을 자동으로 선택합니다. 또한 Systems Manager 파라미터를 사용하여 최신 Amazon Linux 2 AMI를 동적으로 검색합니다.

#### JSON
<a name="mappings-section-structure-input-parameter-example.json"></a>

```
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Parameters" : {
    "EnvironmentType" : {
      "Description" : "The environment type (Dev or Prod)",
      "Type" : "String",
      "Default" : "Dev",
      "AllowedValues" : [ "Dev", "Prod" ]
    }
  },
  "Mappings" : {
    "RegionAndEnvironmentToInstanceType" : {
      "us-east-1"        : { "Dev" : "t3.micro", "Prod" : "c5.large" },
      "us-west-1"        : { "Dev" : "t2.micro", "Prod" : "m5.large" }
    },
    "RegionAndEnvironmentToSecurityGroup" : {
      "us-east-1"        : { "Dev" : "sg-12345678", "Prod" : "sg-abcdef01" },
      "us-west-1"        : { "Dev" : "sg-ghijkl23", "Prod" : "sg-45678abc" }
    }
  },
  "Resources" : {
    "Ec2Instance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}",
        "InstanceType" : { "Fn::FindInMap": [ "RegionAndEnvironmentToInstanceType", { "Ref": "AWS::Region" }, { "Ref": "EnvironmentType" } ]},
        "SecurityGroupIds" : [{ "Fn::FindInMap" : [ "RegionAndEnvironmentToSecurityGroup", { "Ref" : "AWS::Region" }, { "Ref" : "EnvironmentType" } ]}]
      }
    }
  }
}
```

#### YAML
<a name="mappings-section-structure-input-parameter-example.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  EnvironmentType: 
    Description: The environment type (Dev or Prod)
    Type: String
    Default: Dev
    AllowedValues: 
      - Dev
      - Prod
Mappings:
  RegionAndEnvironmentToInstanceType:
    us-east-1: 
      Dev: t3.micro
      Prod: c5.large
    us-west-1: 
      Dev: t2.micro
      Prod: m5.large
  RegionAndEnvironmentToSecurityGroup: 
    us-east-1: 
      Dev: sg-12345678
      Prod: sg-abcdef01
    us-west-1: 
      Dev: sg-ghijkl23
      Prod: sg-45678abc
Resources:
  Ec2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      InstanceType: !FindInMap [RegionAndEnvironmentToInstanceType, !Ref 'AWS::Region', !Ref EnvironmentType]
      SecurityGroupIds:
        - !FindInMap [RegionAndEnvironmentToSecurityGroup, !Ref 'AWS::Region', !Ref EnvironmentType]
```

## 관련 리소스
<a name="mappings-section-related-resources"></a>

이러한 관련 주제는 `Fn::FindInMap` 함수를 사용하는 템플릿을 개발할 때 도움이 될 수 있습니다.
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-findinmap.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-findinmap.html)
+ [Fn::FindInMap 기능 향상](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-findinmap-enhancements.html)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-sub.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-sub.html)

# CloudFormation 템플릿 Metadata 구문
<a name="metadata-section-structure"></a>

`Metadata`는 JSON 또는 YAML 객체를 사용하여 추가 정보를 저장합니다. 템플릿에서 사용할 수 있는 템플릿 수준 메타데이터 유형은 다음과 같습니다.

사용자 지정 메타데이터  
사용자 정의 키-값 페어를 저장합니다. 예를 들어 리소스 생성에는 영향을 미치지 않지만 인프라, 팀 또는 배포 세부 사항에 대한 추가 컨텍스트를 제시하는 추가 정보를 제공할 수 있습니다.

`AWS::CloudFormation::Interface`  
CloudFormation 콘솔에 표시되는 입력 파라미터의 그룹화 및 순서를 정의합니다. 기본적으로 CloudFormation 콘솔에는 파라미터가 논리적 ID에 따라 영문자순으로 정렬됩니다.

`AWS::CloudFormation::Designer`  
CloudFormation Designer(Designer)는 2025년 2월 5일 수명이 종료되었습니다.



**중요**  
스택 업데이트 중에는 `Metadata` 섹션을 자체적으로 업데이트할 수 없습니다. 리소스를 추가, 수정 또는 삭제하는 변경 내용을 포함할 때만 업데이트할 수 있습니다.  
CloudFormation은 `Metadata` 섹션에 포함된 정보를 변환, 수정 또는 삭제하지 않습니다. 이러한 이유 때문에 이 섹션을 사용하여 암호나 보안 암호와 같은 민감한 정보를 저장하지 않는 것이 좋습니다.

## 구문
<a name="metadata-section-structure-syntax"></a>

CloudFormation 템플릿에서 사용자 지정 메타데이터를 선언하려면 다음 구문을 사용합니다.

### JSON
<a name="metadata-section-structure-syntax.json"></a>

```
"Metadata" : {
  "Instances" : {"Description" : "Information about the instances"},
  "Databases" : {"Description" : "Information about the databases"}
}
```

### YAML
<a name="metadata-section-structure-syntax.yaml"></a>

```
Metadata:
  Instances:
    Description: "Information about the instances"
  Databases: 
    Description: "Information about the databases"
```

`AWS::CloudFormation::Interface`에 대한 구문은 [`AWS::CloudFormation::Interface` 메타데이터를 사용하여 CloudFormation 파라미터 구성](aws-cloudformation-interface.md) 섹션을 참조하세요.

# `AWS::CloudFormation::Interface` 메타데이터를 사용하여 CloudFormation 파라미터 구성
<a name="aws-cloudformation-interface"></a>

`AWS::CloudFormation::Interface`는 CloudFormation 콘솔에서 파라미터가 그룹화되고 정렬되는 방식을 정의하는 메타데이터 키입니다. 기본적으로 콘솔에서 스택을 생성하거나 업데이트하면 콘솔에는 입력 파라미터가 논리적 ID를 기준으로 사전순으로 나열됩니다. 이 키를 사용하면 사용자가 파라미터 값을 효율적으로 지정할 수 있도록 고유의 파라미터 그룹화 및 정렬을 정의할 수 있습니다. 예를 들어, 모든 EC2 관련 파라미터를 한 그룹으로 그룹화하고 모든 VPC 관련 파라미터를 다른 한 그룹으로 그룹화할 수 있습니다.

메타데이터 키에서는 생성할 그룹, 각 그룹에 포함할 파라미터, 그리고 콘솔에서 그룹 내 각 파라미터를 표시하는 순서를 지정할 수 있습니다.

파라미터의 레이블을 정의할 수도 있습니다. 레이블은 파라미터의 논리적 ID 대신 콘솔에 표시되는 표시 이름 또는 설명입니다. 레이블은 사용자가 각 파라미터에 지정할 값을 이해하도록 돕는 데 유용합니다. 예를 들어, `KeyPair` 파라미터에 `Select an EC2 key pair`라는 레이블을 지정할 수 있습니다.

메타데이터 키에서 참조하는 모든 파라미터는 템플릿의 `Parameters` 섹션에 선언해야 합니다.

**참고**  
CloudFormation 콘솔만 `AWS::CloudFormation::Interface` 메타데이터 키를 사용합니다. AWS CLI 및 API 호출은 이 키를 사용하지 않습니다.

## 구문
<a name="aws-resource-cloudformation-interface-syntax"></a>

CloudFormation 템플릿에서 이 객체를 선언하려면 다음 구문을 사용합니다.

### JSON
<a name="aws-resource-cloudformation-interface-syntax.json"></a>

```
"Metadata" : {
  "AWS::CloudFormation::Interface" : {
    "ParameterGroups": [
      {
        "Label": {
          "default": "Group Label"
        },
        "Parameters": [
          "Parameter1",
          "Parameter2"
        ]
      }
    ],
    "ParameterLabels": {
      "Parameter1": {
        "default": "Friendly Name for Parameter1"
      }
    }
  }
}
```

### YAML
<a name="aws-resource-cloudformation-interface-syntax.yaml"></a>

```
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Group Label
        Parameters:
          - Parameter1
          - Parameter2
    ParameterLabels:
      Parameter1:
        default: Friendly Name for Parameter1
```

## 속성
<a name="w2aac11c23c29c17c17"></a>

`ParameterGroups`  
그룹 이름, 각 그룹의 파라미터 및 파라미터가 표시되는 순서를 지정하는 파라미터 그룹 유형의 목록입니다.  
*필수 항목 여부*: 아니요    
`Label`  
파라미터 그룹의 이름입니다.  
*필수 항목 여부*: 아니요  
`default`  
CloudFormation 콘솔이 파라미터 그룹의 이름을 지정하는 데 사용하는 기본 레이블입니다.  
*필수 항목 여부*: 아니요  
*유형*: 문자열  
`Parameters`  
그룹에 포함할 파라미터 논리적 ID(대/소문자 구분)의 목록입니다. 파라미터가 템플릿의 `Parameters` 섹션에 이미 정의되어 있어야 합니다. 파라미터는 한 파라미터 그룹에만 포함될 수 있습니다.  
`Other parameters` 그룹에서 파라미터 그룹과 연결되지 않은 파라미터가 사전 순으로 콘솔에 나열됩니다.  
*필수 항목 여부*: 아니요  
*유형*: 문자열 값의 목록

`ParameterLabels`  
스택을 생성하거나 업데이트할 때 CloudFormation 콘솔에 표시되는 파라미터 및 해당 표시 이름의 매핑입니다.  
*필수 항목 여부*: 아니요    
파라미터 레이블  
파라미터에 대한 레이블입니다. 이 레이블은 스택 생성 또는 업데이트 시 CloudFormation 콘솔이 [**파라미터 지정(Specify Parameters)**] 페이지에 표시하는 기억하기 쉬운 이름 또는 설명을 정의합니다. 파라미터 라벨은 템플릿의 `Parameters` 섹션에서 선언된 유효한 파라미터의 논리적 ID(대/소문자 구분)여야 합니다.  
*필수 항목 여부*: 아니요  
`default`  
CloudFormation 콘솔이 파라미터의 이름을 지정하는 데 사용하는 기본 레이블입니다.  
*필수 항목 여부*: 아니요  
*유형*: 문자열

## 예제
<a name="w2aac11c23c29c17c19"></a>

다음 예제에서는 `Network Configuration` 및 `Amazon EC2 Configuration`이라는 두 개의 파라미터 그룹을 정의합니다. `Network Configuration` 그룹에는 템플릿(표시되지 않음)의 `VPCID` 섹션에서 정의되는 `SubnetId`, `SecurityGroupID` 및 `Parameters` 파라미터가 포함됩니다. 이러한 파라미터가 콘솔에 표시되는 순서는 `VPCID` 파라미터로 시작하여 파라미터가 나열되는 순서에 따라 정의됩니다. 예제에서는 비슷한 방식으로 `Amazon EC2 Configuration` 파라미터를 그룹화하고 정렬합니다.

예제에서는 `VPCID` 파라미터의 레이블도 정의합니다. 콘솔에서 파라미터의 논리적 ID(`VPCID`) 대신 **Which VPC should this be deployed to?(어떤 VPC에 배포합니까?)**가 표시됩니다.

### JSON
<a name="aws-cloudformation-interface-example.json"></a>

```
"Metadata" : {
  "AWS::CloudFormation::Interface" : {
    "ParameterGroups" : [
      {
        "Label" : { "default" : "Network Configuration" },
        "Parameters" : [ "VPCID", "SubnetId", "SecurityGroupID" ]
      },
      {
        "Label" : { "default":"Amazon EC2 Configuration" },
        "Parameters" : [ "InstanceType", "KeyName" ]
      }
    ],
    "ParameterLabels" : {
      "VPCID" : { "default" : "Which VPC should this be deployed to?" }
    }
  }
}
```

### YAML
<a name="aws-cloudformation-interface-example.yaml"></a>

```
Metadata: 
  AWS::CloudFormation::Interface: 
    ParameterGroups: 
      - Label: 
          default: "Network Configuration"
        Parameters: 
          - VPCID
          - SubnetId
          - SecurityGroupID
      - Label: 
          default: "Amazon EC2 Configuration"
        Parameters: 
          - InstanceType
          - KeyName
    ParameterLabels: 
      VPCID: 
        default: "Which VPC should this be deployed to?"
```

### 콘솔의 파라미터 그룹
<a name="w2aac11c23c29c17c19c11"></a>

다음 그림에서는 이 예제의 메타데이터 키를 사용하여 스택을 생성하거나 업데이트할 때 파라미터 그룹이 콘솔에 표시되는 방식을 보여 줍니다. **콘솔의 파라미터 그룹** 

![\[이 예제의 파라미터 그룹이 표시된 콘솔입니다.\]](http://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/images/console-create-stack-parameter-groups.png)


# CloudFormation 템플릿 Rules 구문
<a name="rules-section-structure"></a>

`Rules` 섹션은 사용자 지정 검증 로직을 활성화하는 CloudFormation 템플릿의 선택 사항 부분입니다. 포함된 경우 이 섹션에는 CloudFormation에서 리소스를 생성하거나 업데이트하기 전에 파라미터 값을 검증하는 규칙 함수가 포함되어 있습니다.

규칙은 표준 파라미터 제약 조건이 충분하지 않은 경우에 유용합니다. 예를 들어 SSL이 활성화된 경우 인증서와 도메인 이름을 모두 제공해야 합니다. 규칙을 통해 이러한 종속성이 충족되도록 보장할 수 있습니다.

## 구문
<a name="template-constraint-rules-syntax"></a>

`Rules` 섹션에서는 다음 구문을 사용합니다.

### JSON
<a name="rules-section-structure-syntax.json"></a>

템플릿의 `Rules` 섹션은 키 이름 `Rules`와 그 뒤에 이어지는 콜론 하나로 구성됩니다. 모든 규칙 선언을 괄호로 묶어야 합니다. 규칙을 여러 개 선언할 경우 쉼표로 구분됩니다. 각 규칙에 대해 인용 부호 안의 논리적 이름과 그 뒤에 오는 콜론, 그리고 규칙 조건과 어설션을 묶는 중괄호를 선언합니다.

```
{
    "Rules": {
        "LogicalRuleName1": {
            "RuleCondition": {
                "rule-specific intrinsic function": "Value"
            },
            "Assertions": [
                {
                    "Assert": {
                        "rule-specific intrinsic function": "Value"
                    },
                    "AssertDescription": "Information about this assert"
                },
                {
                    "Assert": {
                        "rule-specific intrinsic function": "Value"
                    },
                    "AssertDescription": "Information about this assert"
                }
            ]
        },
        "LogicalRuleName2": {
            "Assertions": [
                {
                    "Assert": {
                        "rule-specific intrinsic function": "Value"
                    },
                    "AssertDescription": "Information about this assert"
                }
            ]
        }
    }
}
```

### YAML
<a name="rules-section-structure-syntax.yaml"></a>

```
Rules:
  LogicalRuleName1:
    RuleCondition:
      rule-specific intrinsic function: Value
    Assertions:
      - Assert:
          rule-specific intrinsic function: Value
        AssertDescription: Information about this assert
      - Assert:
          rule-specific intrinsic function: Value
        AssertDescription: Information about this assert
  LogicalRuleName2:
    Assertions:
      - Assert:
          rule-specific intrinsic function: Value
        AssertDescription: Information about this assert
```

### 규칙 필드
<a name="rules-section-fields"></a>

`Rules` 섹션은 다음 필드를 포함할 수 있습니다.

**논리적 ID(**논리명이라고도 함)**  
각 규칙의 고유 식별자입니다.

**`RuleCondition` (선택 사항)**  
규칙이 언제 적용될지 결정하는 속성입니다. 규칙 조건을 정의하지 않은 경우, 규칙의 어설션이 항상 적용됩니다. 각 규칙은 하나의 규칙 조건만 정의할 수 있습니다.

**`Assertions`(필수)**  
특정 파라미터에 대해 허용되는 값을 지정하는 하나 이상의 문입니다.

**`Assert`**  
반드시 `true`로 평가되는 조건입니다.

**`AssertDescription`**  
어설션 실패 시 표시되는 메시지입니다.

## 규칙별 내장 함수
<a name="rules-specific-intrinsic-section-structure"></a>

규칙을 정의하려면 템플릿의 `Rules` 섹션에서만 사용할 수 있는 함수인 *규칙 관련 함수*를 사용해야 합니다. 이러한 함수는 중첩될 수 있지만, 규칙 조건 또는 어설션의 최종 결과가 `true`이거나 `false`이어야 합니다.

다음과 같은 규칙 함수를 사용할 수 있습니다.
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-and](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-and)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-contains](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-contains)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-eachmemberequals](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-eachmemberequals)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-eachmemberin](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-eachmemberin)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-equals](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-equals)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-not](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-not)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-or](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-or)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-refall](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-refall)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-valueof](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-valueof)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-valueofall](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-rules.html#fn-valueofall)

이러한 함수는 규칙의 조건 또는 어설션에서 사용합니다. 이 조건 속성은 CloudFormation이 어설션을 적용할지 여부를 결정합니다. 조건이 `true`로 평가되면 CloudFormation은 프로비저닝된 제품이 생성되거나 업데이트될 때 파라미터 값이 유효한지 여부를 확인하기 위해 어설션을 평가합니다. 파라미터 값이 유효하지 않으면 CloudFormation은 스택을 생성하거나 업데이트하지 않습니다. 조건이 `false`로 평가되면 CloudFormation은 파라미터 값을 확인하지 않고 스택 작업을 진행합니다.

## 예제
<a name="template-constraint-rules-example"></a>

**Topics**
+ [조건부로 파라미터 값 확인](#template-constraint-rules-example-verify)
+ [파라미터 간 검증](#template-cross-parameter-rules-example)

### 조건부로 파라미터 값 확인
<a name="template-constraint-rules-example-verify"></a>

다음 예제에서는 규칙 두 개가 `InstanceType` 파라미터의 값을 검사합니다. 환경 파라미터(`test` 또는 `prod`)의 값에 따라 사용자는 `InstanceType` 파라미터에 대해 `t3.medium` 또는 `t3.large`를 지정해야 합니다. `InstanceType` 및 `Environment` 파라미터는 동일한 템플릿의 `Parameters` 섹션에서 선언해야 합니다.

#### JSON
<a name="rules-section-example-conditionally-verify.json"></a>

```
{
  "Rules": {
    "testInstanceType": {
      "RuleCondition": {
        "Fn::Equals": [
          {"Ref": "Environment"},
          "test"
        ]
      },
      "Assertions": [
        {
          "Assert": {
            "Fn::Contains": [
              ["t3.medium"],
              {"Ref": "InstanceType"}
            ]
          },
          "AssertDescription": "For a test environment, the instance type must be t3.medium"
        }
      ]
    },
    "prodInstanceType": {
      "RuleCondition": {
        "Fn::Equals": [
          {"Ref": "Environment"},
          "prod"
        ]
      },
      "Assertions": [
        {
          "Assert": {
            "Fn::Contains": [
              ["t3.large"],
              {"Ref": "InstanceType"}
            ]
          },
          "AssertDescription": "For a production environment, the instance type must be t3.large"
        }
      ]
    }
  }
}
```

#### YAML
<a name="rules-section-example-conditionally-verify.yaml"></a>

```
Rules:
  testInstanceType:
    RuleCondition: !Equals 
      - !Ref Environment
      - test
    Assertions:
      - Assert:
          'Fn::Contains':
            - - t3.medium
            - !Ref InstanceType
        AssertDescription: 'For a test environment, the instance type must be t3.medium'
  prodInstanceType:
    RuleCondition: !Equals 
      - !Ref Environment
      - prod
    Assertions:
      - Assert:
          'Fn::Contains':
            - - t3.large
            - !Ref InstanceType
        AssertDescription: 'For a production environment, the instance type must be t3.large'
```

### 파라미터 간 검증
<a name="template-cross-parameter-rules-example"></a>

다음 샘플 템플릿은 파라미터 간 검증을 위한 규칙의 사용을 보여줍니다. 이는 로드 밸런서 뒤의 Auto Scaling 그룹에서 실행되는 샘플 웹 사이트를 생성합니다. 웹 사이트는 입력 파라미터에 따라 포트 80 또는 443에서 사용할 수 있습니다. Auto Scaling 그룹의 인스턴스가 모든 포트(기본값 8888)에서 수신되도록 구성할 수 있습니다.

이 템플릿의 규칙은 스택 생성 전에 입력 파라미터를 검증합니다. 모든 서브넷이 지정된 VPC에 속하는지 검증하고 `UseSSL` 파라미터가 `Yes`로 설정된 경우, SSL 인증서 ARN과 호스팅 영역 이름이 모두 제공되는지 확인합니다.

**참고**  
이 템플릿에서 스택을 생성할 경우 사용한 AWS 리소스에 대한 요금이 청구됩니다.

#### JSON
<a name="rules-section-example-cross-parameter-validation.json"></a>

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "VpcId": {
      "Type": "AWS::EC2::VPC::Id",
      "Description": "VpcId of your existing Virtual Private Cloud (VPC)",
      "ConstraintDescription": "must be the VPC Id of an existing Virtual Private Cloud."
    },
    "Subnets": {
      "Type": "List<AWS::EC2::Subnet::Id>",
      "Description": "The list of SubnetIds in your Virtual Private Cloud (VPC)",
      "ConstraintDescription": "must be a list of at least two existing subnets associated with at least two different availability zones."
    },
    "InstanceType": {
      "Description": "WebServer EC2 instance type",
      "Type": "String",
      "Default": "t2.micro",
      "AllowedValues": ["t2.micro", "t3.micro"],
      "ConstraintDescription": "must be a valid EC2 instance type."
    },
    "KeyName": {
      "Description": "Name of an existing EC2 KeyPair to enable SSH access to the instances",
      "Type": "AWS::EC2::KeyPair::KeyName",
      "ConstraintDescription": "must be the name of an existing EC2 KeyPair."
    },
    "SSHLocation": {
      "Description": "The IP address range that can be used to SSH to the EC2 instances",
      "Type": "String",
      "MinLength": "9",
      "MaxLength": "18",
      "Default": "0.0.0.0/0",
      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
      "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
    },
    "UseSSL": {
      "AllowedValues": ["Yes", "No"],
      "Default": "No",
      "Description": "Select \"Yes\" to implement SSL, \"No\" to skip (default).",
      "Type": "String"
    },
    "ALBSSLCertificateARN": {
      "Default": "",
      "Description": "[Optional] The ARN of the SSL certificate to be used for the Application Load Balancer",
      "Type": "String"
    },
    "HostedZoneName": {
      "AllowedPattern": "^$|(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$",
      "Default": "",
      "Description": "[Optional] The domain name of a valid Hosted Zone on AWS.",
      "Type": "String"
    }
  },
  "Conditions": {
    "UseALBSSL": {"Fn::Equals": [{"Ref": "UseSSL"}, "Yes"]}
  },
  "Rules": {
    "SubnetsInVPC": {
      "Assertions": [
        {
          "Assert": {"Fn::EachMemberEquals": [{"Fn::ValueOf": ["Subnets", "VpcId"]}, {"Ref": "VpcId"}]},
          "AssertDescription": "All subnets must be in the VPC"
        }
      ]
    },
    "ValidateHostedZone": {
      "RuleCondition": {"Fn::Equals": [{"Ref": "UseSSL"}, "Yes"]},
      "Assertions": [
        {
          "Assert": {"Fn::Not": [{"Fn::Equals": [{"Ref": "ALBSSLCertificateARN"}, ""]}]},
          "AssertDescription": "ACM Certificate value cannot be empty if SSL is required"
        },
        {
          "Assert": {"Fn::Not": [{"Fn::Equals": [{"Ref": "HostedZoneName"}, ""]}]},
          "AssertDescription": "Route53 Hosted Zone Name is mandatory when SSL is required"
        }
      ]
    }
  },
  "Resources": {
    "WebServerGroup": {
      "Type": "AWS::AutoScaling::AutoScalingGroup",
      "Properties": {
        "VPCZoneIdentifier": {"Ref": "Subnets"},
        "LaunchTemplate": {
          "LaunchTemplateId": {"Ref": "LaunchTemplate"},
          "Version": {"Fn::GetAtt": ["LaunchTemplate","LatestVersionNumber"]}
        },
        "MinSize": "2",
        "MaxSize": "2",
        "TargetGroupARNs": [{"Ref": "ALBTargetGroup"}]
      },
      "CreationPolicy": {
        "ResourceSignal": {"Timeout": "PT15M"}
      },
      "UpdatePolicy": {
        "AutoScalingRollingUpdate": {
          "MinInstancesInService": "1",
          "MaxBatchSize": "1",
          "PauseTime": "PT15M",
          "WaitOnResourceSignals": true
        }
      }
    },
    "LaunchTemplate": {
      "Type": "AWS::EC2::LaunchTemplate",
      "Metadata": {
        "Comment": "Install a simple application",
        "AWS::CloudFormation::Init": {
          "config": {
            "packages": {"yum": {"httpd": []}},
            "files": {
              "/var/www/html/index.html": {
                "content": {"Fn::Join": ["\n", ["<h1>Congratulations, you have successfully launched the AWS CloudFormation sample.</h1>"]]},
                "mode": "000644",
                "owner": "root",
                "group": "root"
              },
              "/etc/cfn/cfn-hup.conf": {
                "content": {"Fn::Join": ["", [
                  "[main]\n",
                  "stack=", {"Ref": "AWS::StackId"}, "\n",
                  "region=", {"Ref": "AWS::Region"}, "\n"
                ]]},
                "mode": "000400",
                "owner": "root",
                "group": "root"
              },
              "/etc/cfn/hooks.d/cfn-auto-reloader.conf": {
                "content": {"Fn::Join": ["", [
                  "[cfn-auto-reloader-hook]\n",
                  "triggers=post.update\n",
                  "path=Resources.LaunchTemplate.Metadata.AWS::CloudFormation::Init\n",
                  "action=/opt/aws/bin/cfn-init -v ",
                  "         --stack ", {"Ref": "AWS::StackName"},
                  "         --resource LaunchTemplate ",
                  "         --region ", {"Ref": "AWS::Region"}, "\n",
                  "runas=root\n"
                ]]},
                "mode": "000400",
                "owner": "root",
                "group": "root"
              }
            },
            "services": {
              "sysvinit": {
                "httpd": {
                  "enabled": "true",
                  "ensureRunning": "true"
                },
                "cfn-hup": {
                  "enabled": "true",
                  "ensureRunning": "true",
                  "files": [
                    "/etc/cfn/cfn-hup.conf",
                    "/etc/cfn/hooks.d/cfn-auto-reloader.conf"
                  ]
                }
              }
            }
          }
        }
      },
      "Properties": {
        "LaunchTemplateName": {"Fn::Sub": "${AWS::StackName}-launch-template"},
        "LaunchTemplateData": {
          "ImageId": "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}",
          "SecurityGroupIds": [{"Ref": "InstanceSecurityGroup"}],
          "InstanceType": {"Ref": "InstanceType"},
          "KeyName": {"Ref": "KeyName"},
          "UserData": {
            "Fn::Base64": {"Fn::Join": ["", [
              "#!/bin/bash\n",
              "yum install -y aws-cfn-bootstrap\n",
              "/opt/aws/bin/cfn-init -v ",
              "         --stack ", {"Ref": "AWS::StackName"},
              "         --resource LaunchTemplate ",
              "         --region ", {"Ref": "AWS::Region"}, "\n",
              "/opt/aws/bin/cfn-signal -e $? ",
              "         --stack ", {"Ref": "AWS::StackName"},
              "         --resource WebServerGroup ",
              "         --region ", {"Ref": "AWS::Region"}, "\n"
            ]]}
          }
        }
      }
    },
    "ELBSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "Allow access to the ELB",
        "VpcId": {"Ref": "VpcId"},
        "SecurityGroupIngress": [{
          "Fn::If": [
            "UseALBSSL",
            {
              "IpProtocol": "tcp",
              "FromPort": 443,
              "ToPort": 443,
              "CidrIp": "0.0.0.0/0"
            },
            {
              "IpProtocol": "tcp",
              "FromPort": 80,
              "ToPort": 80,
              "CidrIp": "0.0.0.0/0"
            }
          ]
        }]
      }
    },
    "ApplicationLoadBalancer": {
      "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
      "Properties": {
        "Subnets": {"Ref": "Subnets"},
        "SecurityGroups": [{"Ref": "ELBSecurityGroup"}]
      }
    },
    "ALBListener": {
      "Type": "AWS::ElasticLoadBalancingV2::Listener",
      "Properties": {
        "DefaultActions": [{
          "Type": "forward",
          "TargetGroupArn": {"Ref": "ALBTargetGroup"}
        }],
        "LoadBalancerArn": {"Ref": "ApplicationLoadBalancer"},
        "Port": {"Fn::If": ["UseALBSSL", 443, 80]},
        "Protocol": {"Fn::If": ["UseALBSSL", "HTTPS", "HTTP"]},
        "Certificates": [{
          "Fn::If": [
            "UseALBSSL",
            {"CertificateArn": {"Ref": "ALBSSLCertificateARN"}},
            {"Ref": "AWS::NoValue"}
          ]
        }]
      }
    },
    "ALBTargetGroup": {
      "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
      "Properties": {
        "HealthCheckIntervalSeconds": 30,
        "HealthCheckTimeoutSeconds": 5,
        "HealthyThresholdCount": 3,
        "Port": 80,
        "Protocol": "HTTP",
        "UnhealthyThresholdCount": 5,
        "VpcId": {"Ref": "VpcId"}
      }
    },
    "InstanceSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "Enable SSH access and HTTP access on the inbound port",
        "SecurityGroupIngress": [
          {
            "IpProtocol": "tcp",
            "FromPort": 80,
            "ToPort": 80,
            "SourceSecurityGroupId": {"Fn::Select": [0, {"Fn::GetAtt": ["ApplicationLoadBalancer", "SecurityGroups"]}]}
          },
          {
            "IpProtocol": "tcp",
            "FromPort": 22,
            "ToPort": 22,
            "CidrIp": {"Ref": "SSHLocation"}
          }
        ],
        "VpcId": {"Ref": "VpcId"}
      }
    },
    "RecordSet": {
      "Type": "AWS::Route53::RecordSetGroup",
      "Condition": "UseALBSSL",
      "Properties": {
        "HostedZoneName": {"Fn::Join": ["", [{"Ref": "HostedZoneName"}, "."]]},
        "RecordSets": [{
          "Name": {"Fn::Join": ["", [
            {"Fn::Select": ["0", {"Fn::Split": [".", {"Fn::GetAtt": ["ApplicationLoadBalancer", "DNSName"]}]}]},
            ".",
            {"Ref": "HostedZoneName"},
            "."
          ]]},
          "Type": "A",
          "AliasTarget": {
            "DNSName": {"Fn::GetAtt": ["ApplicationLoadBalancer", "DNSName"]},
            "EvaluateTargetHealth": true,
            "HostedZoneId": {"Fn::GetAtt": ["ApplicationLoadBalancer", "CanonicalHostedZoneID"]}
          }
        }]
      }
    }
  },
  "Outputs": {
    "URL": {
      "Description": "URL of the website",
      "Value": {"Fn::Join": ["", [
        {"Fn::If": [
          "UseALBSSL",
          {"Fn::Join": ["", [
            "https://",
            {"Fn::Join": ["", [
              {"Fn::Select": ["0", {"Fn::Split": [".", {"Fn::GetAtt": ["ApplicationLoadBalancer", "DNSName"]}]}]},
              ".",
              {"Ref": "HostedZoneName"},
              "."
            ]]}
          ]]},
          {"Fn::Join": ["", [
            "http://",
            {"Fn::GetAtt": ["ApplicationLoadBalancer", "DNSName"]}
          ]]}
        ]}
      ]]}
    }
  }
}
```

#### YAML
<a name="rules-section-example-syntax.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: VpcId of your existing Virtual Private Cloud (VPC)
    ConstraintDescription: must be the VPC Id of an existing Virtual Private Cloud.
  Subnets:
    Type: List<AWS::EC2::Subnet::Id>
    Description: The list of SubnetIds in your Virtual Private Cloud (VPC)
    ConstraintDescription: >-
      must be a list of at least two existing subnets associated with at least
      two different availability zones. They should be residing in the selected
      Virtual Private Cloud.
  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: t2.micro
    AllowedValues:
      - t2.micro
      - t3.micro
    ConstraintDescription: must be a valid EC2 instance type.
  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instances
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: must be the name of an existing EC2 KeyPair.
  SSHLocation:
    Description: The IP address range that can be used to SSH to the EC2 instances
    Type: String
    MinLength: '9'
    MaxLength: '18'
    Default: 0.0.0.0/0
    AllowedPattern: '(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})'
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
  UseSSL:
    AllowedValues:
      - 'Yes'
      - 'No'
    ConstraintDescription: Select Yes to create a HTTPS Listener
    Default: 'No'
    Description: 'Select "Yes" to implement SSL, "No" to skip (default).'
    Type: String
  ALBSSLCertificateARN:
    Default: ''
    Description: >-
      [Optional] The ARN of the SSL certificate to be used for the Application
      Load Balancer
    Type: String
  HostedZoneName:
    AllowedPattern: >-
      ^$|(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$
    Default: ''
    Description: '[Optional] The domain name of a valid Hosted Zone on AWS.'
    Type: String
Conditions:
  UseALBSSL: !Equals 
    - !Ref UseSSL
    - 'Yes'
Rules:
  SubnetsInVPC:
    Assertions:
      - Assert:
          'Fn::EachMemberEquals':
            - 'Fn::ValueOf':
                - Subnets
                - VpcId
            - Ref: VpcId
        AssertDescription: All subnets must be in the VPC
  ValidateHostedZone:
    RuleCondition: !Equals 
      - !Ref UseSSL
      - 'Yes'
    Assertions:
      - Assert: !Not 
          - !Equals 
            - !Ref ALBSSLCertificateARN
            - ''
        AssertDescription: ACM Certificate value cannot be empty if SSL is required
      - Assert: !Not 
          - !Equals 
            - !Ref HostedZoneName
            - ''
        AssertDescription: Route53 Hosted Zone Name is mandatory when SSL is required
Resources:
  WebServerGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      VPCZoneIdentifier: !Ref Subnets
      LaunchTemplate:
        LaunchTemplateId: !Ref LaunchTemplate
        Version: !GetAtt LaunchTemplate.LatestVersionNumber
      MinSize: '2'
      MaxSize: '2'
      TargetGroupARNs:
        - !Ref ALBTargetGroup
    CreationPolicy:
      ResourceSignal:
        Timeout: PT15M
    UpdatePolicy:
      AutoScalingRollingUpdate:
        MinInstancesInService: '1'
        MaxBatchSize: '1'
        PauseTime: PT15M
        WaitOnResourceSignals: 'true'
  LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Metadata:
      Comment: Install a simple application
      AWS::CloudFormation::Init:
        config:
          packages:
            yum:
              httpd: []
          files:
            /var/www/html/index.html:
              content: !Join 
                - |+
                - - >-
                    <h1>Congratulations, you have successfully launched the AWS
                    CloudFormation sample.</h1>
              mode: '000644'
              owner: root
              group: root
            /etc/cfn/cfn-hup.conf:
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
              mode: '000400'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:
              content: !Sub |-
                [cfn-auto-reloader-hook]
                triggers=post.update
                path=Resources.LaunchTemplate.Metadata.AWS::CloudFormation::Init
                action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchTemplate --region ${AWS::Region}
                runas=root
              mode: '000400'
              owner: root
              group: root
          services:
            sysvinit:
              httpd:
                enabled: 'true'
                ensureRunning: 'true'
              cfn-hup:
                enabled: 'true'
                ensureRunning: 'true'
                files:
                  - /etc/cfn/cfn-hup.conf
                  - /etc/cfn/hooks.d/cfn-auto-reloader.conf
    Properties:
      LaunchTemplateName: !Sub ${AWS::StackName}-launch-template
      LaunchTemplateData:
        ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
        SecurityGroupIds:
        - !Ref InstanceSecurityGroup
        InstanceType: !Ref InstanceType
        KeyName: !Ref KeyName
        UserData: !Base64
          Fn::Sub: |
            #!/bin/bash
            yum install -y aws-cfn-bootstrap
            /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchTemplate --region ${AWS::Region}
            /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerGroup --region ${AWS::Region}
  ELBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow access to the ELB
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - !If 
          - UseALBSSL
          - IpProtocol: tcp
            FromPort: 443
            ToPort: 443
            CidrIp: 0.0.0.0/0
          - IpProtocol: tcp
            FromPort: 80
            ToPort: 80
            CidrIp: 0.0.0.0/0
  ApplicationLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Subnets: !Ref Subnets
      SecurityGroups:
        - !Ref ELBSecurityGroup
  ALBListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref ALBTargetGroup
      LoadBalancerArn: !Ref ApplicationLoadBalancer
      Port: !If
        - UseALBSSL
        - 443
        - 80
      Protocol: !If 
        - UseALBSSL
        - HTTPS
        - HTTP
      Certificates:
        - !If 
          - UseALBSSL
          - CertificateArn: !Ref ALBSSLCertificateARN
          - !Ref 'AWS::NoValue'
  ALBTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 30
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 3
      Port: 80
      Protocol: HTTP
      UnhealthyThresholdCount: 5
      VpcId: !Ref VpcId
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable SSH access and HTTP access on the inbound port
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          SourceSecurityGroupId: !Select 
            - 0
            - !GetAtt 
              - ApplicationLoadBalancer
              - SecurityGroups
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref SSHLocation
      VpcId: !Ref VpcId
  RecordSet:
    Type: AWS::Route53::RecordSetGroup
    Condition: UseALBSSL
    Properties:
      HostedZoneName: !Join 
        - ''
        - - !Ref HostedZoneName
          - .
      RecordSets:
        - Name: !Join 
            - ''
            - - !Select 
                - '0'
                - !Split 
                  - .
                  - !GetAtt 
                    - ApplicationLoadBalancer
                    - DNSName
              - .
              - !Ref HostedZoneName
              - .
          Type: A
          AliasTarget:
            DNSName: !GetAtt 
              - ApplicationLoadBalancer
              - DNSName
            EvaluateTargetHealth: true
            HostedZoneId: !GetAtt 
              - ApplicationLoadBalancer
              - CanonicalHostedZoneID
Outputs:
  URL:
    Description: URL of the website
    Value: !Join 
      - ''
      - - !If 
          - UseALBSSL
          - !Join 
            - ''
            - - 'https://'
              - !Join 
                - ''
                - - !Select 
                    - '0'
                    - !Split 
                      - .
                      - !GetAtt 
                        - ApplicationLoadBalancer
                        - DNSName
                  - .
                  - !Ref HostedZoneName
                  - .
          - !Join 
            - ''
            - - 'http://'
              - !GetAtt 
                - ApplicationLoadBalancer
                - DNSName
```

# CloudFormation 템플릿 Conditions 구문
<a name="conditions-section-structure"></a>

`Conditions` 섹션(선택 사항)에는 엔터티가 생성 또는 구성된 환경을 정의하는 문이 포함되어 있습니다. 예를 들어 조건을 생성하고 이를 리소스 또는 출력에 연결하여 조건이 true인 경우에만 CloudFormation에서 리소스 또는 출력을 생성하도록 할 수 있습니다. 이와 유사하게 조건을 속성에 연결하여 조건이 true인 경우에만 CloudFormation에서 속성을 특정 값으로 설정하도록 할 수 있습니다. 조건이 false인 경우 CloudFormation에서 사용자가 지정한 대체 값으로 속성을 설정합니다.

다양한 컨텍스트(예: 테스트 환경과 프로덕션 환경)에서 리소스를 생성하는 데 템플릿을 재사용하려는 경우에 조건을 사용할 수 있습니다. 예를 들어 템플릿에서 `prod` 또는 `test`를 입력으로 수락하는 `EnvironmentType` 입력 파라미터를 추가할 수 있습니다. `prod` 환경에서는 특정 기능을 가진 EC2 인스턴스를 포함할 수 있지만, `test` 환경에서는 비용 절감을 위해 더 적은 기능을 사용하려고 합니다. 이 조건 정의를 통해, 생성되는 리소스와 각 환경 유형에 대한 리소스 구성 방법을 정의할 수 있습니다.

## 구문
<a name="conditions-section-structure-syntax"></a>

`Conditions` 섹션은 키 이름 `Conditions`로 이루어집니다. 각 조건 선언에는 논리적 ID와 하나 이상의 내장 함수가 포함됩니다.

### JSON
<a name="conditions-section-structure-syntax.json"></a>

```
"Conditions": {
  "LogicalConditionName1": {
    "Intrinsic function": ...[
  },

  "LogicalConditionName2": {
    "Intrinsic function": ...
  }
}
```

### YAML
<a name="conditions-section-structure-syntax.yaml"></a>

```
Conditions:
  LogicalConditionName1:
    Intrinsic function:
      ...

  LogicalConditionName2:
    Intrinsic function:
      ...
```

## 조건 작동 방식
<a name="conditions-section-structure-overview"></a>

조건을 사용하려면 다음 단계를 따릅니다.

1. **파라미터 정의 추가** - 템플릿의 `Parameters` 섹션에서 조건을 사용하여 평가할 입력을 정의합니다. 조건은 이러한 입력 파라미터의 값에 따라 true 또는 false로 평가합니다. 가상 파라미터는 자동으로 제공되며 `Parameters` 섹션에 명시적으로 정의할 필요가 없습니다. 가상 parameters에 대한 자세한 내용은 [가상 파라미터를 사용하여 AWS 값 가져오기](pseudo-parameter-reference.md) 단원을 참조하십시오.

1. **조건 정의 추가** - `Fn::If`, `Fn::Equals`와 같은 내장 함수를 사용하여 `Conditions` 섹션에 조건을 정의합니다. 이러한 조건은 CloudFormation에서 연결된 리소스가 생성되는 경우를 결정합니다. 조건은 다음을 기준으로 할 수 있습니다.
   + 입력 또는 가상 파라미터 값
   + 기타 조건
   + 매핑 값

   그러나 조건에서 리소스 논리적 ID 또는 해당 속성을 참조할 수 없습니다.

1. **조건을 리소스 또는 출력과 연결** - `Condition` 키와 조건의 논리적 ID를 사용하여 리소스 또는 출력에서 조건을 참조합니다. 필요한 경우, 템플릿의 다른 부분(예: 속성 값)에 `Fn::If`을 사용하여 조건을 기준으로 값을 설정할 수 있습니다. 자세한 내용은 [`Condition` 키 사용](#using-conditions-in-templates) 섹션을 참조하세요.

CloudFormation은 스택을 생성하거나 업데이트할 때 조건을 평가합니다. CloudFormation에서는 true 조건과 연결된 엔터티를 생성하고 false 조건과 연결된 엔터티를 무시합니다. 또한 CloudFormation은 리소스를 수정하기 전에 각 스택 업데이트 시에 이러한 조건을 다시 평가합니다. true 조건과 연결된 상태로 남아 있는 엔터티는 업데이트되고, false 조건과 연결되는 엔터티는 삭제됩니다.

**중요**  
스택 업데이트 중에는 조건을 자체적으로 업데이트할 수 없습니다. 조건은 리소스를 추가, 수정 또는 삭제하는 변경 내용을 포함할 때만 업데이트할 수 있습니다.

## 조건 내장 함수
<a name="conditions-section-structure-functions"></a>

다음 내장 함수를 사용하여 조건을 정의할 수 있습니다.
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-and](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-and)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-equals](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-equals)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-foreach.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-foreach.html)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-not](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-not)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-or](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-or)

**참고**  
템플릿의 `Resources` 섹션과 `Outputs` 섹션에 있는 메타데이터 속성, 업데이트 정책 속성 및 속성값에서만 `Fn::If`가 지원됩니다.

## `Condition` 키 사용
<a name="using-conditions-in-templates"></a>

조건이 정의되면 `Condition` 키를 사용하여 `Resources`, `Outputs` 등 템플릿의 여러 위치에 조건을 적용할 수 있습니다. `Condition` 키는 조건의 논리명을 참조하고 지정된 조건의 평가된 결과를 반환합니다.

**Topics**
+ [조건을 리소스와 연결](#associate-conditions-with-resources)
+ [조건을 출력과 연결](#associate-conditions-with-outputs)
+ [다른 조건의 조건 참조](#reference-conditions-in-other-conditions)
+ [`Fn::If`를 사용하여 조건부로 속성 값 반환](#conditional-return-property-values-using-fn-if)

### 조건을 리소스와 연결
<a name="associate-conditions-with-resources"></a>

리소스를 조건부로 생성하려면 조건의 `Condition` 키와 논리적 ID를 리소스에 속성으로 추가합니다. CloudFormation은 조건이 true로 평가될 때만 리소스를 생성합니다.

#### JSON
<a name="associate-conditions-with-resources.json"></a>

```
"NewVolume" : {
  "Type" : "AWS::EC2::Volume",
  "Condition" : "IsProduction",
  "Properties" : {
     "Size" : "100",
     "AvailabilityZone" : { "Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone" ]}
  }
}
```

#### YAML
<a name="associate-conditions-with-resources.yaml"></a>

```
NewVolume:
  Type: AWS::EC2::Volume
  Condition: IsProduction
  Properties:
    Size: 100
    AvailabilityZone: !GetAtt EC2Instance.AvailabilityZone
```

### 조건을 출력과 연결
<a name="associate-conditions-with-outputs"></a>

조건을 출력과 연결할 수도 있습니다. CloudFormation은 연결된 조건이 true로 평가될 때만 출력을 생성합니다.

#### JSON
<a name="associate-conditions-with-outputs.json"></a>

```
"Outputs" : {
  "VolumeId" : {
    "Condition" : "IsProduction",
    "Value" : { "Ref" : "NewVolume" }
  }
}
```

#### YAML
<a name="associate-conditions-with-outputs.yaml"></a>

```
Outputs:
  VolumeId:
    Condition: IsProduction
    Value: !Ref NewVolume
```

### 다른 조건의 조건 참조
<a name="reference-conditions-in-other-conditions"></a>

`Conditions` 섹션에서 조건을 정의할 때 `Condition` 키를 사용하여 다른 조건을 참조할 수 있습니다. 이를 통해 여러 조건을 결합하여 더 복잡한 조건부 로직을 생성할 수 있습니다.

다음 예제에서 `IsProdAndFeatureEnabled` 조건은 `IsProduction` 및 `IsFeatureEnabled` 조건이 true로 평가되는 경우에만 true로 평가됩니다.

#### JSON
<a name="reference-conditions-in-other-conditions.json"></a>

```
"Conditions": {
  "IsProduction" : {"Fn::Equals" : [{"Ref" : "Environment"}, "prod"]},
  "IsFeatureEnabled" : { "Fn::Equals" : [{"Ref" : "FeatureFlag"}, "enabled"]},
  "IsProdAndFeatureEnabled" : {
    "Fn::And" : [
      {"Condition" : "IsProduction"},
      {"Condition" : "IsFeatureEnabled"}
    ]
  }
}
```

#### YAML
<a name="reference-conditions-in-other-conditions.yaml"></a>

```
Conditions:
  IsProduction:
    !Equals [!Ref Environment, "prod"]
  IsFeatureEnabled:
    !Equals [!Ref FeatureFlag, "enabled"]
  IsProdAndFeatureEnabled: !And
    - !Condition IsProduction
    - !Condition IsFeatureEnabled
```

### `Fn::If`를 사용하여 조건부로 속성 값 반환
<a name="conditional-return-property-values-using-fn-if"></a>

더 세분화된 제어를 위해 `Fn::If` 내장 함수를 사용하여 리소스 또는 출력 내에서 두 속성 값 중 하나를 조건부로 반환할 수 있습니다. 이 함수는 조건을 평가하고 조건이 true인 경우 하나의 값을 반환하고, 조건이 false인 경우 다른 값을 반환합니다.

#### 조건부 속성 값
<a name="using-fn-if-for-conditional-values"></a>

다음 예제에서는 환경 조건을 기반으로 EC2 인스턴스 유형을 설정하는 방법을 보여줍니다. `IsProduction` 조건이 true로 평가되면 인스턴스 유형이 `c5.xlarge`로 설정됩니다. 그렇지 않으면 `t3.small`로 설정됩니다.

##### JSON
<a name="using-fn-if-for-conditional-values.json"></a>

```
"Properties" : {
  "InstanceType" : {
    "Fn::If" : [
      "IsProduction",
      "c5.xlarge",
      "t3.small"
    ]
  }
}
```

##### YAML
<a name="using-fn-if-for-conditional-values.yaml"></a>

```
Properties:
  InstanceType: !If
    - IsProduction
    - c5.xlarge
    - t3.small
```

#### 조건부 속성 제거
<a name="using-fn-if-with-novalue"></a>

또한 `AWS::NoValue` 가상 파라미터를 반환 값으로 사용하여 조건이 false인 경우 해당 속성을 제거할 수 있습니다.

##### JSON
<a name="using-fn-if-with-novalue.json"></a>

```
"DBSnapshotIdentifier" : {
  "Fn::If" : [
    "UseDBSnapshot",
    {"Ref" : "DBSnapshotName"},
    {"Ref" : "AWS::NoValue"}
  ]
}
```

##### YAML
<a name="using-fn-if-with-novalue.yaml"></a>

```
DBSnapshotIdentifier: !If
  - UseDBSnapshot
  - !Ref DBSnapshotName
  - !Ref "AWS::NoValue"
```

## 예제
<a name="conditions-section-structure-examples"></a>

**Topics**
+ [환경 기반 리소스 생성](#environment-based-resource-creation)
+ [다중 조건 리소스 프로비저닝](#multi-condition-resource-provisioning)

### 환경 기반 리소스 생성
<a name="environment-based-resource-creation"></a>

다음 예에서는 EC2 인스턴스를 프로비저닝하고, 환경 유형이 `prod`인 경우에만 새 EBS 볼륨을 조건부로 생성 및 연결합니다. 환경이 `test`인 경우에는 추가 볼륨 없이 EC2 인스턴스만 생성합니다.

#### JSON
<a name="conditions-section-example-resource-creation.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "EnvType": {
            "Description": "Environment type",
            "Default": "test",
            "Type": "String",
            "AllowedValues": [
                "prod",
                "test"
            ],
            "ConstraintDescription": "must specify prod or test"
        }
    },
    "Conditions": {
        "IsProduction": {
            "Fn::Equals": [
                {
                    "Ref": "EnvType"
                },
                "prod"
            ]
        }
    },
    "Resources": {
        "EC2Instance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "ImageId": "ami-1234567890abcdef0",
                "InstanceType": "c5.xlarge"
            }
        },
        "MountPoint": {
            "Type": "AWS::EC2::VolumeAttachment",
            "Condition": "IsProduction",
            "Properties": {
                "InstanceId": {
                    "Ref": "EC2Instance"
                },
                "VolumeId": {
                    "Ref": "NewVolume"
                },
                "Device": "/dev/sdh"
            }
        },
        "NewVolume": {
            "Type": "AWS::EC2::Volume",
            "Condition": "IsProduction",
            "Properties": {
                "Size": 100,
                "AvailabilityZone": {
                    "Fn::GetAtt": [
                        "EC2Instance",
                        "AvailabilityZone"
                    ]
                }
            }
        }
    }
}
```

#### YAML
<a name="conditions-section-example-resource-creation.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  EnvType:
    Description: Environment type
    Default: test
    Type: String
    AllowedValues:
      - prod
      - test
    ConstraintDescription: must specify prod or test
Conditions:
  IsProduction: !Equals
    - !Ref EnvType
    - prod
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-1234567890abcdef0
      InstanceType: c5.xlarge
  MountPoint:
    Type: AWS::EC2::VolumeAttachment
    Condition: IsProduction
    Properties:
      InstanceId: !Ref EC2Instance
      VolumeId: !Ref NewVolume
      Device: /dev/sdh
  NewVolume:
    Type: AWS::EC2::Volume
    Condition: IsProduction
    Properties:
      Size: 100
      AvailabilityZone: !GetAtt
        - EC2Instance
        - AvailabilityZone
```

### 다중 조건 리소스 프로비저닝
<a name="multi-condition-resource-provisioning"></a>

다음 예에서는 버킷 이름이 제공된 경우 조건부로 S3 버킷을 생성하고, 환경이 `prod`로 설정된 경우에만 버킷 정책을 연결합니다. 버킷 이름이 지정되지 않았거나 환경이 `test`인 경우에는 리소스가 생성되지 않습니다.

#### JSON
<a name="conditions-section-example-multi-condition.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "EnvType": {
            "Type": "String",
            "AllowedValues": [
                "prod",
                "test"
            ]
        },
        "BucketName": {
            "Default": "",
            "Type": "String"
        }
    },
    "Conditions": {
        "IsProduction": {
            "Fn::Equals": [
                {
                    "Ref": "EnvType"
                },
                "prod"
            ]
        },
        "CreateBucket": {
            "Fn::Not": [
                {
                    "Fn::Equals": [
                        {
                            "Ref": "BucketName"
                        },
                        ""
                    ]
                }
            ]
        },
        "CreateBucketPolicy": {
            "Fn::And": [
                {
                    "Condition": "IsProduction"
                },
                {
                    "Condition": "CreateBucket"
                }
            ]
        }
    },
    "Resources": {
        "Bucket": {
            "Type": "AWS::S3::Bucket",
            "Condition": "CreateBucket",
            "Properties": {
                "BucketName": {
                    "Ref": "BucketName"
                }
            }
        },
        "Policy": {
            "Type": "AWS::S3::BucketPolicy",
            "Condition": "CreateBucketPolicy",
            "Properties": {
                "Bucket": {
                    "Ref": "Bucket"
                },
                "PolicyDocument": { ... }
            }
        }
    }
}
```

#### YAML
<a name="conditions-section-example-multi-condition.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  EnvType:
    Type: String
    AllowedValues:
      - prod
      - test
  BucketName:
    Default: ''
    Type: String
Conditions:
  IsProduction: !Equals
    - !Ref EnvType
    - prod
  CreateBucket: !Not
    - !Equals
      - !Ref BucketName
      - ''
  CreateBucketPolicy: !And
    - !Condition IsProduction
    - !Condition CreateBucket
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Condition: CreateBucket
    Properties:
      BucketName: !Ref BucketName
  Policy:
    Type: AWS::S3::BucketPolicy
    Condition: CreateBucketPolicy
    Properties:
      Bucket: !Ref Bucket
      PolicyDocument: ...
```

이 예제에서 `CreateBucketPolicy` 조건은 `Condition` 키를 사용하여 다른 조건을 참조하는 방법을 보여줍니다. 정책은 `IsProduction` 및 `CreateBucket` 조건이 모두 true로 평가되는 경우에만 생성됩니다.

**참고**  
더 복잡한 조건 사용 예제는 *CloudFormation 템플릿 참조 가이드*의 [Condition 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-condition.html) 주제를 참조하세요.

# CloudFormation 템플릿 Transform 섹션
<a name="transform-section-structure"></a>

선택 사항인 `Transform` 섹션은 CloudFormation에서 템플릿을 어떤 방식으로 처리하는 데 사용하는 하나 이상의 매크로를 지정합니다.

매크로는 텍스트 찾기 및 바꾸기와 같은 간단한 작업을 수행하거나 전체 템플릿을 보다 광범위하게 변환할 수 있습니다. CloudFormation은 지정된 순서에 따라 매크로를 실행합니다. 변경 세트를 생성할 때 CloudFormation에서 처리된 템플릿 콘텐츠를 포함하는 변경 세트를 생성합니다. 변경 사항을 검토하고 변경 세트를 실행할 수 있습니다. 매크로 작동 방식에 대한 자세한 내용은 [템플릿 매크로를 사용하여 CloudFormation 템플릿에서 사용자 지정 처리 수행](template-macros.md) 단원을 참조하세요.

CloudFormation은 CloudFormation에서 호스팅되는 매크로인 **변환도 지원합니다. CloudFormation은 이러한 변환을 실행 순서 및 범위 측면에서 사용자가 생성한 모든 매크로와 동일하게 처리합니다. 자세한 내용은 ​[변환 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/transform-reference.html)를 참조하세요.

여러 매크로를 선언하려면 목록 형식을 사용하고 하나 이상의 매크로를 지정합니다.

예를 들어, 아래 템플릿 샘플에서 CloudFormation은 `MyMacro`를 평가하고 `AWS::Serverless`를 평가합니다. 두 가지는 모두 전체 템플릿의 콘텐츠를 처리할 수 있는데, 이는 `Transform` 섹션이 포함되어 있기 때문입니다.

```
# Start of processable content for MyMacro and AWS::Serverless
Transform:
  - MyMacro
  - 'AWS::Serverless'
Resources:
  WaitCondition:
    Type: AWS::CloudFormation::WaitCondition
  MyBucket:
    Type: AWS::S3::Bucket
    Properties: 
      BucketName: amzn-s3-demo-bucket
      Tags: [{"key":"value"}]
      CorsConfiguration: []
  MyEc2Instance:
    Type: AWS::EC2::Instance 
    Properties:
      ImageId: ami-1234567890abcdef0
# End of processable content for MyMacro and AWS::Serverless
```

# CloudFormation 템플릿 형식 버전 구문
<a name="format-version-structure"></a>

`AWSTemplateFormatVersion` 섹션(선택 사항)은 템플릿이 따르는 템플릿 형식 버전을 식별합니다. 최신 템플릿 포맷 버전은 `2010-09-09`이며 현재 유일한 유효 값입니다.

템플릿 포맷 버전은 API 버전과 같지 않습니다. 템플릿 포맷 버전은 API 버전과 상관없이 변경될 수 있습니다.

템플릿 포맷 버전 선언 값은 리터럴 문자열이어야 합니다 파라미터나 함수를 사용하여 템플릿 포맷 버전을 지정할 수 없습니다. 값을 지정하지 않을 경우 CloudFormation에서는 최신 템플릿 포맷 버전이라고 가정합니다. 다음 코드 조각은 템플릿 포맷 버전 선언 예입니다.

## JSON
<a name="format-version-structure-example.json"></a>

```
"AWSTemplateFormatVersion" : "2010-09-09"
```

## YAML
<a name="format-version-structure-example.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
```

# CloudFormation 템플릿 Description 구문
<a name="template-description-structure"></a>

템플릿의 `Description` 섹션(선택 사항)을 사용하면 템플릿을 설명하는 텍스트 문자열을 포함시킬 수 있습니다. 이 섹션은 항상 템플릿 포맷 버전 섹션 다음에 이어져야 합니다.

설명 선언 값은 0 \$1 1023바이트 길이의 리터럴 문자열이어야 합니다. 파라미터나 함수를 사용하여 설명을 지정할 수 없습니다. 다음 코드 조각은 설명 선언을 보여주는 예입니다.

**중요**  
스택 업데이트 중에는 `Description` 섹션을 자체적으로 업데이트할 수 없습니다. 리소스를 추가, 수정 또는 삭제하는 변경 내용을 포함할 때만 업데이트할 수 있습니다.

## JSON
<a name="template-description-structure-example.json"></a>

```
"Description" : "Here are some details about the template."
```

## YAML
<a name="template-description-structure-example.yaml"></a>

```
Description: > Here are some details about the template.
```

# Infrastructure Composer를 사용하여 시각적으로 템플릿 생성
<a name="infrastructure-composer-for-cloudformation"></a>

AWS Infrastructure Composer(구 **Application Composer**)를 사용하면 AWS에서 최신 애플리케이션을 시각적으로 작성하고 구성할 수 있습니다. 코드를 작성할 필요없이 다양한 리소스를 끌어서 놓아 애플리케이션을 시각적으로 작성할 수 있습니다.

*CloudFormation 콘솔 모드의 Infrastructure Composer*는 시각적으로 CloudFormation 템플릿 작업을 하는 권장 도구입니다. CloudFormation 콘솔에서 액세스할 수 있는 이 Infrastructure Composer 버전은 CloudFormation Designer라는 이전 도구를 개선한 것입니다.

CloudFormation 콘솔 모드의 Infrastructure Composer를 사용하면 *카드*라는 다양한 리소스를 시각적 캔버스로 끌어서 놓고 구성하고 연결할 수 있습니다. 이 시각적 접근 방식을 사용하면 직접 템플릿으로 작업하지 않고도 애플리케이션 아키텍처를 쉽게 설계하고 편집할 수 있습니다. [CloudFormation 콘솔](https://console.aws.amazon.com/cloudformation/)에서 이 모드에 액세스하려면 왼쪽 탐색 메뉴에서 **Infrastructure Composer**를 선택합니다.

자세한 내용은 **AWS Infrastructure Composer 개발자 안내서의 [AWS Infrastructure Composer에서 구성하는 방법](https://docs.aws.amazon.com/infrastructure-composer/latest/dg/using-composer-basics.html)을 참조하세요.

## CloudFormation 콘솔 모드에서 Infrastructure Composer를 사용하는 이유는 무엇인가요?
<a name="app-composer-for-cloudformation-why-use"></a>

Infrastructure Composer에서 템플릿을 시각화하면 CloudFormation 템플릿과 애플리케이션 아키텍처의 격차와 개선 영역을 식별하는 데 도움이 됩니다. Infrastructure Composer를 사용하면 CloudFormation 스택을 쉽고 효율적이고 시각적으로 구축하고 수정할 수 있어 개발 경험이 향상됩니다. 초기 초안부터 시작하여 배포 가능한 코드를 생성하고 개발자 워크플로를 Infrastructure Composer의 비주얼 디자이너와 통합할 수 있습니다.

## 이 모드는 Infrastructure Composer 콘솔과 어떻게 다른가요?
<a name="app-composer-for-cloudformation-differences"></a>

CloudFormation 콘솔 버전의 Infrastructure Composer는 표준 Infrastructure Composer 콘솔과 기능이 유사하지만 몇 가지 차이점이 있습니다. Lambda 관련 카드(**Lambda 함수** 및 **Lambda 계층**)에는 CloudFormation 콘솔 모드의 Infrastructure Composer에서 사용할 수 없는 코드 빌드 및 패키징 솔루션이 필요합니다. 이 모드에서는 로컬 동기화도 사용할 수 없습니다.

하지만 [Infrastructure Composer 콘솔](https://console.aws.amazon.com/composer/home) 또는 AWS Toolkit for Visual Studio Code에서 이러한 Lambda 관련 카드와 로컬 동기화 기능을 사용할 수 있습니다. 자세한 내용은 [AWS Infrastructure Composer 개발자 안내서](https://docs.aws.amazon.com/infrastructure-composer/latest/dg/what-is-composer.html)와 *AWS Toolkit for Visual Studio Code 사용 설명서*의 [Infrastructure Composer](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/appcomposer.html)를 참조하세요.

# AWS CloudFormation 언어 서버
<a name="ide-extension"></a>

AWS CloudFormation 언어 서버는 코드형 인프라(IaC) 작성을 가속화하고 AWS 리소스를 안전하고 자신 있게 배포하는 기능을 제공합니다. [언어 서버 프로토콜](https://microsoft.github.io/language-server-protocol/)(LSP)에 따라 가리키기, 자동 완성, 정적 검증을 통한 진단에 대한 설명서를 제공하고 정의 및 코드 작업으로 이동합니다. 이러한 기존 언어 서버 기능 외에도 서버는 CloudFormation을 통해 AWS 리소스를 탐색 및 배포하는 온라인 기능을 추가합니다. 여기에는 변경 세트를 사용하여 템플릿을 검증 및 배포하고, 스택 차이, 이벤트, 리소스 및 출력을 보며, 스택을 나열하고 유형별로 리소스를 찾아보고, 라이브 리소스 상태를 CloudFormation 템플릿에 직접 삽입하는 기능이 포함됩니다.

**Topics**
+ [AWS CloudFormation 언어 서버와 통합되는 IDE](#ide-extension-supported-ides)
+ [시작하기](#ide-extension-getting-started)
+ [IDE에서 CloudFormation 프로젝트 초기화(VS Code만 해당)](#ide-extension-initialize-project)
+ [오픈 소스](#ide-extension-open-source)
+ [도움이 필요하세요?](#ide-extension-need-help)

## AWS CloudFormation 언어 서버와 통합되는 IDE
<a name="ide-extension-supported-ides"></a>

AWS는 다음 IDE용 AWS Toolkit를 통해 CloudFormation Language Server와의 off-the-shelf 통합을 제공합니다.
+ [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=AmazonWebServices.aws-toolkit-vscode)
+ IntelliJ IDEA, WebStorm 및 PyCharm을 포함한 [JetBrains IDE](https://plugins.jetbrains.com/plugin/11349-aws-toolkit)(버전 2025.3 이상)

다음 IDE도 CloudFormation 언어 서버를 지원합니다.
+ [Kiro](https://kiro.dev/downloads/)
+ [Cursor](https://cursor.com/)
+ 대부분의 VS Code 포크 및 배포

CloudFormation Language Server는 [Language Server Protocol](https://microsoft.github.io/language-server-protocol/)(LSP)을 준수하므로 다른 통합을 구성할 수 있습니다. 언어 서버를 다른 편집기와 통합하는 방법에 대한 지침은 [설치 가이드](https://github.com/aws-cloudformation/cloudformation-languageserver/blob/main/INSTALLATION.md)를 참조하세요.

## 시작하기
<a name="ide-extension-getting-started"></a>

**Topics**
+ [사전 조건](#ide-extension-prerequisites)
+ [1단계: AWS Toolkit 설치 또는 업그레이드](#ide-extension-install-toolkit)
+ [2단계: AWS Toolkit에서 CloudFormation에 액세스](#ide-extension-access-toolkit-panel)
+ [3단계: 템플릿 검증, 테스트 및 세부 조정](#ide-extension-validate-test-refine)
+ [4단계: 템플릿 탐색](#ide-extension-navigate-template)
+ [5단계: 검증 및 배포](#ide-extension-validate-deploy)

### 사전 조건
<a name="ide-extension-prerequisites"></a>

시작하기 전에 다음을 확인하세요.
+ 지원되는 운영 체제(macOS, Windows 또는 Linux)에서 지원되는 IDE를 사용하고 있습니다.
+ IDE에 대한 AWS Toolkit의 최신 버전을 설치했거나 해당 버전으로 업그레이드했습니다.

AWS CloudFormation 언어 서버의 일부 기능에는 활성 AWS 계정 및 구성된 자격 증명이 필요합니다. 유효한 자격 증명을 사용하여 AWS Toolkit를 통해 AWS 계정에 로그인해야 합니다.

### 1단계: AWS Toolkit 설치 또는 업그레이드
<a name="ide-extension-install-toolkit"></a>

IDE의 확장 또는 플러그인 관리자에서 최신 버전의 AWS Toolkit를 설치하거나 업데이트한 다음 IDE를 다시 시작합니다.

설치 후 AWS Toolkit는 CloudFormation IDE 지원을 자동으로 활성화합니다. AWS CloudFormation 언어 서버를 사용하여 AWS Toolkit를 처음 설치하거나 업그레이드할 때 익명 사용 데이터를 수집할 수 있는 AWS에 대한 권한을 부여하라는 메시지가 표시됩니다. 이 데이터는 AWS에서 CloudFormation 언어 서버 및 작성 환경을 개선하는 데 도움이 됩니다. 민감한 정보는 수집되지 않으며 AWS에서는 템플릿 콘텐츠, 리소스 구성 또는 식별 가능한 고객 데이터를 기록하거나 저장하지 않습니다. IDE 설정에서 언제라도 원격 측정 기본 설정을 변경할 수 있습니다. IDE를 다시 시작하여 변경 사항을 적용합니다. 수집된 사용 데이터는 기능 상호 작용 및 성능 지표에만 중점을 둡니다. 이러한 인사이트를 통해 AWS에서 더 빠른 검증, 개선된 자동 완성, 더 나은 오류 진단과 같은 개선 사항을 식별하고 우선순위를 지정할 수 있습니다.

### 2단계: AWS Toolkit에서 CloudFormation에 액세스
<a name="ide-extension-access-toolkit-panel"></a>

AWS Toolkit를 설치한 후 IDE에서 CloudFormation 패널을 엽니다. VS Code의 활동 표시줄에서 AWS Toolkit 패널을 열고 **CLOUDFORMATION**을 선택합니다. JetBrains IDE의 사이드 바에서 **AWS Toolkit** 도구 창을 열고 **CloudFormation** 탭을 선택합니다.

CloudFormation 패널에는 다음 섹션이 포함되어 있습니다.
+ **리전**: 현재 AWS 리전을 표시합니다. VS Code에서는 리전 이름을 선택하거나 명령 팔레트에서 **AWS CloudFormation: 리전 선택** 명령을 사용하여 변경할 수 있습니다. JetBrains IDE에서 리전은 AWS Toolkit 연결 설정을 통해 구성됩니다.
+ **스택**: 계정에서 CloudFormation 스택의 페이지가 매겨진 목록을 표시합니다. 스택을 확장하여 해당 스택과 연결된 변경 세트를 나열하는 **변경 세트** 노드를 봅니다. 스택 세부 정보 보기 작업을 사용하여 스택 개요, 이벤트, 출력 및 리소스를 표시하는 스택 세부 정보 보기를 엽니다.
+ **리소스**: 리소스 유형을 추가한 후 패널에는 계정에서 해당 유형의 AWS 리소스가 표시됩니다. 보거나 새로 고치거나 복사하거나 템플릿으로 가져올 수 있습니다.

JetBrains IDE에서 트리 위의 도구 모음을 활용하면 **검증 및 배포**, **검증 및 배포 재실행**, **리소스 유형 추가**, **새로 고침** 등의 일반적인 작업에 빠르게 액세스할 수 있습니다. 트리 노드의 오른쪽 클릭 컨텍스트 메뉴를 통해 작업을 사용할 수도 있습니다.

### 3단계: 템플릿 검증, 테스트 및 세부 조정
<a name="ide-extension-validate-test-refine"></a>

CloudFormation 템플릿을 작성할 때 IDE는 정확하고 규정을 준수하는 인프라를 더 빠르게 생성하는 데 도움이 되는 지능형 작성 지원 기능을 제공합니다. CloudFormation 언어 서버는 백그라운드에서 실행되며 다음과 같은 작성 기능을 제공합니다.
+ 코드 완성: CloudFormation 스키마를 기반으로 리소스 유형, 파라미터, 속성을 제안합니다.
+ 기존 AWS 리소스 추가: AWS 계정에서 템플릿으로 기존 리소스를 가져올 수 있습니다. IDE는 [AWS Cloud Control API(CCAPI)](https://docs.aws.amazon.com/cloudcontrolapi/latest/userguide/what-is-cloudcontrolapi.html)를 사용하여 리소스의 라이브 구성 및 속성을 검색하며, 이를 통해 템플릿 내 기존 인프라를 복제하거나 재사용할 수 있습니다.
+ 파라미터로 추출: 커서가 템플릿의 리터럴 값(예: `t2.micro`와 같은 문자열)에 있으면 IDE는 리팩터링 작업을 제공하여 값을 `Parameters` 섹션으로 추출하고 리터럴을 새 파라미터의 `!Ref`로 바꿉니다. 동일한 리터럴 값이 여러 위치에 나타나는 경우 모든 발생을 한 번에 추출하도록 선택할 수 있습니다.

#### 템플릿에 리소스를 추가하는 방법
<a name="ide-extension-add-resources-to-template"></a>
+ **리소스 유형 추가**: AWS Toolkit CloudFormation 패널의 **리소스**에서 찾아볼 리소스 유형을 추가합니다. VS Code에서 **추가 \$1** 아이콘을 클릭하거나 명령 팔레트에서 **AWS CloudFormation: 리소스 유형 추가** 명령을 사용합니다. JetBrains의 도구 모음에서 **리소스 유형 추가** 버튼을 클릭하거나 **리소스** 노드를 마우스 오른쪽 버튼으로 클릭합니다.
+ **리소스 유형 검색**: 검색 대화 상자에서 추가할 AWS 리소스 유형을 입력합니다. 예제:
  + `AWS::S3::Bucket`
  + `AWS::Lambda::Function`
+ **리소스 탐색**: **리소스** 섹션 아래에 계정에서 감지된 AWS 리소스의 페이지가 매겨진 목록이 표시됩니다. 리소스가 많은 경우 첫 번째 페이지만 표시됩니다. 탐색 제어를 사용하여 추가 페이지를 이동하면서 확인하고 사용 가능한 모든 리소스를 봅니다.
+ 템플릿에 포함하려는 리소스를 선택합니다.
+ 다음과 같이 목표에 따라 두 가지 방법으로 템플릿에 리소스를 삽입할 수 있습니다.
  + **기존 리소스 복제**: 기존 AWS 리소스의 라이브 구성 및 속성을 사용하여 템플릿에서 새 리소스를 생성합니다.
  + **기존 리소스 가져오기**: 라이브 상태를 사용하여 템플릿에 추가해 스택에 실제 리소스를 삽입합니다.

**팁**
+ 언제든지 **리소스** 섹션을 새로 고쳐 계정 또는 리전에서 사용 가능한 최신 리소스 목록을 볼 수 있습니다.
+ 리소스를 가져오는 경우 동일한 계정의 기존 CloudFormation 스택에 이미 속한 리소스를 추가하지 마세요.
+ 리소스가 CloudFormation에서 이미 관리되고 있는지 확인하려면 리소스 옆에 있는 정보 작업을 사용합니다. VS Code에서 **i** 아이콘을 클릭합니다. JetBrains IDE에서 리소스를 마우스 오른쪽 버튼으로 클릭하고 **스택 관리 정보 가져오기**를 선택합니다.

##### 관련 리소스 추가
<a name="ide-extension-add-related-resources"></a>

VS Code에서 명령 **AWS CloudFormation: 유형별 관련 리소스 추가**를 사용하여 선택한 리소스에 관련 리소스를 추가할 수 있습니다. 템플릿에 이미 정의된 리소스 유형에서 리소스 유형을 선택하면 IDE는 일반적으로 해당 유형에 연결되거나 종속된 리소스 목록을 표시합니다. 예를 들어 `AWS::EC2::Instance`를 선택하면 IDE에서 `AWS::EC2::SecurityGroup` 또는 `AWS::EC2::Subnet`과 같은 관련 리소스 추가를 제안할 수 있습니다. 이 기능을 사용하면 호환되는 리소스 유형을 수동으로 검색하지 않고도 연결된 인프라 구성 요소를 빠르게 빌드할 수 있습니다. 이 기능은 현재 JetBrains IDE에서는 지원되지 않습니다.

#### 정적 검증
<a name="ide-extension-static-validation"></a>

CloudFormation 언어 서버는 [AWS CloudFormation Linter(cfn-lint)](https://github.com/aws-cloudformation/cfn-lint) 및 [AWS CloudFormation Guard](https://docs.aws.amazon.com/cfn-guard/latest/ug/what-is-guard.html)로 구동되는 기본 제공 정적 검증을 제공합니다. 이러한 검증은 템플릿을 작성할 때 백그라운드에서 실행되므로 배포 전에 구문 오류, 규정 준수 격차, 모범 사례 문제를 식별하는 데 도움이 됩니다.

**정적 검증 개요**

IDE에는 다음과 같은 두 가지 유형의 실시간 정적 검증이 표시됩니다.
+ CloudFormation Linter(`cfn-lint`): CloudFormation 리소스 사양 및 스키마 규칙을 기준으로 템플릿을 검증합니다.
+ Guard(`cfn-guard`): 규정 준수 규칙 및 조직 정책 팩을 기준으로 템플릿을 검증합니다.

##### CloudFormation Linter(cfn-lint)
<a name="ide-extension-cfn-linter-details"></a>

CloudFormation Linter는 IDE에 통합되어 입력 시 템플릿 구문 및 구조를 자동으로 확인합니다.
+ **스키마 검증**: 구문 및 스키마 오류를 감지하여 템플릿이 CloudFormation 리소스 스키마를 준수하는지 확인합니다.
+ **오류 강조 표시**: 문제 아래에 인라인 마커를 표시하여 배포 블로커 또는 경고를 나타냅니다.
+ **가리킬 때 도움말 표시**: 오류 위로 마우스를 가져가면 IDE에서 해당 문제와 관련된 진단 메시지를 표시합니다. 빠른 수정을 사용할 수 있는 경우 빠른 수정도 제공됩니다.

##### Guard 통합
<a name="ide-extension-cfn-guard-integration"></a>

Guard는 규정 준수 및 보안 정책을 정의하는 규칙 세트를 기준으로 템플릿을 검증합니다. IDE는 CloudFormation 언어 서버를 통해 실시간으로 Guard 검증을 실행하여 템플릿을 작성하는 동안 즉각적인 피드백을 제공합니다.
+ **기본 규칙 팩**: IDE에는 리소스 보안 및 구성 위생을 위한 기본 모범 사례에 초점을 맞춘 사전 등록된 Guard 규칙 세트가 있습니다. 더 자세히 알아보려면 [Guard 규칙 레지스트리](https://github.com/aws-cloudformation/aws-guard-rules-registry)를 참조하십시오.
+ **규칙 팩 추가**: 규칙 세트를 추가하거나 수정하려면 IDE 설정을 열고, Guard 구성 섹션으로 이동해 추가 Guard 규칙 팩을 선택하거나 업로드합니다.

**팁**: 진단 지표 이해
+ 파란색 표시기: 모범 사례 힌트 또는 최적화 권장 사항.
+ 노란색 표시기: 차단 외 문제(예: 태그 또는 파라미터 누락)에 대한 경고.
+ 빨간색 표시기: 유효하지 않은 속성 이름, 필수 필드 누락 또는 스키마 불일치와 같은 배포 블로커.

### 4단계: 템플릿 탐색
<a name="ide-extension-navigate-template"></a>

IDE는 각 리소스 유형과 논리적 ID를 보여주는 `Parameters`, `Resources`, `Outputs`, `Mappings` 등의 섹션으로 구성된 CloudFormation 템플릿의 구조화된 계층적 보기를 제공합니다. 그러면 대규모 템플릿 내에서 특정 리소스 또는 파라미터를 빠르게 찾고 탐색할 수 있습니다. VS Code에서는 **Explorer** 사이드바의 **개요** 패널에 이 구조가 표시됩니다. JetBrains IDE에서 **구조** 도구 창을 열어 현재 열려 있는 파일의 템플릿 구조를 확인합니다.

`GetAtt` 및 `Ref`와 같은 내장 함수에 대한 **정의로 이동**을 사용하면 템플릿에서 참조된 리소스 또는 파라미터로 직접 이동할 수 있습니다. 이를 통해 종속성을 추적하고, 리소스 관계를 이해하며, 보다 효율적으로 편집할 수 있습니다.

### 5단계: 검증 및 배포
<a name="ide-extension-validate-deploy"></a>

CloudFormation 템플릿을 배포할 준비가 되면 검증 및 배포 기능을 사용하여 변경 세트를 생성합니다. IDE는 템플릿을 검증하며, 차단 오류가 발견되지 않으면 계속해서 [드리프트 인식 변경 세트](drift-aware-change-sets.md)를 생성합니다. 그러면 IDE에 변경 세트를 실행하기 전에 제안된 모든 변경 사항을 검토할 수 있는 diff 보기가 표시됩니다.

VS Code에서 명령 팔레트를 열고 **AWS CloudFormation: 검증 및 배포**를 실행합니다. 명령 팔레트는 템플릿, 스택 이름, 파라미터, 기능 및 기타 배포 옵션을 단계별로 선택하는 방법을 안내합니다. JetBrains IDE에서 **검증 및 배포** 도구 모음 버튼을 사용하거나, 편집기에서 템플릿 파일을 마우스 오른쪽 버튼으로 클릭하거나, 트리에서 스택을 마우스 오른쪽 버튼으로 클릭합니다. JetBrains는 템플릿 선택, 스택 이름, 파라미터, 기능, 태그 및 고급 옵션을 포함한 모든 배포 옵션을 구성하는 마법사 대화 상자를 제공합니다.

#### 검증 작동 방식
<a name="ide-extension-how-validation-works"></a>

IDE는 [배포 전에 검증 검사](validate-stack-deployments.md)를 자동으로 수행하고 다음과 같은 일반적인 장애 원인에 대해 템플릿을 검증합니다.
+ 유효하지 않은 속성 구문 또는 스키마 불일치: 이러한 문제는 일반적으로 작성 중에 `cfn-lint`에서 발견하지만 사용자가 문제를 해결하지 않고 배포를 진행하는 경우 CloudFormation의 배포 시 검증은 스택이 생성되거나 업데이트되기 전에 동일한 오류를 표시합니다.
+ 리소스 이름이 계정의 기존 리소스와 충돌합니다.
+ S3 버킷 이름 충돌 또는 암호화 누락과 같은 서비스별 제약 조건.

검증에서 오류가 감지되면 IDE는 템플릿에서 직접 문제를 강조 표시하고 진단 패널에 오류를 나열합니다. 각 문제에는 실패의 원인이 되는 특정 속성 또는 리소스와 제안된 수정 사항이 포함되어 있습니다. 차단 오류가 없는 경우 배포 단계로 진행할 수 있습니다.

경고(차단 외 문제)가 발견되면 배포를 진행하거나 취소하고 수정할 수 있는 대화 상자가 나타납니다.

IDE는 현재 템플릿과 배포된 스택 구성 간의 차이를 표시하는 [드리프트 인식 변경 세트](drift-aware-change-sets.md)를 엽니다. 이를 통해 실행 전에 변경 세트를 검토, 확인 또는 취소할 수 있습니다. 배포를 취소하면 변경 세트가 삭제됩니다.

드리프트 인식 변경 세트는 스택 드리프트를 안전하게 처리할 수 있도록 함으로써 CloudFormation 배포 프로세스를 개선합니다. 스택 드리프트는 리소스의 실제 상태가 CloudFormation 템플릿에 정의된 상태와 다를 때 발생합니다. 종종 AWS Management Console, CLI 또는 SDK를 통해 수행된 수동 변경으로 인해 발생합니다. CloudFormation의 [드리프트 인식 변경 세트](drift-aware-change-sets.md)가 처리된 스택 구성을 라이브 리소스 상태와 비교하고, IDE에서 이러한 차이를 표시하므로 배포 전에 리소스를 다시 규정 준수 상태로 되돌릴 수 있습니다.

#### 스택 이벤트 보기
<a name="ide-extension-view-stack-events"></a>

배포가 시작되면 CloudFormation 패널에서 진행 상황을 실시간으로 모니터링할 수 있습니다. **스택 이벤트** 아래에서 배포 중에 수행된 작업 목록이 표시됩니다. 각 이벤트에는 다음과 같은 세부 정보가 포함됩니다.
+ **타임스탬프**: 이벤트가 발생한 시간
+ **리소스**: 생성, 업데이트 또는 삭제되는 특정 AWS 리소스
+ **상태**: 작업의 현재 상태(예: `CREATE_IN_PROGRESS`, `UPDATE_COMPLETE` 또는 `ROLLBACK_IN_PROGRESS`)
+ **이유**: 해당하는 경우 추가 컨텍스트 또는 오류 메시지

이 패널에서 스택의 **리소스** 및 **출력**을 볼 수도 있습니다. **스택 이벤트** 보기를 통해 배포 진행 상황을 추적하고, 잠재적 문제를 식별하며, 스택이 성공적으로 완료된 시점을 확인할 수 있습니다.

## IDE에서 CloudFormation 프로젝트 초기화(VS Code만 해당)
<a name="ide-extension-initialize-project"></a>

IDE에서 CloudFormation 프로젝트를 초기화하면 올바른 폴더, 환경 구성 및 AWS 자격 증명으로 구조화된 작업 영역을 설정하여 신뢰할 수 있는 방식으로 템플릿을 검증하고 배포할 수 있습니다. IDE에서 직접 새 CloudFormation 프로젝트를 초기화하여 이 권장 설정을 생성할 수 있습니다. 이 기능은 현재 VS Code에서 사용할 수 있으며, JetBrains IDE에서는 지원되지 않습니다.

**CloudFormation 프로젝트를 초기화하는 방법:**
+ **명령 팔레트 열기**
  + VS Code에서 명령 팔레트(`Ctrl+Shift+P` 또는 macOS의 `Cmd+Shift+P`)를 엽니다.
  + **AWS CloudFormation: CFN Init: 프로젝트 초기화**를 선택합니다.
+ **프로젝트 디렉터리 선택**
  + 기본적으로 IDE는 현재 작업 디렉터리를 사용합니다.
  + 이 경로를 CloudFormation 템플릿을 저장하려는 폴더로 변경할 수 있습니다.
+ **AWS 자격 증명 프로파일 선택**
  + AWS 자격 증명 프로파일을 선택하라는 메시지가 표시됩니다. 선택한 프로파일은 환경 감지, 검증 및 배포에 사용됩니다.
+ **환경 설정**
  + 환경을 생성하거나 선택하라는 메시지가 표시됩니다.
  + 환경에서는 템플릿을 배포하거나 검증할 위치와 방법을 정의합니다(예: 개발, 베타 또는 프로덕션). **AWS CloudFormation: CFN Init: 환경 추가**를 사용하여 환경을 선택하거나 변경할 수 있습니다.
  + **AWS CloudFormation: CFN Init: 환경 제거**를 사용하여 선택한 환경을 제거할 수 있습니다.
+ **(선택 사항) 파라미터 파일 가져오기**
  + 기존 파라미터 파일이 이미 있는 경우 IDE를 사용하여 초기화 중에 해당 파일을 가져올 수 있습니다.
  + IDE는 호환되는 파일을 자동으로 감지하고 템플릿 검증 및 배포에 사용할 수 있도록 프로젝트에 연결합니다.
+ **프로젝트 이름 지정 및 마무리**
  + beta-environment와 같은 프로젝트 이름을 제공하고 설정을 완료합니다.
  + IDE는 사용자를 대신해 초기 프로젝트 구조 및 구성 파일을 생성합니다.

IDE에서 직접 검증을 실행하거나 배포를 미리 보거나 여러 환경 사이를 전환할 수 있습니다.

## 오픈 소스
<a name="ide-extension-open-source"></a>

AWS CloudFormation 언어 서버는 Apache-2.0 라이선스에 따라 오픈 소스로 제공되므로 고객에게 템플릿 진단, 스키마 검증 및 정적 분석을 수행하는 방법에 대한 완전한 투명성을 제공합니다. 이를 통해 도구를 채택하기 전에 소스 수준의 가시성이 필요한 고객 측에서 보안 및 규정 준수 마찰이 줄어듭니다.

코드 베이스는 GitHub([https://github.com/aws-cloudformation/cloudformation-languageserver/](https://github.com/aws-cloudformation/cloudformation-languageserver/))에서 공개적으로 사용할 수 있습니다.

## 도움이 필요하세요?
<a name="ide-extension-need-help"></a>

AWS re:Post에서 [CloudFormation 커뮤니티](https://repost.aws/tags/TAm3R3LNU3RfSX9L23YIpo3w)를 이용해 보세요.

# IaC 생성기를 사용하여 기존 리소스에서 템플릿 생성
<a name="generate-IaC"></a>

CloudFormation 인프라를 코드 생성기(IaC 생성기)로 사용하면 계정에 프로비저닝된 리소스 중에 CloudFormation에서 아직 관리하지 않는 AWS 리소스를 사용하여 템플릿을 생성할 수 있습니다.

IaC 생성기의 장점은 다음과 같습니다.
+ 전체 애플리케이션을 CloudFormation 관리에 포함하거나 AWS CDK 앱으로 마이그레이션합니다.
+ 리소스 속성을 속성별로 설명할 필요 없이 템플릿을 생성한 다음 이를 JSON 또는 YAML 구문으로 변환합니다.
+ 템플릿을 사용하여 새 계정 또는 리전에서 리소스를 복제합니다.

IaC 생성 프로세스는 다음 단계로 구성됩니다.

1. **리소스 스캔** - 첫 번째 단계는 리소스 스캔을 시작하는 것입니다. 이 스캔은 리전 전체에 적용되며 30일 후에 만료됩니다. 이 시간 동안 동일한 스캔에서 템플릿을 여러 개 생성할 수 있습니다.

1. **템플릿 생성** - 템플릿을 생성하려면 다음 두 가지 옵션이 있습니다.
   + 처음부터 새 템플릿을 생성하고 스캔한 리소스와 관련 리소스를 추가합니다.
   + 기존 CloudFormation 스택을 시작점으로 사용하고 템플릿에 스캔한 리소스와 관련 리소스를 추가합니다.

1. **리소스 가져오기** - 템플릿을 사용하여 리소스를 CloudFormation 스택으로 가져오거나 AWS CDK 앱으로 마이그레이션합니다.

IaC 생성기 특성은 모든 상업 리전에서 사용할 수 있으며 많은 일반적인 AWS 리소스 유형을 지원합니다. 지원되는 전체 리소스 목록은 [리소스 유형 지원](resource-import-supported-resources.md) 섹션을 참조하세요.

**Topics**
+ [고려 사항](#iac-generator-considerations)
+ [리소스 스캔에 필요한 IAM 권한](#iac-generator-permissions)
+ [템플릿 생성, 관리 및 삭제에 일반적으로 사용되는 명령](#iac-generator-commonly-used-commands)
+ [AWS CDK로 템플릿 마이그레이션](#iac-generator-cdk-migrate)
+ [CloudFormation IaC 생성기로 리소스 스캔 시작](iac-generator-start-resource-scan.md)
+ [CloudFormation 콘솔의 스캔 요약 보기](generate-IaC-view-scan-summary.md)
+ [IaC 생성기로 스캔한 리소스로 CloudFormation 템플릿 생성](iac-generator-create-template-from-scanned-resources.md)
+ [스캔한 리소스에서 CloudFormation 스택 생성](iac-generator-create-stack-from-scanned-resources.md)
+ [쓰기 전용 속성 해결](generate-IaC-write-only-properties.md)

## 고려 사항
<a name="iac-generator-considerations"></a>

읽기 액세스 권한이 있는 AWS 리소스에 대해 JSON 또는 YAML 템플릿을 생성할 수 있습니다. IaC 생성기 기능의 템플릿은 리소스 속성을 속성별로 설명할 필요 없이 클라우드 리소스를 안정적이고 빠르게 모델링합니다.

다음 표에는 IaC 생성 특성에 사용할 수 있는 할당량이 나와 있습니다.


| 이름 | 전체 스캔 | 부분 스캔 | 
| --- | --- | --- | 
|  스캔에서 처리할 수 있는 최대 리소스 수  |  100,000건  |  100,000건  | 
|  일일 스캔 횟수(리소스가 10,000개 미만인 스캔의 경우)  |  10  |  10  | 
|  일일 스캔 횟수(리소스가 10,000개를 초과하는 스캔의 경우)  |  1  |  1  | 
|  계정당 생성되는 템플릿의 동시 개수  |  5  |  5  | 
|  한 번의 템플릿 생성을 위해 모델링된 동시 리소스 수  |  5  |  5  | 
|  하나의 템플릿에서 모델링할 수 있는 총 리소스 수  |  500  |  500  | 
|  계정당 생성되는 최대 템플릿 수  |  1,000  |  1,000  | 

**중요**  
IaC 생성기는 리전의 Cloud Control API에서 지원하는 AWS 리소스만 지원합니다. 자세한 내용은 [리소스 유형 지원](resource-import-supported-resources.md) 섹션을 참조하세요.

## 리소스 스캔에 필요한 IAM 권한
<a name="iac-generator-permissions"></a>

IaC 생성기로 리소스를 스캔하려면 IAM 위탁자(사용자, 역할 또는 그룹)에 다음이 있어야 합니다.
+ CloudFormation 스캔 권한
+ 대상 AWS 서비스에 대한 읽기 권한

스캔 범위는 읽기 액세스 권한이 있는 리소스로 제한됩니다. 권한이 누락되어도 스캔에 실패하지 않지만 해당 리소스는 제외됩니다.

스캔 및 템플릿 관리 권한을 부여하는 IAM 정책의 예는 [모든 IaC 생성기 작업 허용](security_iam_id-based-policy-examples.md#iam-policy-example-for-iac-generator) 섹션을 참조하세요.

## 템플릿 생성, 관리 및 삭제에 일반적으로 사용되는 명령
<a name="iac-generator-commonly-used-commands"></a>

IaC 생성기 작업에 일반적으로 사용되는 명령은 다음과 같습니다.
+ [start-resource-scan](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/start-resource-scan.html) - AWS 리전의 계정에서 리소스 스캔을 시작합니다.
+ [describe-resource-scan](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-resource-scan.html) - 리소스 스캔의 진행 상황을 모니터링합니다.
+ [list-resource-scans](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-resource-scans.html)에 AWS 리전의 리소스 스캔이 나열됩니다.
+ [list-resource-scan-resources](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-resource-scan-resources.html) - 리소스 스캔 중 찾은 리소스를 나열합니다.
+  [list-resource-scan-related-resources](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-resource-scan-related-resources.html) - 스캔한 리소스와 관련된 리소스를 나열합니다.
+ [create-generated-template](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-generated-template.html) - 스캔한 리소스 세트에서 CloudFormation 템플릿을 생성합니다.
+ [update-generated-template](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/update-generated-template.html) - 생성된 템플릿을 업데이트합니다.
+ [describe-generated-template](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-generated-template.html) - 생성된 템플릿에 대한 정보를 반환합니다.
+ [list-generated-templates](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-generated-templates.html) - 계정과 현재 리전에서 생성된 모든 템플릿을 나열합니다.
+ [delete-generated-template](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/delete-generated-template.html) - 생성된 템플릿을 삭제합니다.

## AWS CDK로 템플릿 마이그레이션
<a name="iac-generator-cdk-migrate"></a>

AWS Cloud Development Kit (AWS CDK)는 널리 사용되는 프로그래밍 언어를 사용하여 CloudFormation 리소스를 개발, 관리, 배포하는 데 사용할 수 있는 오픈 소스 소프트웨어 개발 프레임워크입니다.

AWS CDK CLI는 IaC 생성기와의 통합 기능을 제공합니다. AWS CDK CLI `cdk migrate` 명령을 사용하여 CloudFormation 템플릿을 변환하고 리소스를 포함하는 새 CDK 앱을 생성합니다. 그런 다음 AWS CDK를 사용하여 리소스를 관리하고 CloudFormation에 배포할 수 있습니다.

자세한 내용은 **AWS Cloud Development Kit (AWS CDK) 개발자 안내서의 [AWS CDK로 마이그레이션](https://docs.aws.amazon.com/cdk/v2/guide/migrate.html)을 참조하세요.

# CloudFormation IaC 생성기로 리소스 스캔 시작
<a name="iac-generator-start-resource-scan"></a>

기존 리소스에서 템플릿을 생성하기 전에 먼저 리소스 스캔을 시작하여 현재 리소스 및 해당 관계를 검색해야 합니다.

다음 옵션 중 하나를 사용하여 리소스 스캔을 시작할 수 있습니다. IaC 생성기를 처음 사용하는 경우 첫 번째 옵션을 권장합니다.
+ **모든 리소스 스캔(전체 스캔)** - 현재 계정 및 리전의 모든 기존 리소스를 스캔합니다. 이 스캔 프로세스는 1,000개의 리소스를 스캔하는 데 최대 10분이 걸릴 수 있습니다.
+ **특정 리소스 스캔(부분 스캔)** - 현재 계정 및 리전에서 스캔할 리소스 유형을 수동으로 선택합니다. 이 옵션은 더 빠르고 집중적인 스캔 프로세스를 제공하므로 반복 템플릿 개발에 적합합니다.

스캔이 완료되면 템플릿을 생성할 때 포함할 리소스 및 관련 리소스를 선택할 수 있습니다. 부분 스캔을 사용하는 경우 다음 중 하나에 해당할 때에만 템플릿 생성 중에 관련 리소스를 사용할 수 있습니다.
+ 스캔을 시작하기 전에 특별히 선택한 경우 또는
+ 선택한 리소스 유형을 검색하는 데 필요한 경우.

예를 들어 `AWS::EKS::Cluster`를 선택하지 않고 `AWS::EKS::Nodegroup`을 선택하는 경우 노드 그룹을 검색하려면 먼저 클러스터를 검색해야 하므로 IaC 생성기는 스캔에 `AWS::EKS::Cluster` 리소스를 자동으로 포함합니다. 다른 모든 경우 스캔에는 특별히 사용자가 선택한 리소스만 포함됩니다.

**참고**  
계속 진행하기 전에 IaC 생성기를 사용하는 데 필요한 권한이 있는지 확인합니다. 자세한 내용은 [리소스 스캔에 필요한 IAM 권한](generate-IaC.md#iac-generator-permissions) 섹션을 참조하세요.

**Topics**
+ [리소스 스캔 시작(콘솔)](#start-resource-scan-console)
+ [리소스 스캔 시작(AWS CLI)](#start-resource-scan-cli)

## 리소스 스캔 시작(콘솔)
<a name="start-resource-scan-console"></a>

**모든 리소스 유형의 리소스 스캔을 시작하는 방법(전체 스캔)**

1. CloudFormation 콘솔의 [IaC 생성기 페이지](https://console.aws.amazon.com/cloudformation/home?#iac-generator)를 엽니다.

1. 화면 상단의 탐색 모음에서 스캔할 리소스가 포함된 AWS 리전을 선택합니다.

1. **스캔** 패널에서 **새 스캔 시작**을 선택한 다음 **모든 리소스 스캔**을 선택하세요.

**특정 리소스 유형의 리소스 스캔을 시작하는 방법(부분 스캔)**

1. CloudFormation 콘솔의 [IaC 생성기 페이지](https://console.aws.amazon.com/cloudformation/home?#iac-generator)를 엽니다.

1. 화면 상단의 탐색 모음에서 스캔할 리소스가 포함된 AWS 리전을 선택합니다.

1. **스캔** 패널에서 **새 스캔 시작**을 선택한 다음 **특정 리소스 스캔**을 선택하세요.

1. **부분 스캔 시작** 대화 상자에서 최대 100개의 리소스 유형을 선택한 다음 **스캔 시작**을 선택하세요.

## 리소스 스캔 시작(AWS CLI)
<a name="start-resource-scan-cli"></a>

**모든 리소스 유형의 리소스 스캔을 시작하는 방법(전체 스캔)**  
다음 [start-resource-scan](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/start-resource-scan.html) 명령을 사용합니다. *us-east-1*을 스캔할 리소스가 포함된 AWS 리전으로 바꿉니다.

```
aws cloudformation start-resource-scan --region us-east-1
```

이 명령이 성공하면 스캔의 ARN을 반환합니다. `ResourceScanId` 속성의 ARN을 기록해 둡니다. 템플릿을 생성하는 데 필요합니다.

```
{
    "ResourceScanId":
      "arn:aws:cloudformation:region:account-id:resourceScan/0a699f15-489c-43ca-a3ef-3e6ecfa5da60"
}
```

**특정 리소스 유형의 리소스 스캔을 시작하는 방법(부분 스캔)**

1. [cat](https://en.wikipedia.org/wiki/Cat_(Unix)) 명령을 사용하여 홈 디렉터리에서 이름이 `config.json`인 JSON 파일에 스캔하려는 리소스 유형 및 식별자를 저장하세요. 다음은 Amazon EC2 인스턴스, 보안 그룹 및 모든 Amazon S3 리소스를 스캔하는 스캔 구성 예제입니다.

   ```
   $ cat > config.json
   [
     {
       "Types":[
         "AWS::EC2::Instance",
         "AWS::EC2::SecurityGroup",
         "AWS::S3::*"
       ]
     }
   ]
   ```

1. 생성한 `config.json` 파일과 함께 `--scan-filters` 옵션을 포함해 [start-resource-scan](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/start-resource-scan.html) 명령을 사용하여 부분 스캔을 시작하세요. *us-east-1*을 스캔할 리소스가 포함된 AWS 리전으로 바꿉니다.

   ```
   aws cloudformation start-resource-scan --scan-filters file://config.json --region us-east-1
   ```

   이 명령이 성공하면 스캔의 ARN을 반환합니다. `ResourceScanId` 속성의 ARN을 기록해 둡니다. 템플릿을 생성하는 데 필요합니다.

   ```
   {
       "ResourceScanId":
         "arn:aws:cloudformation:region:account-id:resourceScan/0a699f15-489c-43ca-a3ef-3e6ecfa5da60"
   }
   ```

**리소스 스캔 진행 상황을 모니터링하는 방법**  
[describe-resource-scan](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-resource-scan.html) 명령을 사용합니다. `--resource-scan-id` 옵션의 경우 샘플 ARN을 실제 ARN으로 바꿉니다.

```
aws cloudformation describe-resource-scan --region us-east-1 \
  --resource-scan-id arn:aws:cloudformation:us-east-1:123456789012:resourceScan/0a699f15-489c-43ca-a3ef-3e6ecfa5da60
```

이 명령이 제대로 실행되면 다음과 비슷한 출력이 반환됩니다.

```
{
    "ResourceScanId": "arn:aws:cloudformation:region:account-id:resourceScan/0a699f15-489c-43ca-a3ef-3e6ecfa5da60",
    "Status": "COMPLETE",
    "StartTime": "2023-08-21T03:10:38.485000+00:00",
    "EndTime": "2023-08-21T03:20:28.485000+00:00",
    "PercentageCompleted": 100.0,
    "ResourceTypes": [
        "AWS::CloudFront::CachePolicy",
        "AWS::CloudFront::OriginRequestPolicy",
        "AWS::EC2::DHCPOptions",
        "AWS::EC2::InternetGateway",
        "AWS::EC2::KeyPair",
        "AWS::EC2::NetworkAcl",
        "AWS::EC2::NetworkInsightsPath",
        "AWS::EC2::NetworkInterface",
        "AWS::EC2::PlacementGroup",
        "AWS::EC2::Route",
        "AWS::EC2::RouteTable",
        "AWS::EC2::SecurityGroup",
        "AWS::EC2::Subnet",
        "AWS::EC2::SubnetCidrBlock",
        "AWS::EC2::SubnetNetworkAclAssociation",
        "AWS::EC2::SubnetRouteTableAssociation",
        ...
    ],
    "ResourcesRead": 676
}
```

부분 스캔의 경우 다음과 비슷한 출력이 표시됩니다.

```
{
    "ResourceScanId": "arn:aws:cloudformation:region:account-id:resourceScan/0a699f15-489c-43ca-a3ef-3e6ecfa5da60",
    "Status": "COMPLETE",
    "StartTime": "2025-03-06T18:24:19.542000+00:00",
    "EndTime": "2025-03-06T18:25:23.142000+00:00",
    "PercentageCompleted": 100.0,
    "ResourceTypes": [
        "AWS::EC2::Instance",
        "AWS::EC2::SecurityGroup",
        "AWS::S3::Bucket",
        "AWS::S3::BucketPolicy"
    ],
    "ResourcesRead": 65,
    "ScanFilters": [
        {
            "Types": [
                "AWS::EC2::Instance",
                "AWS::EC2::SecurityGroup",
                "AWS::S3::*"
            ]
        }
    ]
}
```

출력의 필드에 대한 설명은 **AWS CloudFormation API 참조의 [DescribeResourceScan](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeResourceScan.html)을 참조하세요.

# CloudFormation 콘솔의 스캔 요약 보기
<a name="generate-IaC-view-scan-summary"></a>

스캔 완료 후 스캔 중에 찾은 리소스를 시각화하여 볼 수 있어 다양한 제품 유형에 걸쳐 리소스가 얼마나 집중되어 있는지 식별하는 데 도움이 됩니다.

**스캔 중에 찾은 리소스에 대한 정보를 보는 방법**

1. CloudFormation 콘솔의 [IaC 생성기 페이지](https://console.aws.amazon.com/cloudformation/home?#iac-generator)를 엽니다.

1. 화면 상단의 탐색 모음에서 보려는 리소스 스캔이 포함된 AWS 리전을 선택합니다.

1. 탐색 창에서 **IaC 생성기**를 선택합니다.

1. 스캔한 리소스의 시각적 분석을 **스캔한 리소스 분석**에서 찾을 수 있습니다(예: **컴퓨팅**, **스토리지**).

1. 표시되는 제품 유형 수를 사용자 지정하려면 **표시된 데이터 필터링**을 선택합니다. 그러면 가장 관심 있는 제품 유형에 초점을 맞춰 시각화를 조정하는 데 도움이 됩니다.

1. 페이지 오른쪽에 **스캔 요약 세부 정보** 패널이 있습니다. 패널을 열려면 **패널 열기** 아이콘을 선택합니다.

![\[스캔한 리소스의 시각적 분석이 IaC 생성기 콘솔에서 제공됩니다.\]](http://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/images/IaC-generator-scan-summary.png)


# IaC 생성기로 스캔한 리소스로 CloudFormation 템플릿 생성
<a name="iac-generator-create-template-from-scanned-resources"></a>

이 주제에서는 IaC 생성기 기능을 사용하여 스캔한 리소스에서 템플릿을 생성하는 방법을 설명합니다.

## 스캔한 리소스에서 템플릿 생성(콘솔)
<a name="create-template-from-scanned-resources-console"></a>

**스캔한 리소스에서 새 스택 템플릿 생성**

1. CloudFormation 콘솔의 [IaC 생성기 페이지](https://console.aws.amazon.com/cloudformation/home?#iac-generator)를 엽니다.

1. 화면 상단의 탐색 모음에서 스캔한 리소스가 포함된 AWS 리전을 선택합니다.

1. **템플릿** 섹션에서 **템플릿 생성**을 선택합니다.

1. **새 템플릿에서 시작**을 선택합니다.

   1. **템플릿 이름**에 템플릿의 이름을 입력합니다.

   1. (선택 사항) **삭제 정책** 및 **업데이트 교체 정책**을 구성합니다.

   1. **다음**을 선택하여 스캔한 리소스를 템플릿에 추가합니다.

1. **스캔한 리소스 추가**에서 스캔한 리소스 목록을 탐색하고 템플릿에 추가할 리소스를 선택합니다. 리소스 식별자, 리소스 유형 또는 태그를 기준으로 리소스를 필터링할 수 있습니다. 필터는 상호 포괄적입니다.

1. 템플릿에 필요한 리소스를 모두 추가했으면 **다음**을 선택하여 **스캔한 리소스 추가** 페이지를 종료하고 **관련 리소스 추가** 페이지로 진행합니다.

1. 관련 리소스 권장 목록을 검토하세요. Amazon EC2 인스턴스와 보안 그룹 등의 관련 리소스는 상호 의존적이며 일반적으로 동일한 워크로드에 속합니다. 생성된 템플릿에 포함하려는 관련 리소스를 선택합니다.
**참고**  
이 템플릿에 모든 관련 리소스를 추가하는 것이 좋습니다.

1. 템플릿 세부 정보, 스캔한 리소스, 관련 리소스를 검토하세요.

1. **템플릿 생성**을 선택하여 **검토 및 생성** 페이지를 종료하고 템플릿을 생성합니다.

## 스캔한 리소스에서 템플릿 생성(AWS CLI)
<a name="create-template-from-scanned-resources-cli"></a>

**스캔한 리소스에서 새 스택 템플릿 생성**

1. 스캔 중 찾은 리소스를 나열하려면 [list-resource-scan-resources](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-resource-scan-resources.html) 명령을 사용하고 필요에 따라 출력을 제한하는 `--resource-identifier` 옵션을 지정합니다. `--resource-scan-id` 옵션의 경우 샘플 ARN을 실제 ARN으로 바꿉니다.

   ```
   aws cloudformation list-resource-scan-resources \
     --resource-scan-id arn:aws:cloudformation:us-east-1:123456789012:resourceScan/0a699f15-489c-43ca-a3ef-3e6ecfa5da60 \
     --resource-identifier MyApp
   ```

   다음은 응답 예제이며, 여기서 `ManagedByStack`은 CloudFormation이 리소스를 이미 관리하고 있는지 여부를 나타냅니다. 출력을 복사합니다. 이 정보는 다음 단계에 필요합니다.

   ```
   {
       "Resources": [
           {
               "ResourceType": "AWS::EKS::Cluster",
               "ResourceIdentifier": {
                   "ClusterName": "MyAppClusterName"
               },
               "ManagedByStack": false
           },
           {
               "ResourceType": "AWS::AutoScaling::AutoScalingGroup",
               "ResourceIdentifier": {
                   "AutoScalingGroupName": "MyAppASGName"
               },
               "ManagedByStack": false
           }
       ]
   }
   ```

   출력의 필드에 대한 설명은 **AWS CloudFormation API 참조의 [ScannedResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_ScannedResource.html)를 참조하세요.

1. `cat` 명령을 사용하여 홈 디렉터리의 이름이 `resources.json`인 JSON 파일에 리소스 유형과 식별자를 저장합니다. 다음은 이전 단계의 예제 출력을 기반으로 하는 JSON 예제입니다.

   ```
   $ cat > resources.json
   [
       {
           "ResourceType": "AWS::EKS::Cluster",
           "ResourceIdentifier": {
               "ClusterName": "MyAppClusterName"
           }
       },
       {
           "ResourceType": "AWS::AutoScaling::AutoScalingGroup",
           "ResourceIdentifier": {
               "AutoScalingGroupName": "MyAppASGName"
           }
       }
   ]
   ```

1. 스캔한 리소스와 관련된 리소스를 나열하려면 [list-resource-scan-related-resources](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-resource-scan-related-resources.html) 명령과 함께 생성한 `resources.json` 파일을 사용합니다.

   ```
   aws cloudformation list-resource-scan-related-resources \
     --resource-scan-id arn:aws:cloudformation:us-east-1:123456789012:resourceScan/0a699f15-489c-43ca-a3ef-3e6ecfa5da60 \
     --resources file://resources.json
   ```

   다음은 응답 예제이며, 여기서 `ManagedByStack`은 CloudFormation이 리소스를 이미 관리하고 있는지 여부를 나타냅니다. 이전 단계에서 생성한 JSON 파일에 리소스를 추가합니다. 템플릿을 생성할 때 필요합니다.

   ```
   {
       "RelatedResources": [
           {
               "ResourceType": "AWS::EKS::Nodegroup",
               "ResourceIdentifier": {
                   "NodegroupName": "MyAppNodegroupName"
               },
               "ManagedByStack": false
           },
           {
               "ResourceType": "AWS::IAM::Role",
               "ResourceIdentifier": {
                   "RoleId": "arn:aws::iam::account-id:role/MyAppIAMRole"
               },
               "ManagedByStack": false
           }
       ]
   }
   ```

   출력의 필드에 대한 설명은 **AWS CloudFormation API 참조의 [ScannedResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_ScannedResource.html)를 참조하세요.
**참고**  
리소스 입력 목록의 길이는 100을 초과할 수 없습니다. 100개 이상의 리소스에 대한 관련 리소스를 나열하려면 100개씩 배치로 **list-resource-scan-related-resources** 명령을 실행하고 결과를 통합합니다.  
목록의 중복된 리소스가 출력에 포함될 수 있다는 점에 유의하세요.

1. 새 스택 템플릿을 생성하려면 [create-generated-template](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-generated-template.html) 명령을 다음과 같이 수정하여 사용합니다.
   + 스캔한 리소스가 포함된 AWS 리전으로 `us-east-1`을 바꿉니다.
   + 생성할 템플릿의 이름으로 `MyTemplate`을 바꿉니다.

   ```
   aws cloudformation create-generated-template --region us-east-1 \
    --generated-template-name MyTemplate \
     --resources file://resources.json
   ```

   다음은 예 `resources.json` 파일입니다.

   ```
   [
       {
           "ResourceType": "AWS::EKS::Cluster",
           "LogicalResourceId":"MyCluster",
           "ResourceIdentifier": {
               "ClusterName": "MyAppClusterName"
           }
       },
       {
           "ResourceType": "AWS::AutoScaling::AutoScalingGroup",
           "LogicalResourceId":"MyASG",
           "ResourceIdentifier": {
               "AutoScalingGroupName": "MyAppASGName"
           }
       },
       {
           "ResourceType": "AWS::EKS::Nodegroup",
           "LogicalResourceId":"MyNodegroup",
           "ResourceIdentifier": {
               "NodegroupName": "MyAppNodegroupName"
           }
       },
       {
           "ResourceType": "AWS::IAM::Role",
           "LogicalResourceId":"MyRole",
           "ResourceIdentifier": {
               "RoleId": "arn:aws::iam::account-id:role/MyAppIAMRole"
           }
       }
   ]
   ```

   이 명령이 제대로 실행되면 다음을 반환합니다.

   ```
   {
     "Arn":
       "arn:aws:cloudformation:region:account-id:generatedtemplate/7fc8512c-d8cb-4e02-b266-d39c48344e48",
     "Name": "MyTemplate"
   }
   ```

# 스캔한 리소스에서 CloudFormation 스택 생성
<a name="iac-generator-create-stack-from-scanned-resources"></a>

템플릿을 생성한 후 스택을 생성하고 스캔한 리소스를 가져오기 전에 Infrastructure Composer를 사용하여 생성된 템플릿을 미리 볼 수 있습니다. 이를 통해 리소스가 포함된 전체 애플리케이션 아키텍처와 그 관계를 시각화할 수 있습니다. Infrastructure Composer에 대한 자세한 내용은 [Infrastructure Composer를 사용하여 시각적으로 템플릿 생성](infrastructure-composer-for-cloudformation.md) 섹션을 참조하세요.

**스택을 생성하고 스캔한 리소스를 가져오는 방법**

1. CloudFormation 콘솔의 [IaC 생성기 페이지](https://console.aws.amazon.com/cloudformation/home?#iac-generator)를 엽니다.

1. 화면 상단의 탐색 모음에서 템플릿에 대한 AWS 리전을 선택합니다.

1. **템플릿** 탭을 선택한 다음에 템플릿 이름을 선택하여 자세한 내용을 봅니다.

1. **템플릿** 섹션 상단의 **템플릿 정의** 탭에서 기본 설정을 기반으로 템플릿을 YAML에서 JSON 구문으로 전환할 수 있습니다.

1. 템플릿의 세부 정보를 검토하여 모든 항목이 올바르게 설정되었는지 확인합니다. 템플릿을 더 쉽게 검토하고 이해할 수 있도록 Infrastructure Composer를 사용하여 기본 코드 보기에서 템플릿에 설명된 인프라의 그래픽 형태 보기로 전환할 수 있습니다. 이렇게 하려면 **템플릿**에서 **템플릿** 대신에 **캔버스**를 선택합니다.

    **캔버스 작업** 
   + 템플릿 내 특정 리소스의 세부 정보에 집중하려면 카드를 두 번 클릭하여 **리소스 속성** 패널을 불러옵니다.
   + 캔버스에서 카드를 시각적으로 정렬하고 구성하려면 캔버스 왼쪽 상단에서 **정렬**을 선택합니다.
   + 캔버스를 확대 및 축소하려면 캔버스 오른쪽 아래에 있는 확대/축소 컨트롤을 사용합니다.

1. 콘솔의 특정 리소스를 보려면 **템플릿 리소스** 탭을 선택한 다음에 살펴보려는 리소스의 물리적 ID를 선택합니다. 그러면 해당 특정 리소스의 콘솔로 이동합니다. **템플릿 리소스** 탭에서 템플릿 정의의 리소스를 추가, 제거 및 재동기화할 수도 있습니다.

1. **템플릿 정의** 탭에서 IaC 생성기는 쓰기 전용 속성을 포함하는 리소스에 대해 경고를 표시할 수 있습니다. 경고를 검토한 후 생성된 템플릿을 다운로드하고 필요에 따라 변경할 수 있습니다. 자세한 내용은 [쓰기 전용 속성 해결](generate-IaC-write-only-properties.md) 섹션을 참조하세요.

1. 템플릿 정의에 만족하면 **템플릿 정의** 탭에서 **스택으로 가져오기**와 **다음**을 차례로 선택합니다.

1. **스택 세부 정보 지정** 페이지의 **스택 지정** 패널에서 스택 이름을 입력하고 **다음**을 선택합니다.

1. 스택에 대한 파라미터를 검토하고 입력합니다. **다음**을 선택합니다.

1. **변경 사항 검토** 페이지에서 옵션을 검토하고 **다음**을 선택합니다.

1. **검토 및 가져오기** 페이지에서 세부 정보를 검토하고 **리소스 가져오기**를 선택합니다.

# 쓰기 전용 속성 해결
<a name="generate-IaC-write-only-properties"></a>

CloudFormation IaC 생성기를 사용하면 계정에 프로비저닝된 리소스 중 CloudFormation에서 아직 관리하지 않는 리소스를 사용하여 템플릿을 생성할 수 있습니다. 하지만 특정 리소스 속성은 쓰기 전용으로 지정되므로 데이터베이스 암호와 같이 CloudFormation에서 쓸 수 있지만 읽을 수는 없습니다.**

기존 리소스에서 CloudFormation 템플릿을 생성할 때 쓰기 전용 속성은 문제를 야기합니다. 대부분의 경우 CloudFormation은 이러한 속성을 생성된 템플릿의 파라미터로 변환합니다. 이렇게 하면 가져오기 작업 중에 속성을 파라미터값으로 입력할 수 있습니다. 하지만 이러한 변환이 불가능한 시나리오도 있으며, CloudFormation은 이러한 경우를 다르게 처리합니다.

## 상호 배타적 속성
<a name="write-only-mutually-exclusive-properties"></a>

몇몇 리소스에는 상호 배타적인 속성 세트가 여러 개 있으며, 그중 일부는 쓰기 전용입니다. 이러한 경우 IaC 생성기는 생성 도중 리소스에 어떤 배타적인 속성 세트가 적용되었는지 확인할 수 없습니다. 예를 들어 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html)에 대한 코드를 
+ `Code/S3Bucket`, `Code/S3Key`, 선택적으로 `Code/S3ObjectVersion` 속성 세트를 사용하여 제공할 수 있습니다.
+ `Code/ImageUri`
+ `Code/ZipFile`

해당 속성은 모두 쓰기 전용입니다. IaC 생성기는 독점적인 속성 세트 중에서 하나를 선택하여 생성된 템플릿에 추가합니다. 각 쓰기 전용 속성에 대해 파라미터가 추가됩니다. 파라미터 이름에는 `OneOf`가 포함되며 파라미터 설명에 따르면 해당 속성을 다른 독점적인 속성으로 바꿀 수 있습니다. IaC 생성기는 포함된 속성에 대해 `MUTUALLY_EXCLUSIVE_PROPERTIES`의 경고 유형을 설정합니다.

## 상호 배타적 유형
<a name="write-only-mutually-exclusive-types"></a>

경우에 따라 쓰기 전용 속성이 여러 데이터 유형일 수 있습니다. 예를 들어 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-apigateway-restapi.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-apigateway-restapi.html)의 `Body` 속성은 `object` 또는 `string`가 될 수 있습니다. 이러한 경우 IaC 생성기는 `string` 유형을 사용하여 생성된 템플릿에 속성을 포함하고 `MUTUALLY_EXCLUSIVE_TYPES`의 경고 유형을 설정합니다.

## Array 속성
<a name="write-only-array-properties"></a>

쓰기 전용 속성의 유형이 `array`인 경우 파라미터는 스칼라 값만 사용할 수 있으므로 IaC 생성기는 생성된 템플릿에 해당 속성을 포함할 수 없습니다. 이 경우 템플릿에서 해당 속성이 생략되고 경고 유형이 `UNSUPPORTED_PROPERTIES`로 설정됩니다.

## 선택적 속성
<a name="write-only-optional-properties"></a>

선택적 쓰기 전용 속성의 경우 IaC 생성기는 리소스를 설정할 때 속성이 사용되었는지 감지할 수 없습니다. 이 경우 생성된 템플릿에서 해당 속성이 생략되고 경고 유형이 `UNSUPPORTED_PROPERTIES`로 설정됩니다.

## 경고 및 다음 단계
<a name="write-only-properties-warnings-and-next-steps"></a>

어떤 속성이 쓰기 전용인지 판단하려면 IaC 생성기 콘솔에서 반환되는 경고를 살펴보아야 합니다. [AWS 리소스 및 속성 유형 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-template-resource-type-ref.html)는 속성이 쓰기 전용인지 또는 여러 유형을 지원하는지를 나타내지 않습니다.

또는 리소스 공급자 스키마에서 어떤 속성이 쓰기 전용인지 확인할 수 있습니다. 리소스 공급자 스키마를 다운로드하려면 [CloudFormation 리소스 공급자 스키마](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/resource-type-schemas.html)를 참조하세요.

**쓰기 전용 속성 문제를 해결하는 방법**

1. CloudFormation 콘솔의 [IaC 생성기 페이지](https://console.aws.amazon.com/cloudformation/home?#iac-generator)를 엽니다.

1. 화면 상단의 탐색 모음에서 템플릿에 대한 AWS 리전을 선택합니다.

1. **템플릿** 탭을 선택한 다음에 생성한 템플릿의 이름을 선택합니다.

1. **템플릿 정의** 탭에서는 생성된 템플릿에 쓰기 전용 속성이 있는 리소스가 포함되어 있는 경우 IaC 생성기 콘솔에 문제 유형에 대한 요약과 함께 경고가 표시됩니다. 예:  
![\[생성된 템플릿의 쓰기 전용 속성에 대한 IaC 생성기 콘솔 경고\]](http://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/images/IaC-generator-write-only-property-warning.png)

1. 자세히 알아보려면 **경고 세부 정보 보기**를 선택합니다. 쓰기 전용 속성이 있는 리소스는 생성된 템플릿과 리소스 유형에 사용된 논리적 ID에 따라 식별됩니다.

   경고 목록을 사용하여 쓰기 전용 속성이 있는 리소스를 식별하고 생성된 템플릿에 변경이 필요한 경우 어떤 변경이 필요한지 판단하기 위해 각 리소스를 살펴봅니다.  
![\[생성된 템플릿의 쓰기 전용 속성에 대한 IaC 생성기 콘솔의 자세한 경고\]](http://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/images/IaC-generator-write-only-property-resource-warning.png)

1. 템플릿을 업데이트하여 쓰기 전용 속성 문제를 해결해야 한다면 다음과 같은 단계를 수행합니다.

   1. **다운로드**를 선택하여 템플릿 사본을 다운로드합니다.

   1. 템플릿을 편집합니다.

   1. 변경이 완료되면 **편집한 템플릿 가져오기** 버튼을 선택하여 가져오기 프로세스를 계속할 수 있습니다.

# AWS::ApiGateway::RestAPI 리소스의 쓰기 전용 속성 문제를 해결하는 방법
<a name="generate-IaC-apigateway-restapi"></a>

이 주제에서는 IaC 생성기를 사용할 때 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-apigateway-restapi.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-apigateway-restapi.html) 리소스의 쓰기 전용 속성 문제를 해결하는 방법을 설명합니다.

## 문제
<a name="apigateway-restapi-write-only-properties-issue"></a>

생성된 템플릿에 `AWS::ApiGateway::RestApi` 리소스가 포함되어 있으면 `Body`, `BodyS3Location`, `CloneFrom` 속성이 `UNSUPPORTED_PROPERTIES`로 식별된다는 경고가 생성됩니다. 이는 해당 속성이 선택적인 쓰기 전용 속성이기 때문입니다. IaC 생성기는 해당 속성이 리소스에 적용되었는지 여부를 알지 못합니다. 따라서 생성된 템플릿에서 이러한 속성을 생략합니다.

## 해결 방법
<a name="apigateway-restapi-write-only-properties-resolution"></a>

REST API의 `Body` 속성을 설정하려면 생성된 템플릿을 업데이트하세요.

1. Amazon API Gateway [https://docs.aws.amazon.com/apigateway/latest/api/API_GetExport.html](https://docs.aws.amazon.com/apigateway/latest/api/API_GetExport.html) API 작업을 사용하여 API를 다운로드합니다. 예를 들어 [https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-export.html](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-export.html) AWS CLI 명령을 사용합니다. 자세한 내용을 알아보려면 **API Gateway 개발자 안내서의 [API Gateway에서 REST API 내보내기](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-export-api.html)를 참조하세요.

1. `GetExport` API 작업의 응답에서 `Body` 속성을 검색합니다. Amazon S3 버킷에 업로드합니다.

1. 생성된 템플릿을 다운로드합니다.

1. 템플릿에 `BodyS3Location/Bucket` 및 `BodyS3Location/Key` 속성을 추가하고 `Body`가 저장되는 버킷 이름과 키를 지정합니다.

1. IaC 생성기 콘솔에서 생성된 템플릿을 열고 **편집한 템플릿 가져오기**를 선택합니다.

# AWS::Lambda::Function 리소스의 쓰기 전용 속성 문제를 해결하는 방법
<a name="generate-IaC-lambda-function"></a>

이 주제에서는 IaC 생성기를 사용할 때 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html) 리소스의 쓰기 전용 속성 문제를 해결하는 방법을 설명합니다.

## 문제
<a name="lambda-function-mutually-exclusive-properties-issue"></a>

`AWS::Lambda::Function` 리소스에는 Lambda 코드를 지정하기 위한 상호 배타적인 속성 세트가 3개 있습니다.
+ `Code/S3Bucket` 및 `Code/S3Key` 속성과 선택적으로 `Code/S3ObjectVersion` 속성 중 하나만 있을 수 있습니다.
+ `Code/ImageUri` 속성
+ `Code/ZipFile` 속성

지정된 `AWS::Lambda::Function` 리소스에는 이러한 세트 중 하나만 사용할 수 있습니다.

IaC 생성기는 리소스를 생성하거나 업데이트하는 데 사용된 독점적인 쓰기 전용 속성 세트를 확인할 수 없습니다. 결과적으로 생성된 템플릿에 첫 번째 속성 세트만 포함합니다. `Code/ImageUri` 및 `Code/ZipFile` 속성은 생략됩니다.

또한 IaC 생성기는 다음과 같은 경고를 표시합니다.
+ **`MUTUALLY_EXCLUSIVE_PROPERTIES`** - `Code/S3Bucket`과 `Code/S3Key`가 상호 배타적 속성으로 식별된다고 경고합니다.
+ **`UNSUPPORTED_PROPERTIES`** - `Code/S3ObjectVersion` 속성이 지원되지 않는다고 경고합니다.

생성된 템플릿에 `AWS::Lambda::Function` 리소스를 포함하려면 템플릿을 다운로드하고 올바른 코드 속성으로 업데이트해야 합니다.

## 해결 방법
<a name="lambda-function-mutually-exclusive-properties-resolution"></a>

**Amazon S3 버킷에 Lambda 코드를 저장하고 `S3ObjectVersion` 속성을 사용하지 않는 경우**에는 생성된 템플릿을 수정하지 않고 가져올 수 있습니다. IaC 생성기는 가져오기 작업 중에 템플릿 파라미터로 Amazon S3 버킷과 키를 요청합니다.

****Lambda 코드를 Amazon ECR 리포지토리로 저장하는 경우**에는 다음 지침에 따라 템플릿을 업데이트할 수 있습니다.**

1. 생성된 템플릿을 다운로드합니다.

1. 생성된 템플릿에서 `Code/S3Bucket` 및 `Code/S3Key` 속성에 대한 속성 및 해당 파라미터를 제거합니다.

1. 생성된 템플릿에서 제거된 속성을 `Code/ImageUri` 속성으로 바꾸고 Amazon ECR 리포지토리의 URL을 지정합니다.

1. IaC 생성기 콘솔에서 생성된 템플릿을 열고 **편집한 템플릿 가져오기** 버튼을 선택합니다.

****Lambda 코드를 zip 파일로 저장하는 경우**에는 다음 지침에 따라 템플릿을 업데이트할 수 있습니다.**

1. 생성된 템플릿을 다운로드합니다.

1. 생성된 템플릿에서 `Code/S3Bucket` 및 `Code/S3Key` 속성에 대한 속성 및 해당 파라미터를 제거합니다.

1. 생성된 템플릿에서 제거된 속성을 `Code/ZipFile` 속성으로 바꿉니다.

1. IaC 생성기 콘솔에서 생성된 템플릿을 열고 **편집한 템플릿 가져오기** 버튼을 선택합니다.

****Lambda 코드 사본이 없는 경우**에는 다음 지침에 따라 템플릿을 업데이트할 수 있습니다.**

1. AWS Lambda [https://docs.aws.amazon.com/lambda/latest/api/API_GetFunction.html](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunction.html) API 작업을 사용하세요(예: [https://docs.aws.amazon.com/cli/latest/reference/lambda/get-function.html](https://docs.aws.amazon.com/cli/latest/reference/lambda/get-function.html) AWS CLI 명령 사용).

1. 응답에서 `RepositoryType` 파라미터는 코드가 Amazon S3 버킷에 있는 경우 `S3`, 코드가 Amazon ECR 리포지토리에 있는 경우에는 `ECR`입니다.

1. 응답에서 `Location` 파라미터에는 배포 패키지를 10분 동안 다운로드하는 데 사용할 수 있는 미리 서명된 URL이 포함되어 있습니다. 코드를 다운로드하십시오.

1. Amazon S3 버킷에 코드를 업로드합니다.

1. 생성된 템플릿으로 가져오기 작업을 실행하고 버킷 이름과 키를 파라미터 값으로 제공합니다.

# 동적 참조를 사용하여 다른 서비스에 저장된 값 가져오기
<a name="dynamic-references"></a>

동적 참조는 다른 서비스에서 저장되고 관리되는 외부 값을 지정하고 코드형 인프라 템플릿에서 민감한 정보를 분리하는 편리한 방법을 제공합니다. CloudFormation에서 스택 및 변경 세트 작업 도중 필요한 지정된 참조의 값을 검색합니다.

동적 참조를 사용하여 다음을 수행할 수 있습니다.
+ **보안 문자열 사용** - 민감한 데이터의 경우 데이터가 저장 시 암호화되도록 항상 AWS Systems Manager Parameter Store의 보안 문자열 파라미터 또는 AWS Secrets Manager의 보안 암호를 사용하세요.
+ **액세스 제한** - Parameter Store 파라미터 또는 Secrets Manager 보안 암호에 대한 액세스를 승인된 보안 주체 및 역할로만 제한합니다.
+ **자격 증명 교체** - Parameter Store 또는 Secrets Manager에 저장된 민감한 데이터를 정기적으로 교체하여 높은 수준의 보안을 유지하세요.
+ **자동 교체** - Secrets Manager의 자동 교체 기능을 활용하여 민감한 데이터를 정기적으로 업데이트하고 애플리케이션 및 환경 전체에 배포하세요.

## 일반적인 고려 사항
<a name="dynamic-references-considerations"></a>

다음은 CloudFormation 템플릿에서 동적 참조를 지정하기 전에 고려할 일반적인 사항들입니다.
+ 리소스의 기본 식별자의 일부인 리소스 속성에 동적 참조 또는 민감한 데이터를 포함하지 마세요. CloudFormation은 기본 리소스 식별자의 실제 일반 텍스트 값을 사용할 수 있으며, 이는 보안 위험이 될 수 있습니다. 이 리소스 ID는 파생된 출력 또는 대상에 나타날 수 있습니다.

  리소스 유형의 기본 식별자를 구성하는 리소스 속성을 확인하려면 [AWS 리소스 및 속성 유형 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-template-resource-type-ref.html)에서 해당 리소스에 대한 리소스 참조 설명서를 참조하세요. **Return values**(반환 값) 섹션에서 `Ref` 함수 반환 값은 리소스 유형의 기본 식별자를 구성하는 리소스 속성을 나타냅니다.
+ 스택 템플릿에 최대 60개의 동적 참조를 포함할 수 있습니다.
+ 변환(예: `AWS::Include` 또는 `AWS::Serverless`)을 사용하는 경우 CloudFormation은 변환을 적용하기 전에 동적 참조를 확인하지 않습니다. 대신 동적 참조의 리터럴 문자열을 변형으로 전달하고, 템플릿을 사용하여 변경 세트를 실행할 때 참조를 확인합니다.
+ 사용자 지정 리소스의 보안 값(예: Parameter Store 또는 Secrets Manager에 저장된 값)에서는 동적 참조를 사용할 수 없습니다.
+ 동적 참조는 `AWS::CloudFormation::Init` 메타데이터 및 Amazon EC2 `UserData` 속성에서도 지원되지 않습니다.
+ 백슬래시(\$1)로 끝나는 동적 참조를 생성하지 마세요. CloudFormation은 이러한 참조를 확인할 수 없으므로 스택 작업이 실패합니다.

다음 주제에서는 동적 참조 사용에 대한 정보 및 기타 고려 사항을 제공합니다.

**Topics**
+ [일반적인 고려 사항](#dynamic-references-considerations)
+ [Systems Manager Parameter Store에서 일반 텍스트 값 가져오기](dynamic-references-ssm.md)
+ [Systems Manager Parameter Store에서 보안 문자열 값 가져오기](dynamic-references-ssm-secure-strings.md)
+ [Secrets Manager에서 보안 암호 또는 보안 암호 값 가져오기](dynamic-references-secretsmanager.md)

# Systems Manager Parameter Store에서 일반 텍스트 값 가져오기
<a name="dynamic-references-ssm"></a>

CloudFormation 템플릿을 생성할 때 Parameter Store에 저장된 일반 텍스트 값을 사용하는 것이 좋습니다. Parameter Store는 AWS Systems Manager의 기능입니다. Parameter Store 소개는 **AWS Systems Manager 사용 설명서의 [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html)를 참조하세요.

템플릿 내에서 Parameter Store의 일반 텍스트 값을 사용하려면 `ssm` 동적 참조를 사용합니다. 이 참조를 사용하면 Parameter Store의 `String` 또는 `StringList` 유형의 파라미터에서 값을 액세스할 수 있습니다.

스택 작업에 사용할 `ssm` 동적 참조의 버전을 확인하려면 스택 작업에 대한 변경 세트를 생성합니다. 그런 다음 **템플릿** 탭에서 처리된 템플릿을 검토합니다. 자세한 내용은 [CloudFormation 스택에 대한 변경 세트 생성](using-cfn-updating-stacks-changesets-create.md) 섹션을 참조하세요.

`ssm` 동적 참조를 사용할 때는 다음과 같은 몇 가지를 염두에 두어야 합니다.
+ CloudFormation은 동적 참조에 대한 드리프트 감지를 지원하지 않습니다. 파라미터 버전을 지정하지 않은 `ssm` 동적 참조에 대해 Systems Manager에서 파라미터 버전을 업데이트하는 경우 `ssm` 동적 참조가 포함된 모든 스택에서 스택 업데이트 작업을 수행하여 최신 파라미터 버전을 가져오는 것이 좋습니다.
+ CloudFormation 템플릿의 `Parameters` 섹션에서 `ssm` 동적 참조를 사용하려면 버전 번호를 포함해야 합니다. CloudFormation에서는 이 섹션에 버전 번호가 없으면 Parameter Store 값을 참조할 수 없습니다. 템플릿에서 파라미터를 Systems Manager 파라미터 유형으로 정의할 수도 있습니다. 이렇게 하면 Systems Manager 파라미터 키를 파라미터의 기본값으로 지정할 수 있습니다. 그러면 버전 번호를 지정하지 않아도 CloudFormation이 Parameter Store에서 최신 버전의 파라미터 값을 검색합니다. 이렇게 하면 템플릿을 더 간단하고 쉽게 유지할 수 있습니다. 자세한 내용은 [CloudFormation에서 제공하는 파라미터 유형을 사용하여 런타임 시 기존 리소스 지정](cloudformation-supplied-parameter-types.md) 섹션을 참조하세요.
+ 사용자 지정 리소스의 경우 CloudFormation에서 사용자 지정 리소스로 요청을 전송하기 전에 `ssm` 동적 참조를 확인합니다.
+ CloudFormation은 동적 참조를 사용하여 다른 AWS 계정에서 공유된 파라미터를 참조하는 것을 지원하지 않습니다.
+ CloudFormation에서 동적 참조 내에서 Systems Manager 파라미터 레이블 사용을 지원하지 않습니다.

## 권한
<a name="dynamic-references-ssm-permissions"></a>

시스템 관리자 Parameter Store에 저장된 파라미터를 지정하려면 지정된 파라미터에 대한 [https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetParameter.html](https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_GetParameter.html)를 호출할 수 있는 권한이 있어야 합니다. 특정 Systems Manager 파라미터에 대한 액세스를 제공하는 IAM 정책을 생성하는 방법을 알아보려면 *AWS Systems Manager 사용 설명서*의 [IAM 정책을 사용하여 Systems Manager 파라미터에 대한 액세스 제한](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-access.html)을 참조하세요.

## 참조 패턴
<a name="dynamic-references-ssm-pattern"></a>

CloudFormation 템플릿의 Systems Manager Parameter Store에 저장된 일반 텍스트 값을 참조하려면 다음 `ssm` 참조 패턴을 사용합니다.

```
{{resolve:ssm:parameter-name:version}}
```

참조는 parameter-name 및 version에 대해 다음 정규 표현식 패턴을 준수해야 합니다.

```
{{resolve:ssm:[a-zA-Z0-9_.\-/]+(:\d+)?}}
```

`parameter-name`  
 Parameter Store의 파라미터 이름입니다. 파라미터 이름은 대/소문자를 구분합니다.  
필수 사항입니다.

`version`  
사용할 파라미터의 버전을 지정하는 정수입니다. 정확한 버전을 지정하지 않으면 CloudFormation은 스택을 생성하거나 업데이트할 때마다 최신 버전의 파라미터를 사용합니다. 자세한 내용을 알아보려면 **AWS Systems Manager 사용 설명서의 [파라미터 버전 사용](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-versions.html)을 참조하세요.  
선택 사항.

## 예제
<a name="dynamic-references-ssm-examples"></a>

**Topics**
+ [퍼블릭 AMI ID 파라미터](#dynamic-references-ssm-public-ami-example)
+ [사용자 지정 AMI ID 파라미터](#dynamic-references-ssm-custom-ami-example)

### 퍼블릭 AMI ID 파라미터
<a name="dynamic-references-ssm-public-ami-example"></a>

다음 예제에서는 퍼블릭 AMI 파라미터를 참조하는 EC2 인스턴스를 생성합니다. 동적 참조는 퍼블릭 파라미터에서 최신 Amazon Linux 2023 AMI ID를 검색합니다. 퍼블릭 파라미터에 대한 자세한 내용은 *AWS Systems Manager 사용 설명서*의 [Parameter Store에서 퍼블릭 파라미터 검색](https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-finding-public-parameters.html)을 참조하세요.

#### JSON
<a name="dynamic-references-ssm-public-ami-example.json"></a>

```
{
    "Resources": {
        "MyInstance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "ImageId": "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64}}",
                "InstanceType": "t2.micro"
            }
        }
    }
}
```

#### YAML
<a name="dynamic-references-ssm-public-ami-example.yaml"></a>

```
Resources:
  MyInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64}}'
      InstanceType: t2.micro
```

### 사용자 지정 AMI ID 파라미터
<a name="dynamic-references-ssm-custom-ami-example"></a>

다음 예제는 Parameter Store에 저장된 사용자 지정 AMI ID를 참조하는 EC2 시작 템플릿을 생성합니다. 동적 참조는 인스턴스가 시작 템플릿에서 시작될 때마다 *`2`* 버전의 `golden-ami` 파라미터에서 AMI 검색합니다.

#### JSON
<a name="dynamic-references-ssm-custom-ami-example.json"></a>

```
{
    "Resources": {
        "MyLaunchTemplate": {
            "Type": "AWS::EC2::LaunchTemplate",
            "Properties": {
                "LaunchTemplateName": {
                    "Fn::Sub": "${AWS::StackName}-launch-template"
                },
                "LaunchTemplateData": {
                    "ImageId": "{{resolve:ssm:golden-ami:2}}",
                    "InstanceType": "t2.micro"
                }
            }
        }
    }
}
```

#### YAML
<a name="dynamic-references-ssm-custom-ami-example.yaml"></a>

```
Resources:
  MyLaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties: 
      LaunchTemplateName: !Sub ${AWS::StackName}-launch-template
      LaunchTemplateData:
        ImageId: '{{resolve:ssm:golden-ami:2}}'
        InstanceType: t2.micro
```

# Systems Manager Parameter Store에서 보안 문자열 값 가져오기
<a name="dynamic-references-ssm-secure-strings"></a>

CloudFormation에서 민감한 데이터를 AWS Systems Manager Parameter Store에 “보안 문자열”로 저장하여 템플릿에 직접 노출하지 않고도 암호 또는 라이센스 키와 같은 민감한 데이터를 사용할 수 있습니다. Parameter Store 소개는 **AWS Systems Manager 사용 설명서의 [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html)를 참조하세요.

템플릿 내에서 Parameter Store 보안 문자열을 참조하려면 `ssm-secure` 동적 참조를 사용합니다. CloudFormation은 실제 보안 문자열 값을 저장하지 않습니다. 대신 보안 문자열의 일반 텍스트 파라미터가 포함된 리터럴 동적 참조를 저장합니다.

스택 생성 또는 업데이트 도중 CloudFormation은 실제 값을 노출하지 않고 필요에 따라 보안 문자열 값에 액세스합니다. 보안 문자열은 `ssm-secure` 동적 참조 패턴을 지원하는 리소스 속성에 대해서만 사용할 수 있습니다. 자세한 내용은 [보안 문자열에 대한 동적 파라미터 패턴을 지원하는 리소스](#template-parameters-dynamic-patterns-resources) 섹션을 참조하세요.

CloudFormation에서는 API 호출의 보안 문자열에 대한 실제 파라미터 값을 반환하지 않습니다. 리터럴 동적 참조만 반환합니다. 변경 세트를 사용하여 변경을 비교할 때 CloudFormation에서는 리터럴 동적 참조 문자열만 비교합니다. 실제 보안 문자열 값을 확인하고 비교하지는 않습니다.

`ssm-secure` 동적 참조를 사용할 때는 다음과 같은 몇 가지를 염두에 두어야 합니다.
+ CloudFormation은 다른 AWS 계정의 Parameter Store 값에 액세스할 수 없습니다.
+ CloudFormation에서 동적 참조 내에서 Systems Manager 파라미터 레이블 또는 퍼블릭 파라미터 사용을 지원하지 않습니다.
+ `cn-north-1` 및 `cn-northwest-1` 리전에서 보안 문자열은 Systems Manager에서 지원되지 않습니다.
+ `ssm-secure`와 같은 보안 암호 값에 대한 동적 참조는 현재 사용자 지정 리소스에서 지원되지 않습니다.
+ CloudFormation에서 스택 업데이트를 롤백해야 하고, 이전에 지정된 버전의 보안 문자열 파라미터를 더 이상 사용할 수 없는 경우 롤백 작업은 실패합니다. 이 경우 다음 두 가지 선택지가 있습니다.
  + `CONTINUE_UPDATE_ROLLBACK`을 사용하여 리소스를 건너뜁니다.
  + 시스템 관리자 Parameter Store의 보안 문자열 파라미터를 재생성하고, 파라미터 버전이 템플릿에서 사용되는 버전에 도달할 때까지 업데이트합니다. 그런 다음 리소스를 건너뛰지 않고 `CONTINUE_UPDATE_ROLLBACK`을 사용합니다.

## 보안 문자열에 대한 동적 파라미터 패턴을 지원하는 리소스
<a name="template-parameters-dynamic-patterns-resources"></a>

`ssm-secure` 동적 참조 패턴을 지원하는 리소스는 다음과 같습니다.


| 리소스 | 속성 유형 | 속성 | 
| --- | --- | --- | 
| [AWS::DirectoryService::MicrosoftAD](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-directoryservice-microsoftad.html) |  | `Password` | 
| [AWS::DirectoryService::SimpleAD](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-directoryservice-simplead.html) |  | `Password` | 
| [AWS::ElastiCache::ReplicationGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticache-replicationgroup.html) |  | `AuthToken` | 
| [AWS::IAM::User](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html) | [LoginProfile](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-iam-user-loginprofile.html) | `Password` | 
| [AWS::KinesisFirehose::DeliveryStream](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-kinesisfirehose-deliverystream.html) | [RedshiftDestinationConfiguration](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-kinesisfirehose-deliverystream-redshiftdestinationconfiguration.html) | `Password` | 
| [AWS::OpsWorks::App](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-opsworks-app.html) | [소스](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-opsworks-app-source.html) | `Password` | 
| [AWS::OpsWorks::Stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-opsworks-stack.html) | [CustomCookbooksSource](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-opsworks-stack-source.html) | `Password` | 
| [AWS::OpsWorks::Stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-opsworks-stack.html) | [RdsDbInstances](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-opsworks-stack-rdsdbinstance.html) | `DbPassword` | 
| [AWS::RDS::DBCluster](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbcluster.html) |  | `MasterUserPassword` | 
| [AWS::RDS::DBInstance](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbinstance.html) |  | `MasterUserPassword`  | 
| [AWS::Redshift::Cluster](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-redshift-cluster.html) |  | `MasterUserPassword` | 

## 참조 패턴
<a name="dynamic-references-ssm-secure-pattern"></a>

CloudFormation 템플릿에서 Systems Manager Parameter Store에서 보안 문자열 값을 참조하려면 다음 `ssm-secure` 동적 패턴을 사용합니다.

```
{{resolve:ssm-secure:parameter-name:version}}
```

참조는 parameter-name 및 version에 대해 다음 정규 표현식 패턴을 준수해야 합니다.

```
{{resolve:ssm-secure:[a-zA-Z0-9_.\-/]+(:\d+)?}}
```

`parameter-name`  
 Parameter Store의 파라미터 이름입니다. 파라미터 이름은 대/소문자를 구분합니다.  
필수 사항입니다.

`version`  
사용할 파라미터의 버전을 지정하는 정수입니다. 정확한 버전을 지정하지 않으면 CloudFormation은 스택을 생성하거나 업데이트할 때마다 최신 버전의 파라미터를 사용합니다. 자세한 내용을 알아보려면 **AWS Systems Manager 사용 설명서의 [파라미터 버전 사용](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-versions.html)을 참조하세요.  
선택 사항.

## 예제
<a name="dynamic-references-ssm-secure-example"></a>

다음 예제에서는 `ssm-secure` 동적 참조를 사용하여 Parameter Store에 저장된 보안 문자열에 대한 IAM 사용자의 암호를 설정합니다. 지정된 것과 같이 CloudFormation은 스택 및 변경 세트 작업에 대해 *`10`* 버전의 `IAMUserPassword` 파라미터를 사용합니다.

### JSON
<a name="dynamic-references-ssm-secure-example.json"></a>

```
  "MyIAMUser": {
    "Type": "AWS::IAM::User",
    "Properties": {
      "UserName": "MyUserName",
      "LoginProfile": {
        "Password": "{{resolve:ssm-secure:IAMUserPassword:10}}"
      }
    }
  }
```

### YAML
<a name="dynamic-references-ssm-secure-example.yaml"></a>

```
  MyIAMUser:
    Type: AWS::IAM::User
    Properties:
      UserName: 'MyUserName'
      LoginProfile:
        Password: '{{resolve:ssm-secure:IAMUserPassword:10}}'
```

# Secrets Manager에서 보안 암호 또는 보안 암호 값 가져오기
<a name="dynamic-references-secretsmanager"></a>

Secrets Manager는 데이터베이스 자격 증명, 암호, 타사 API 키와 같은 보안 암호를 안전하게 저장 및 관리하는 서비스입니다. Secrets Manager를 사용하면 이러한 보안 암호에 대한 액세스를 중앙에서 저장하고 제어할 수 있으므로 코드의 하드코딩된 자격 증명(암호 포함)을 Secrets Manager에 대한 API 호출로 대체하여 프로그래밍 방식으로 보안 암호를 검색할 수 있습니다. 자세한 내용은 *AWS Secrets Manager 사용 설명서*의 [AWS Secrets Manager이란?](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html)을 참조하세요.

CloudFormation 템플릿 내에서 Secrets Manager에 저장된 전체 보안 암호 또는 보안 암호 값을 사용하려면 `secretsmanager` 동적 참조를 사용합니다.

## 모범 사례
<a name="dynamic-references-secretsmanager-best-practices"></a>

CloudFormation 템플릿에서 Secrets Manager 동적 참조를 사용할 때는 다음 모범 사례를 따르세요.
+ **CloudFormation 템플릿에 버전 없는 참조 사용** - 자격 증명을 Secrets Manager에 저장하고 적절한 보안 암호 교체 워크플로를 지원하기 위해 `version-stage` 또는 `version-id` 파라미터를 지정하지 않고 동적 참조를 사용합니다.
+ **자동 교체 활용** - 자격 증명 관리를 위해 버전 없는 동적 참조와 함께 Secrets Manager의 자동 교체 기능을 사용합니다. 이렇게 하면 템플릿 변경 없이 자격 증명을 정기적으로 업데이트할 수 있습니다. 자세한 내용을 알아보려면 [AWS Secrets Manager 보안 암호 교체](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets.html)를 참조하세요.
+ **버전이 지정된 참조를 거의 사용 ** - 테스트 또는 롤백 상황과 같은 특정 시나리오에 대해 명시적 `version-stage` 또는 `version-id` 파라미터만 지정합니다.

## 고려 사항
<a name="dynamic-references-secretsmanager-considerations"></a>

`secretsmanager` 동적 참조를 사용할 때는 다음과 같은 중요한 보안 고려 사항을 염두에 두어야 합니다.
+ CloudFormation은 이전 배포에서 사용된 보안 암호 버전을 추적하지 않습니다. 동적 참조를 구현하기 전에 보안 암호 관리 전략을 신중하게 계획합니다. 가능하면 버전 없는 참조를 사용하여 자동 보안 암호 교체를 활용합니다. 버전 관리되지 않은 동적 참조에서 버전 관리된 동적 참조로 전환하거나 그 반대로 전환하는 경우와 같이 동적 참조 구성을 변경할 때 리소스 업데이트를 모니터링하고 검증합니다.
+ Secrets Manager에서 보안 암호 값만 업데이트해도 CloudFormation에서 새 값을 자동으로 검색하지는 않습니다. CloudFormation은 리소스 생성 또는 동적 참조가 포함된 리소스를 수정하는 업데이트 중에만 보안 암호 값을 검색합니다.

  예를 들어 템플릿에 `MasterPassword` 속성이 Secrets Manager 동적 참조로 설정된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbinstance.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbinstance.html) 리소스가 포함되어 있다고 가정합니다. 이 템플릿에서 스택을 생성한 후 Secrets Manager에서 보안 암호 값을 업데이트합니다. 그러나 `MasterPassword` 속성은 이전 암호 값을 유지합니다.

  새 보안 암호 값을 적용하려면 CloudFormation 템플릿에서 `AWS::RDS::DBInstance` 리소스를 수정하고 스택 업데이트를 수행해야 합니다.

  향후 이 수동 프로세스를 거치지 않으려면 Secrets Manager를 사용하여 보안 암호를 자동으로 교체하는 것이 좋습니다.
+ `secretsmanager`와 같은 보안 암호 값에 대한 동적 참조는 현재 사용자 지정 리소스에서 지원되지 않습니다.
+ `secretsmanager` 동적 참조는 모든 리소스 속성에서 사용될 수 있습니다. `secretsmanager` 동적 참조 사용은 Secrets Manager 또는 CloudFormation 로그에서 확인된 보안 암호 값을 보존하지 않아야 함을 나타냅니다. 하지만 보안 암호 값이 리소스가 사용 중인 서비스에 표시될 수 있습니다. 사용을 검토하여 보안 암호 데이터 유출을 피합니다.

## 권한
<a name="dynamic-references-secretsmanager-permissions"></a>

Secrets Manager에 저장된 보안 암호를 지정하려면 보안 암호에 대한 [https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html)를 호출할 수 있는 권한이 있어야 합니다.

## 참조 패턴
<a name="dynamic-references-secretsmanager-pattern"></a>

CloudFormation 템플릿에서 Secrets Manager 보안 암호를 참조하려면 다음과 같은 `secretsmanager` 동적 참조 패턴을 사용합니다.

```
{{resolve:secretsmanager:secret-id:secret-string:json-key:version-stage:version-id}}
```

`secret-id`  
보안 암호의 이름 또는 ARN입니다.  
AWS 계정의 보안 암호에 액세스하려면 보안 암호 이름만 지정하면 됩니다. 다른 AWS 계정의 보안 암호에 액세스하려면 보안 암호의 전체 ARN을 지정해야 합니다.  
필수 사항입니다.

`secret-string`  
지원되는 유일한 값은 `SecretString`입니다. 기본값은 `SecretString`입니다.

`json-key`  
검색하고자 하는 값을 보유한 키-값 페어의 키 이름입니다. `json-key`를 지정하지 않는 경우 CloudFormation에서 전체 암호 텍스트를 검색합니다.  
이 세그먼트에는 콜론 문자(`:`)가 포함되지 않을 수 있습니다.

`version-stage`  
사용할 보안 암호 버전의 스테이징 레이블입니다. Secrets Manager는 교체 프로세스 도중 다른 버전을 추적하는 데 스테이징 레이블을 사용합니다. `version-stage`을 사용하는 경우 `version-id`를 지정하지 마세요. `version-stage` 또는 `version-id`를 지정하지 않은 경우 기본값은 `AWSCURRENT` 버전입니다.  
이 세그먼트에는 콜론 문자(`:`)가 포함되지 않을 수 있습니다.

`version-id`  
사용하고자 하는 보안 암호의 버전에 대한 고유 식별자입니다. `version-id`을 지정할 경우 `version-stage`을 지정하지 마세요. `version-stage` 또는 `version-id`를 지정하지 않은 경우 기본값은 `AWSCURRENT` 버전입니다.  
이 세그먼트에는 콜론 문자(`:`)가 포함되지 않을 수 있습니다.

## 예제
<a name="dynamic-references-secretsmanager-examples"></a>

**Topics**
+ [보안 암호에서 사용자 이름 및 암호 값 검색](#dynamic-references-secretsmanager-examples-user-name-and-password)
+ [전체 SecretString 검색](#dynamic-references-secretsmanager-examples-entire-secretstring)
+ [특정 버전의 보안 암호에서 값 검색](#dynamic-references-secretsmanager-examples-specific-version)
+ [다른 AWS 계정에서 보안 암호 검색](#dynamic-references-secretsmanager-examples-secrets-from-another-account)

### 보안 암호에서 사용자 이름 및 암호 값 검색
<a name="dynamic-references-secretsmanager-examples-user-name-and-password"></a>

다음 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbinstance.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbinstance.html) 예제에서는 `MySecret` 보안 암호에 저장된 사용자 이름 및 암호 값을 검색합니다. 이 예제는 버전 없는 동적 참조에 권장되는 패턴을 보여줍니다. 이 패턴은 템플릿 변경 없이 자동으로 `AWSCURRENT` 버전을 사용하고 Secrets Manager 회전 워크플로를 지원합니다.

#### JSON
<a name="dynamic-references-secretsmanager-examples-user-name-and-password.json"></a>

```
{
    "MyRDSInstance": {
        "Type": "AWS::RDS::DBInstance",
        "Properties": {
            "DBName": "MyRDSInstance",
            "AllocatedStorage": "20",
            "DBInstanceClass": "db.t2.micro",
            "Engine": "mysql",
            "MasterUsername": "{{resolve:secretsmanager:MySecret:SecretString:username}}",
            "MasterUserPassword": "{{resolve:secretsmanager:MySecret:SecretString:password}}"
        }
    }
}
```

#### YAML
<a name="dynamic-references-secretsmanager-examples-user-name-and-password.yaml"></a>

```
  MyRDSInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      DBName: MyRDSInstance
      AllocatedStorage: '20'
      DBInstanceClass: db.t2.micro
      Engine: mysql
      MasterUsername: '{{resolve:secretsmanager:MySecret:SecretString:username}}'
      MasterUserPassword: '{{resolve:secretsmanager:MySecret:SecretString:password}}'
```

### 전체 SecretString 검색
<a name="dynamic-references-secretsmanager-examples-entire-secretstring"></a>

다음 동적 참조는 `SecretString`의 `MySecret`을 검색합니다.

```
{{resolve:secretsmanager:MySecret}}
```

대안:

```
{{resolve:secretsmanager:MySecret::::}}
```

### 특정 버전의 보안 암호에서 값 검색
<a name="dynamic-references-secretsmanager-examples-specific-version"></a>

다음 동적 참조는 `AWSPREVIOUS` 버전의 `password`에 대한 `MySecret` 값을 검색합니다.

```
{{resolve:secretsmanager:MySecret:SecretString:password:AWSPREVIOUS}}
```

### 다른 AWS 계정에서 보안 암호 검색
<a name="dynamic-references-secretsmanager-examples-secrets-from-another-account"></a>

다음 동적 참조는 다른 AWS 계정에 있는 `MySecret`에 대한 `SecretString`을 검색합니다. 다른 AWS 계정의 보안 암호에 액세스하려면 전체 보안 암호 ARN을 지정해야 합니다.

```
{{resolve:secretsmanager:arn:aws:secretsmanager:us-west-2:123456789012:secret:MySecret}}
```

다음 동적 참조는 다른 AWS 계정에 있는 `MySecret`에 대한 `password` 값을 검색합니다. 다른 AWS 계정의 보안 암호에 액세스하려면 전체 보안 암호 ARN을 지정해야 합니다.

```
{{resolve:secretsmanager:arn:aws:secretsmanager:us-west-2:123456789012:secret:MySecret:SecretString:password}}
```

# 가상 파라미터를 사용하여 AWS 값 가져오기
<a name="pseudo-parameter-reference"></a>

가상 파라미터는 배포 또는 환경 간에 변경될 수 있는 계정 ID, 리전 이름, 스택 세부 정보 등의 중요한 AWS 환경 정보에 대한 액세스를 제공하는 기본 제공 변수입니다.

하드 코딩된 값 대신 가상 파라미터를 사용하여 템플릿을 더 쉽게 이동하고 여러 AWS 계정 및 리전에 재사용할 수 있습니다.

## 구문
<a name="pseudo-parameter-syntax"></a>

가상 파라미터는 `Ref` 내장 함수 또는 `Fn::Sub` 내장 함수를 사용하여 참조할 수 있습니다.

### Ref
<a name="pseudo-parameter-ref-syntax"></a>

`Ref` 내장 함수는 다음과 같은 일반 구문을 사용합니다. 자세한 내용은 [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-ref.html)를 참조하세요.

#### JSON
<a name="pseudo-parameter-ref-syntax.json"></a>

```
{ "Ref" : "AWS::PseudoParameter" }
```

#### YAML
<a name="pseudo-parameter-ref-syntax.yaml"></a>

```
!Ref AWS::PseudoParameter
```

### Fn::Sub
<a name="pseudo-parameter-sub-syntax"></a>

`Fn::Sub` 내장 함수는 가상 파라미터 주위에 `${}` 구문을 포함하는 다른 형식을 사용합니다. 자세한 내용은 [Fn::Sub](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-sub.html) 단원을 참조하십시오.

#### JSON
<a name="pseudo-parameter-sub-syntax.json"></a>

```
{ "Fn::Sub" : "${AWS::PseudoParameter}" }
```

#### YAML
<a name="pseudo-parameter-sub-syntax.yaml"></a>

```
!Sub '${AWS::PseudoParameter}'
```

## 사용 가능한 의사 파라미터
<a name="available-pseudo-parameters"></a>

### `AWS::AccountId`
<a name="cfn-pseudo-param-accountid"></a>

스택이 생성되는 계정의 AWS 계정 ID를 반환합니다(예: `123456789012`).

이 가상 파라미터는 계정별 ARN과 관련한 IAM 역할, 정책 및 기타 리소스 정책을 정의하는 데 많이 사용됩니다.

### `AWS::NotificationARNs`
<a name="cfn-pseudo-param-notificationarns"></a>

스택 이벤트 알림이 발생한 Amazon SNS 주제의 Amazon 리소스 이름(ARN) 목록을 반환합니다. 스택을 생성하거나 업데이트할 때 AWS CLI의 `--notification-arns` 옵션을 통해, 또는 콘솔을 통해 이러한 ARN을 지정할 수 있습니다.

단일 값을 반환하는 다른 가상 파라미터와 달리, `AWS::NotificationARNs`는 ARN 목록을 반환합니다. 목록의 특정 ARN에 액세스하려면 `Fn::Select` 내장 함수를 사용합니다. 자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-select.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-select.html) 섹션을 참조하세요.

### `AWS::NoValue`
<a name="cfn-pseudo-param-novalue"></a>

`Fn::If` 내장 함수에 반환 값으로 지정된 경우 해당 리소스 속성을 제거합니다. 자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if) 섹션을 참조하세요.

이 가상 파라미터는 특정 조건에서만 포함되어야 하는 조건부 리소스 속성을 생성하는 데 특히 유용합니다.

### `AWS::Partition`
<a name="cfn-pseudo-param-partition"></a>

리소스가 있는 파티션을 반환합니다. 표준 AWS 리전에서 파티션은 `aws`입니다. 다른 파티션에 있는 리소스의 경우 파티션은 `aws-`*partitionname*입니다. 예를 들어 중국(베이징 및 닝샤) 리전에 있는 리소스에 대한 파티션은 `aws-cn`이고, AWS GovCloud(미국 서부) 리전에 있는 리소스에 대한 파티션은 `aws-us-gov`입니다.

이 파티션은 리소스의 ARN에서 일부분을 구성합니다. `AWS::Partition`을 사용하면 여러 AWS 파티션에서 템플릿이 올바르게 작동합니다.

### `AWS::Region`
<a name="cfn-pseudo-param-region"></a>

포괄 리소스를 생성하는 리전을 나타내는 문자열을 반환합니다(예: `us-west-2`).

수정 없이 여러 AWS 리전에 템플릿이 적응될 수 있기 때문에, 가장 일반적으로 사용되는 가상 파라미터 중 하나입니다.

### `AWS::StackId`
<a name="cfn-pseudo-param-stackid"></a>

`arn:aws:cloudformation:us-west-2:123456789012:stack/teststack/51af3dc0-da77-11e4-872e-1234567db123`과 같은 스택의 ID(ARN)를 반환합니다.

### `AWS::StackName`
<a name="cfn-pseudo-param-stackname"></a>

`teststack`과 같은 스택의 이름을 반환합니다.

스택 이름은 고유한 리소스 이름을 생성하는 데 많이 사용되며, 해당 리소스가 특정 스택에 속해 있음을 쉽게 식별하는 데 도움이 됩니다.

### `AWS::URLSuffix`
<a name="cfn-pseudo-param-urlsuffix"></a>

스택이 배포된 AWS 리전에서 AWS 도메인의 접미사를 반환합니다. 이 접미사는 일반적으로 `amazonaws.com`이지만 중국(베이징) 리전의 경우 이 접미사는 `amazonaws.com.cn`입니다.

이 파라미터는 AWS 서비스 엔드포인트의 URL을 구성할 때 특히 유용합니다.

## 예제
<a name="pseudo-parameter-examples"></a>

**Topics**
+ [기본 사용법](#pseudo-parameter-basic-example)
+ [AWS::NotificationARNs 사용하기](#pseudo-parameter-notification-example)
+ [AWS::NoValue을 사용한 조건부 속성](#pseudo-parameter-novalue-example)

### 기본 사용법
<a name="pseudo-parameter-basic-example"></a>

다음 예에서는 두 가지 리소스, 즉 Amazon SNS 주제와 해당 주제에 알림을 전송하는 CloudWatch 경보를 생성합니다. `AWS::StackName`, `AWS::Region` 및 `AWS::AccountId`를 사용하여 스택 이름, 현재 AWS 리전 및 계정 ID를 리소스 이름, 설명 및 ARN에 동적으로 삽입합니다.

#### JSON
<a name="pseudo-parameter-basic-example.json"></a>

```
{
    "Resources": {
        "MyNotificationTopic": {
            "Type": "AWS::SNS::Topic",
            "Properties": {
                "DisplayName": { "Fn::Sub": "Notifications for ${AWS::StackName}" }
            }
        },
        "CPUAlarm": {
            "Type": "AWS::CloudWatch::Alarm",
            "Properties": {
                "AlarmDescription": { "Fn::Sub": "Alarm for high CPU in ${AWS::Region}" },
                "AlarmName": { "Fn::Sub": "${AWS::StackName}-HighCPUAlarm" },
                "MetricName": "CPUUtilization",
                "Namespace": "AWS/EC2",
                "Statistic": "Average",
                "Period": 300,
                "EvaluationPeriods": 1,
                "Threshold": 80,
                "ComparisonOperator": "GreaterThanThreshold",
                "AlarmActions": [{ "Fn::Sub": "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${MyNotificationTopic}" }]
            }
        }
    }
}
```

#### YAML
<a name="pseudo-parameter-basic-example.yaml"></a>

```
Resources:
  MyNotificationTopic:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: !Sub Notifications for ${AWS::StackName}
  CPUAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: !Sub Alarm for high CPU in ${AWS::Region}
      AlarmName: !Sub ${AWS::StackName}-HighCPUAlarm
      MetricName: CPUUtilization
      Namespace: AWS/EC2
      Statistic: Average
      Period: 300
      EvaluationPeriods: 1
      Threshold: 80
      ComparisonOperator: GreaterThanThreshold
      AlarmActions:
        - !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${MyNotificationTopic}
```

### AWS::NotificationARNs 사용하기
<a name="pseudo-parameter-notification-example"></a>

다음 예에서는 인스턴스 시작 이벤트 및 시작 오류에 대한 알림을 전송하도록 Auto Scaling 그룹을 구성합니다. 이 구성에는 스택 생성 중에 지정된 Amazon SNS 주제 ARN 목록을 제공하는 `AWS::NotificationARNs` 가상 파라미터를 사용합니다. `Fn::Select` 함수는 해당 목록에서 첫 번째 ARN을 선택합니다.

#### JSON
<a name="pseudo-parameter-notification-example.json"></a>

```
"myASG": {
   "Type": "AWS::AutoScaling::AutoScalingGroup",
   "Properties": {
      "LaunchTemplate": {
         "LaunchTemplateId": { "Ref": "myLaunchTemplate" },
         "Version": { "Fn::GetAtt": [ "myLaunchTemplate", "LatestVersionNumber" ] }
       },
       "MaxSize": "1",
       "MinSize": "1",
       "VPCZoneIdentifier": [
          "subnetIdAz1",
          "subnetIdAz2",
          "subnetIdAz3"
      ],
      "NotificationConfigurations" : [{
         "TopicARN" : { "Fn::Select" : [ "0", { "Ref" : "AWS::NotificationARNs" } ] },
         "NotificationTypes" : [ "autoscaling:EC2_INSTANCE_LAUNCH", "autoscaling:EC2_INSTANCE_LAUNCH_ERROR" ]
      }]
   }
}
```

#### YAML
<a name="pseudo-parameter-notification-example.yaml"></a>

```
myASG:
  Type: AWS::AutoScaling::AutoScalingGroup
  Properties:
    LaunchTemplate:
      LaunchTemplateId: !Ref myLaunchTemplate
      Version: !GetAtt myLaunchTemplate.LatestVersionNumber
    MinSize: '1'
    MaxSize: '1'
    VPCZoneIdentifier:
      - subnetIdAz1
      - subnetIdAz2
      - subnetIdAz3
    NotificationConfigurations:
      - TopicARN:
          Fn::Select:
          - '0'
          - Ref: AWS::NotificationARNs
        NotificationTypes:
        - autoscaling:EC2_INSTANCE_LAUNCH
        - autoscaling:EC2_INSTANCE_LAUNCH_ERROR
```

### AWS::NoValue을 사용한 조건부 속성
<a name="pseudo-parameter-novalue-example"></a>

다음 예는 스냅샷 ID가 제공된 경우에만 스냅샷을 사용하는 Amazon RDS DB 인스턴스를 생성합니다. `UseDBSnapshot` 조건이 true로 평가되면 CloudFormation에서는 `DBSnapshotIdentifier` 속성에 대한 `DBSnapshotName` 파라미터 값을 사용합니다. 조건이 false로 평가되면 CloudFormation이 `DBSnapshotIdentifier` 속성을 제거합니다.

#### JSON
<a name="pseudo-parameter-novalue-example.json"></a>

```
"MyDB" : {
  "Type" : "AWS::RDS::DBInstance",
  "Properties" : {
    "AllocatedStorage" : "5",
    "DBInstanceClass" : "db.t2.small",
    "Engine" : "MySQL",
    "EngineVersion" : "5.5",
    "MasterUsername" : { "Ref" : "DBUser" },
    "MasterUserPassword" : { "Ref" : "DBPassword" },
    "DBParameterGroupName" : { "Ref" : "MyRDSParamGroup" },
    "DBSnapshotIdentifier" : {
      "Fn::If" : [
        "UseDBSnapshot",
        {"Ref" : "DBSnapshotName"},
        {"Ref" : "AWS::NoValue"}
      ]
    }
  }
}
```

#### YAML
<a name="pseudo-parameter-novalue-example.yaml"></a>

```
MyDB:
  Type: AWS::RDS::DBInstance
  Properties:
    AllocatedStorage: '5'
    DBInstanceClass: db.t2.small
    Engine: MySQL
    EngineVersion: '5.5'
    MasterUsername:
      Ref: DBUser
    MasterUserPassword:
      Ref: DBPassword
    DBParameterGroupName:
      Ref: MyRDSParamGroup
    DBSnapshotIdentifier:
      Fn::If:
        - UseDBSnapshot
        - Ref: DBSnapshotName
        - Ref: AWS::NoValue
```

# 배포된 CloudFormation 스택에서 내보낸 출력 가져오기
<a name="using-cfn-stack-exports"></a>

동일한 AWS 계정 및 리전에 여러 스택이 있으면 스택 간에 정보를 공유하는 것이 좋습니다. 이는 하나의 스택에서 생성한 리소스를 다른 스택에서 사용해야 할 때 유용합니다.

예를 들어, 서브넷 및 보안 그룹과 같은 네트워크 리소스를 생성하는 웹 서버용 스택이 하나 있을 수 있습니다. 그러면 실제 웹 서버를 생성하는 다른 스택이 첫 번째 스택에서 생성된 네트워크 리소스를 사용할 수 있습니다. 스택의 템플릿 내에서 리소스 ID를 하드 코딩하거나 리소스 ID를 입력 파라미터로 전달할 필요가 없습니다.

스택 간에 정보를 공유하려면 한 스택에서 출력값을 **내보내기하고 다른 스택으로 **가져오기를 합니다. 작동 방식은 다음과 같습니다.

1. 첫 번째 스택의 템플릿(예: 네트워킹 스택)에서 `Outputs` 섹션의 `Export` 필드를 사용하여 내보낼 특정 값을 정의합니다. 자세한 내용은 [CloudFormation 템플릿 Outputs 구문](outputs-section-structure.md) 섹션을 참조하세요.

1. 해당 스택을 생성하거나 업데이트하면 CloudFormation에서는 동일 AWS 계정 및 리전의 다른 스택에서 사용할 수 있도록 출력값을 내보냅니다.

1. 다른 스택의 템플릿에서는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-importvalue.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-importvalue.html) 함수를 사용하여 첫 번째 스택에서 내보낸 값을 가져옵니다.

1. 두 번째 스택(예: 웹 서버 스택)을 생성하거나 업데이트하면 CloudFormation에서는 첫 번째 스택에서 내보낸 값을 자동으로 검색하여 사용합니다.

연습 및 샘플 템플릿은 [다른 CloudFormation 스택의 리소스 출력 참조](walkthrough-crossstackref.md) 단원을 참조하십시오.

## 스택 출력값 내보내기와 중첩 스택 사용 비교
<a name="output-vs-nested"></a>

중첩 스택은 `AWS::CloudFormation::Stack` 리소스를 사용하여 다른 스택 내에 생성하는 스택입니다. 중첩 스택을 사용하여 단일 스택의 모든 리소스를 배포 및 관리합니다. 중첩 스택 그룹 내 스택 하나의 출력은 그룹 내 다른 스택에 대한 입력으로 사용할 수 있습니다. 이는 값을 내보내는 것과는 다릅니다.

중첩 스택 그룹 내로 정보 공유를 제한하려면 중첩 스택을 사용하는 것이 좋습니다. (중첩 스택 그룹 내에서뿐만이 아니라 해당 그룹 외부에서도) 다른 스택과 정보를 공유하려면 값을 내보냅니다. 예를 들어 서브넷을 사용해 단일 스택을 생성한 다음 이 서브넷의 ID를 내보냅니다. 다른 스택은 ID를 가져와서 해당 서브넷을 사용할 수 있습니다. 각 스택은 자체 서브넷을 생성할 필요가 없습니다. 스택이 서브넷 ID를 가져오는 한 이 ID를 변경하거나 삭제할 수 없습니다.

중첩 스택에 대한 자세한 내용은 [중첩 스택을 사용하여 템플릿을 재사용 가능한 조각으로 분할](using-cfn-nested-stacks.md) 섹션을 참조하세요.

## 고려 사항
<a name="using-cfn-stack-exports-considerations"></a>

교차 스택 참조에 적용되는 제한은 다음과 같습니다.
+ 각 AWS 계정의 `Export` 이름은 한 리전 내에서 고유해야 합니다.
+ 여러 리전 간에 교차 스택 참조를 생성할 수 없습니다. `Fn::ImportValue` 내장 함수는 동일 리전 안에서 내보냈던 값을 가져오는 데만 사용할 수 있습니다.
+ 출력의 경우, 리소스에 의존하는 `Name` 또는 `Export` 함수를 `Ref`의 `GetAtt` 속성값으로 사용할 수 없습니다.

  마찬가지로 `ImportValue` 함수는 리소스에 의존하는 `Ref` 또는 `GetAtt` 함수를 포함할 수 없습니다.
+ 다른 스택이 출력 값을 가져오면 출력값을 내보내는 스택을 삭제하거나 내보낸 출력 값을 수정할 수 없습니다. 따라서 내보내는 스택을 삭제하거나 출력값을 수정하려면 가져오기를 모두 제거해야 합니다.

## 내보낸 출력값 나열
<a name="using-cfn-stack-exports-listing"></a>

스택에서 내보낸 출력 값을 확인해야 하는 경우 다음 방법 중 하나를 사용하세요.

**내보낸 출력값을 나열하려면(콘솔)**

1. CloudFormation 콘솔([https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/))을 엽니다.

1. 화면 상단의 탐색 모음에서 AWS 리전을 선택합니다.

1. 왼쪽 탐색 창에서 **내보내기**를 선택합니다.

**내보낸 출력값을 나열하려면(AWS CLI)**  
다음 [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-exports.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-exports.html) 명령을 사용합니다. *us-east-1*을 해당 AWS 리전으로 대체합니다.

```
aws cloudformation list-exports --region us-east-1
```

다음은 예제 출력입니다.

```
{
    "Exports": [
        {
            "ExportingStackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/private-vpc/99764070-b56c-xmpl-bee8-062a88d1d800",
            "Name": "private-vpc-subnet-a",
            "Value": "subnet-07b410xmplddcfa03"
        },
        {
            "ExportingStackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/private-vpc/99764070-b56c-xmpl-bee8-062a88d1d800",
            "Name": "private-vpc-subnet-b",
            "Value": "subnet-075ed3xmplebd2fb1"
        },
        {
            "ExportingStackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/private-vpc/99764070-b56c-xmpl-bee8-062a88d1d800",
            "Name": "private-vpc-vpcid",
            "Value": "vpc-011d7xmpl100e9841"
        }
    ]
}
```

CloudFormation에서는 출력을 내보낸 현재 리전 및 스택에 대해 내보낸 출력의 이름 및 값을 표시합니다. 다른 스택의 템플릿에서 내보낸 출력 값을 사용하려면 내보내기 이름 및 `Fn::ImportValue` 함수를 사용하여 참조할 수 있습니다.

## 출력값을 가져오고 내보내는 스택 나열
<a name="using-cfn-stack-imports"></a>

내보낸 출력 값을 삭제하거나 변경하려면 먼저 어떤 스택이 해당 출력 값을 가져오는지 확인해야 합니다.

내보낸 출력 값을 가져오는 스택을 보려면 다음 방법 중 하나를 사용하세요.

**내보낸 출력값을 가져오는 스택을 나열하려면(콘솔)**

1. CloudFormation 콘솔([https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/))을 엽니다.

1. 왼쪽 탐색 창에서 **내보내기**를 선택합니다.

1. 지정된 내보내기 값을 가져오는 스택을 보려면 해당 내보내기 값에 대해 **Export Name**(내보내기 이름)을 선택합니다. CloudFormation은 값을 가져오는 모든 스택을 나열하는 내보내기 세부 정보 페이지를 표시합니다.

**내보낸 출력값을 가져오는 스택을 나열하려면(AWS CLI)**  
[https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-imports.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-imports.html) 명령을 사용합니다. *us-east-1*을 AWS 리전으로 바꾸고 `private-vpc-vpcid`를 내보낸 출력 값의 이름으로 바꿉니다.

```
aws cloudformation list-imports --region us-east-1 \
    --export-name private-vpc-vpcid
```

CloudFormation에서는 값을 가져오는 스택 목록을 반환합니다.

```
{
    "Imports": [
        "my-app-stack"
    ]
}
```

어떤 스택에서 내보낸 특정 값을 가져오는지 확인한 후에는 해당 출력 값을 참조하는 `Fn::ImportValue` 함수를 제거하도록 스택을 수정합니다. 내보낸 출력값을 삭제 또는 수정하려면 내보낸 출력 값을 참조하는 가져오기를 모두 제거해야 합니다.

# CloudFormation에서 제공하는 파라미터 유형을 사용하여 런타임 시 기존 리소스 지정
<a name="cloudformation-supplied-parameter-types"></a>

템플릿을 생성할 때 CloudFormation에서 제공하는 특수 파라미터 유형을 사용하여 사용자가 기존 AWS 리소스의 식별자 또는 Systems Manager 파라미터의 식별자를 입력해야 하는 파라미터를 생성할 수 있습니다.

**Topics**
+ [개요](#cloudformation-supplied-parameter-types-overview)
+ [예제](#cloudformation-supplied-parameter-types-example)
+ [고려 사항](#cloudformation-supplied-parameter-types-considerations)
+ [지원되는 AWS 특정 파라미터 유형](#aws-specific-parameter-types-supported)
+ [지원되는 Systems Manager 파라미터 유형](#systems-manager-parameter-types-supported)
+ [지원되지 않는 Systems Manager 파라미터 유형](#systems-manager-parameter-types-unsupported)

## 개요
<a name="cloudformation-supplied-parameter-types-overview"></a>

CloudFormation에서 파라미터를 사용하여 스택 생성 또는 업데이트 중에 입력 값을 제공하여 스택을 사용자 지정할 수 있습니다. 이 특성을 통해 템플릿을 다양한 시나리오에서 유연하게 재사용할 수 있습니다.

파라미터는 CloudFormation 템플릿의 `Parameters` 섹션에 정의되어 있습니다. 파라미터마다 이름과 유형이 있으며, 기본값과 허용되는 값 등의 추가 설정이 있을 수 있습니다. 자세한 내용은 [CloudFormation 템플릿 Parameters 구문](parameters-section-structure.md) 섹션을 참조하세요.

파라미터 유형에 따라 파라미터가 허용할 수 있는 입력 값의 종류가 결정됩니다. 예를 들어, `Number`는 숫자 값만 허용하고 `String`은 텍스트 입력을 허용합니다.

CloudFormation은 템플릿에서 기존 AWS 리소스 및 Systems Manager 파라미터를 참조하는 데 사용할 수 있는 몇 가지 추가 파라미터 유형을 제공합니다.

이러한 파라미터 유형은 두 가지 범주로 분류됩니다.
+ **AWS 특정 파라미터 유형** - CloudFormation은 스택을 생성하거나 업데이트할 때 잘못된 값을 포착하는 데 도움이 되는 파라미터 유형 세트를 제공합니다. 이러한 파라미터 유형을 사용할 때 템플릿을 사용하는 모든 사용자는 스택을 생성하는 AWS 계정과 리전에서 유효한 값을 지정해야 합니다.

  AWS Management Console을 사용하는 경우 CloudFormation은 계정과 리전의 미리 채워진 기존 값 목록을 제공합니다. 이렇게 하면 사용자가 특정 이름이나 ID를 기억하고 정확하게 입력할 필요가 없습니다. 대신 드롭다운 목록에서 값을 선택하기만 하면 됩니다. 경우에 따라 ID, 이름 또는 `Name` 태그 값으로 값을 검색할 수도 있습니다.
+ **Systems Manager 파라미터 유형** - CloudFormation은 또한 Systems Manager Parameter Store의 기존 파라미터에 해당하는 파라미터 유형을 제공합니다. 이러한 파라미터 유형을 사용하는 경우 템플릿을 사용하는 모든 사용자는 Parameter Store 파라미터 키를 Systems Manager 파라미터 유형 값으로 지정해야 합니다. 그러면 CloudFormation이 Parameter Store에서 스택에 사용할 최신 값을 검색합니다. 이는 새로운 Amazon Machine Image(AMI) ID와 같은 새 속성 값으로 애플리케이션을 자주 업데이트해야 할 때 유용할 수 있습니다. Parameter Store에 대한 자세한 내용은 [Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html)를 참조하세요.

`Parameters` 섹션에 파라미터가 정의되면 `Ref` 함수를 사용하여 CloudFormation 템플릿 전체에서 파라미터 값을 참조할 수 있습니다.

## 예제
<a name="cloudformation-supplied-parameter-types-example"></a>

다음 예에서는 다음 파라미터 유형을 사용하는 템플릿을 보여줍니다.
+ `AWS::EC2::VPC::Id`
+ `AWS::EC2::Subnet::Id`
+ `AWS::EC2::KeyPair::KeyName`
+ `AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>`

이 템플릿에서 스택을 생성하려면 계정에서 기존 VPC ID, 서브넷 ID 및 키 페어 이름을 지정해야 합니다. 원하는 AMI ID를 참조하는 기존 Parameter Store 키를 지정하거나 기본값인 `/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2`를 유지할 수도 있습니다. 이 공용 파라미터는 최신 Amazon Linux 2 AMI의 리전 AMI ID에 대한 별칭입니다. 공용 파라미터에 대한 자세한 내용은 *AWS Systems Manager 사용 설명서*의 [Parameter Store에서 퍼블릭 파라미터 검색](https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-finding-public-parameters.html)을 참조하세요.

### JSON
<a name="cloudformation-supplied-parameter-types-example.json"></a>

```
{
    "Parameters": {
        "VpcId": {
            "Description": "ID of an existing Virtual Private Cloud (VPC).",
            "Type": "AWS::EC2::VPC::Id"
        },
        "PublicSubnetId": {
            "Description": "ID of an existing public subnet within the specified VPC.",
            "Type": "AWS::EC2::Subnet::Id"
        },
        "KeyName": {
            "Description": "Name of an existing EC2 key pair to enable SSH access to the instance.",
            "Type": "AWS::EC2::KeyPair::KeyName"
        },
        "AMIId": {
            "Description": "Name of a Parameter Store parameter that stores the ID of the Amazon Machine Image (AMI).",
            "Type": "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>",
            "Default": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
        }
    },
    "Resources": {
        "InstanceSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": "Enable SSH access via port 22",
                "VpcId": { "Ref": "VpcId" },
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 22,
                        "ToPort": 22,
                        "CidrIp": "0.0.0.0/0"
                    }
                ]
            }
        },
        "Ec2Instance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "KeyName": { "Ref": "KeyName" },
                "ImageId": { "Ref": "AMIId" },
                "NetworkInterfaces": [
                    {
                        "AssociatePublicIpAddress": "true",
                        "DeviceIndex": "0",
                        "SubnetId": { "Ref": "PublicSubnetId" },
                        "GroupSet": [{ "Ref": "InstanceSecurityGroup" }]
                    }
                ]
            }
        }
    },
    "Outputs": {
        "InstanceId": {
            "Value": { "Ref": "Ec2Instance" }
        }
    }
}
```

### YAML
<a name="cloudformation-supplied-parameter-types-example.yaml"></a>

```
Parameters:
  VpcId:
    Description: ID of an existing Virtual Private Cloud (VPC).
    Type: AWS::EC2::VPC::Id
  PublicSubnetId:
    Description: ID of an existing public subnet within the specified VPC.
    Type: AWS::EC2::Subnet::Id
  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance.
    Type: AWS::EC2::KeyPair::KeyName
  AMIId:
    Description: Name of a Parameter Store parameter that stores the ID of the Amazon Machine Image (AMI).
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
Resources:
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable SSH access via port 22
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
  Ec2Instance:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: !Ref KeyName
      ImageId: !Ref AMIId
      NetworkInterfaces:
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"
          SubnetId: !Ref PublicSubnetId
          GroupSet:
            - !Ref InstanceSecurityGroup
Outputs:
  InstanceId:
    Value: !Ref Ec2Instance
```

### 스택을 생성하는 AWS CLI 명령
<a name="cloudformation-supplied-parameter-types-cli-command"></a>

다음 [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack.html) 명령은 예제 템플릿을 기초로 스택을 생성합니다.

```
aws cloudformation create-stack --stack-name MyStack \
  --template-body file://sampletemplate.json \
  --parameters \
ParameterKey="VpcId",ParameterValue="vpc-a123baa3" \
ParameterKey="PublicSubnetId",ParameterValue="subnet-123a351e" \
ParameterKey="KeyName",ParameterValue="MyKeyName" \
ParameterKey="AMIId",ParameterValue="MyParameterKey"
```

`List<AWS::EC2::Subnet::Id>`와 같이 문자열 목록을 허용하는 파라미터 유형을 사용하려면 다음 예와 같이 `ParameterValue` 내부의 쉼표를 이중 백슬래시로 이스케이프해야 합니다.

```
--parameters ParameterKey="SubnetIDs",ParameterValue="subnet-5ea0c127\\,subnet-6194ea3b\\,subnet-c87f2be0"
```

## 고려 사항
<a name="cloudformation-supplied-parameter-types-considerations"></a>

동적 참조를 사용하여 타사 자격 증명과 같은 민감한 구성 정의에 대한 액세스를 제한하는 것이 좋습니다. 자세한 내용은 [동적 참조를 사용하여 다른 서비스에 저장된 값 가져오기](dynamic-references.md) 섹션을 참조하세요.

템플릿 사용자가 다른 AWS 계정의 값을 지정할 수 있도록 하려면 AWS 특정 파라미터 유형을 사용하지 마세요. 대신 `String` 또는 `CommaDelimitedList` 유형의 파라미터를 정의하세요.

Systems Manager 파라미터 유형과 관련하여 몇 가지 유의해야 할 사항이 있습니다.
+ 확인된 파라미터 값은 콘솔의 스택 **파라미터** 탭에서 확인하거나 [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) 또는 [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-change-set.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-change-set.html)를 실행하여 확인할 수 있습니다. 이러한 값은 스택이 생성되거나 업데이트될 때 설정되므로 Parameter Store의 최신 값과 다를 수 있습니다.
+ 스택 업데이트의 경우 **기존 값 사용** 옵션을 사용하거나 `UsePreviousValue`를 true로 설정하면 해당 값이 아닌 동일한 Parameter Store 키를 계속 사용한다는 의미입니다. CloudFormation은 항상 최신 값을 검색합니다.
+ 허용되는 값이나 기타 제약 조건을 지정하는 경우 CloudFormation은 지정한 파라미터 키에 대해 이를 검증하지만 해당 값은 검증하지 않습니다. Parameter Store 자체에서 값을 검증해야 합니다.
+ 스택을 생성하거나 업데이트하고 변경 세트를 생성할 때 CloudFormation은 해당 시점에 Parameter Store에 있는 임의의 값을 사용합니다. 지정한 파라미터가 호출자의 AWS 계정과 연결된 Parameter Store에 없는 경우 CloudFormation은 검증 오류를 반환합니다.
+ 변경 세트를 실행하면, CloudFormation은 변경 세트에서 지정한 값을 사용합니다. 변경 세트를 실행하기 전에 값을 확인해야 합니다. 변경 세트를 생성해 실행하는 동안 Parameter Store에서 변경될 수 있기 때문입니다.
+ 동일한 AWS 계정에 저장된 Parameter Store 파라미터의 경우 파라미터 이름을 제공해야 합니다. 다른 AWS 계정에서 공유하는 Parameter Store 파라미터의 경우 전체 파라미터 ARN을 제공해야 합니다.

## 지원되는 AWS 특정 파라미터 유형
<a name="aws-specific-parameter-types-supported"></a>

CloudFormation에서는 다음과 같은 AWS 관련 유형을 지원합니다.

`AWS::EC2::AvailabilityZone::Name`  
가용 영역(예: `us-west-2a`).

`AWS::EC2::Image::Id`  
Amazon EC2 이미지 ID(예: `ami-0ff8a91507f77f867`). CloudFormation 콘솔은 이 파라미터 유형에 대해 드롭다운 값 목록을 표시하지 않습니다.

`AWS::EC2::Instance::Id`  
Amazon EC2 인스턴스 ID(예: `i-1e731a32`).

`AWS::EC2::KeyPair::KeyName`  
Amazon EC2 키 페어 이름.

`AWS::EC2::SecurityGroup::GroupName`  
기본 VPC 보안 그룹 이름(예: `my-sg-abc`).

`AWS::EC2::SecurityGroup::Id`  
보안 그룹 ID(예: `sg-a123fd85`).

`AWS::EC2::Subnet::Id`  
서브넷 ID(예: `subnet-123a351e`).

`AWS::EC2::Volume::Id`  
Amazon EBS 볼륨 ID(예: `vol-3cdd3f56`).

`AWS::EC2::VPC::Id`  
VPC ID(예: `vpc-a123baa3`).

`AWS::Route53::HostedZone::Id`  
Amazon Route 53 호스팅 영역 ID(예: `Z23YXV4OVPL04A`).

`List<AWS::EC2::AvailabilityZone::Name>`  
리전 가용 영역 어레이(예: `us-west-2a, us-west-2b`).

`List<AWS::EC2::Image::Id>`  
Amazon EC2 이미지 ID 어레이(예: `ami-0ff8a91507f77f867, ami-0a584ac55a7631c0c`). CloudFormation 콘솔은 이 파라미터 유형에 대해 드롭다운 값 목록을 표시하지 않습니다.

`List<AWS::EC2::Instance::Id>`  
Amazon EC2 인스턴스 ID 어레이(예: `i-1e731a32, i-1e731a34`).

`List<AWS::EC2::SecurityGroup::GroupName>`  
기본 VPC 보안 그룹 이름 어레이(예: `my-sg-abc, my-sg-def`).

`List<AWS::EC2::SecurityGroup::Id>`  
보안 그룹 ID 어레이(예: `sg-a123fd85, sg-b456fd85`).

`List<AWS::EC2::Subnet::Id>`  
서브넷 ID 어레이(예: `subnet-123a351e, subnet-456b351e`).

`List<AWS::EC2::Volume::Id>`  
Amazon EBS 볼륨 ID 어레이(예: `vol-3cdd3f56, vol-4cdd3f56`).

`List<AWS::EC2::VPC::Id>`  
VPC ID 어레이(예: `vpc-a123baa3, vpc-b456baa3`).

`List<AWS::Route53::HostedZone::Id>`  
Amazon Route 53 호스팅 영역 ID 어레이(예: `Z23YXV4OVPL04A, Z23YXV4OVPL04B`).

## 지원되는 Systems Manager 파라미터 유형
<a name="systems-manager-parameter-types-supported"></a>

CloudFormation은 다음과 같은 Systems Manager 파라미터 유형을 지원합니다.

`AWS::SSM::Parameter::Name`  
시스템 관리자 파라미터 키의 이름입니다. 이 파라미터 유형은 필수 파라미터가 존재하는지 확인하는 데만 사용합니다. CloudFormation은 파라미터와 연결된 실제 값을 검색하지 않습니다.

`AWS::SSM::Parameter::Value<String>`  
값이 문자열인 시스템 관리자 파라미터입니다. 이는 Parameter Store의 `String` 파라미터 유형과 일치합니다.

`AWS::SSM::Parameter::Value<List<String>>` 또는 `AWS::SSM::Parameter::Value<CommaDelimitedList>`  
값이 문자열 목록인 시스템 관리자 파라미터입니다. 이는 Parameter Store의 `StringList` 파라미터 유형과 일치합니다.

`AWS::SSM::Parameter::Value<AWS-specific parameter type>`  
값이 AWS 특정 파라미터 유형인 Systems Manager 파라미터입니다.  
다음은 `AWS::EC2::KeyPair::KeyName` 유형을 지정하는 예제입니다.  
+ `AWS::SSM::Parameter::Value<AWS::EC2::KeyPair::KeyName>`

`AWS::SSM::Parameter::Value<List<AWS-specific parameter type>>`  
값이 AWS 특정 파라미터 유형 목록인 Systems Manager 파라미터입니다.  
다음은 `AWS::EC2::KeyPair::KeyName` 유형 목록을 지정하는 예제입니다.  
+ `AWS::SSM::Parameter::Value<List<AWS::EC2::KeyPair::KeyName>>`

## 지원되지 않는 Systems Manager 파라미터 유형
<a name="systems-manager-parameter-types-unsupported"></a>

CloudFormation은 다음 Systems Manager 파라미터 유형을 지원하지 않습니다.
+ Systems Manager 파라미터 유형 목록(예: `List<AWS::SSM::Parameter::Value<String>>`)

추가로 CloudFormation에서는 `SecureString` Systems Manager 파라미터 유형으로 템플릿 파라미터를 정의하는 것을 지원하지 않습니다. 하지만 보안 문자열을 특정 리소스에 대한 파라미터 **값으로 지정할 수 있습니다. 자세한 내용은 [동적 참조를 사용하여 다른 서비스에 저장된 값 가져오기](dynamic-references.md) 섹션을 참조하세요.

# CloudFormation 연습
<a name="walkthroughs"></a>

이 설명서에서는 스택 배포를 직접 실습할 수 있도록 설계된 연습 모음을 제공합니다.
+ [다른 CloudFormation 스택의 리소스 출력 참조](walkthrough-crossstackref.md) - 이 연습에서는 다른 스택 내에서 한 CloudFormation 스택의 출력을 참조하는 방법을 보여줍니다. 단일 스택의 모든 리소스를 포함하는 대신 별도의 스택에서 관련 AWS 리소스를 생성하여 보다 모듈화되고 재사용 가능한 템플릿을 생성할 수 있습니다.
+ [Amazon EC2에 애플리케이션 배포](deploying.applications.md) - CloudFormation을 사용하여 Amazon EC2 인스턴스에 애플리케이션을 자동으로 설치, 구성 및 시작하는 방법을 알아보세요. 이렇게 하면 인스턴스에 직접 연결하지 않고도 배포를 쉽게 복제하고 기존 설치를 업데이트할 수 있습니다.
+ [CloudFormation 스택 업데이트](updating.stacks.walkthrough.md) - CloudFormation에서 실행 중인 스택에 대한 간단한 업데이트 진행 과정을 살펴보겠습니다.
+ [조정 및 로드 밸런싱된 애플리케이션 생성](walkthrough-autoscaling.md) - CloudFormation을 사용하여 확장 가능하고 로드 밸런싱된 애플리케이션을 생성하는 방법을 알아보세요. 이 연습에서는 애플리케이션이 다양한 트래픽 부하를 처리하고 고가용성을 유지할 수 있도록 Auto Scaling 그룹, 로드 밸런서 및 기타 관련 리소스를 생성하는 방법을 다룹니다.
+ [다른 AWS 계정의 VPC와 피어링](peer-with-vpc-in-another-account.md) - 이 연습에서는 서로 다른 AWS 계정에 있는 두 VPC 간에 가상 프라이빗 클라우드(VPC) 피어링 연결을 생성하는 프로세스를 안내합니다. VPC 피어링을 사용하면 VPC 간에 트래픽을 라우팅하고 마치 동일한 네트워크에 속한 것처럼 리소스에 액세스할 수 있습니다.
+ [CloudFormation을 사용하여 CodeDeploy를 통한 ECS 블루/그린 배포 수행](blue-green.md) - CloudFormation을 사용하여 Amazon ECS에서 AWS CodeDeploy 블루/그린 배포를 수행하는 방법을 알아봅니다. 블루/그린 배포는 최소한의 가동 중지 시간으로 애플리케이션이나 서비스를 업데이트하는 방법입니다.

# 다른 CloudFormation 스택의 리소스 출력 참조
<a name="walkthrough-crossstackref"></a>

이 연습에서는 다른 스택 내에서 한 CloudFormation 스택의 출력을 참조하여 보다 모듈화되고 재사용 가능한 템플릿을 생성하는 방법을 보여줍니다.

단일 스택의 모든 리소스를 포함하는 대신 별도의 스택에서 관련 AWS 리소스를 생성합니다. 그런 다음 다른 스택의 필수 리소스 출력을 참조할 수 있습니다. 교차 스택 참조를 출력으로 제한하여 다른 스택에서 참조되는 스택 부분을 제어합니다.

예를 들어, VPC, 보안 그룹 및 퍼블릭 웹 애플리케이션의 서브넷을 포함하는 네트워크 스택과 별도의 퍼블릭 웹 애플리케이션 스택이 있습니다. 웹 애플리케이션에서 네트워크 스택의 보안 그룹과 서브넷을 사용하도록 하려면 웹 애플리케이션 스택에서 네트워크 스택의 리소스 출력을 참조하도록 허용하는 교차 스택 참조를 생성합니다. 교차 스택 참조를 사용하면 웹 애플리케이션 스택 소유자가 네트워킹 규칙 또는 자산을 생성하거나 유지할 필요가 없습니다.

교차 스택 참조를 생성하려면 `Export` 출력 필드를 사용하여 내보낼 리소스 출력 값에 플래그를 표시합니다. 그런 다음 `Fn::ImportValue` 내장 함수를 사용하여 값을 가져옵니다. 자세한 내용은 [배포된 CloudFormation 스택에서 내보낸 출력 가져오기](using-cfn-stack-exports.md) 섹션을 참조하세요.

**참고**  
CloudFormation은 무료 서비스입니다. 하지만 스택에 포함시키는 AWS 리소스에 대해서는 리소스별 현재 시세로 요금이 청구됩니다. AWS 요금에 대한 자세한 내용은 [각 제품의 세부 정보 페이지](https://aws.amazon.com/)를 참조하십시오.

**Topics**
+ [샘플 템플릿을 사용하여 네트워크 스택 생성](#walkthrough-crossstackref-create-vpc-stack)
+ [샘플 템플릿을 사용하여 웹 애플리케이션 스택 생성](#walkthrough-crossstackref-create-ec2-stack)
+ [스택이 설계대로 작동하는지 확인](#walkthrough-crossstackref-verify)
+ [AMI 매핑 오류 해결](#walkthrough-crossstackref-troubleshooting-ami)
+ [리소스 정리](#walkthrough-crossstackref-clean-up)

## 샘플 템플릿을 사용하여 네트워크 스택 생성
<a name="walkthrough-crossstackref-create-vpc-stack"></a>

이 연습을 시작하기 전에 Amazon VPC, Amazon EC2 및 CloudFormation 서비스를 모두 사용할 수 있는 IAM 권한이 있는지 확인합니다.

네트워크 스택에는 웹 애플리케이션 스택에서 사용할 VPC, 보안 그룹 및 서브넷이 포함되어 있습니다. 이러한 리소스 외에 네트워크 스택에서는 퍼블릭 액세스를 활성화하기 위해 인터넷 게이트웨이 및 라우팅 테이블을 생성합니다.

웹 애플리케이션 스택을 생성하기 전에 이 스택을 생성해야 합니다. 웹 애플리케이션 스택을 먼저 생성한 경우에는 보안 그룹 또는 서브넷이 없습니다.

스택 템플릿은 [https://s3.amazonaws.com/cloudformation-examples/user-guide/cross-stack/SampleNetworkCrossStack.template](https://s3.amazonaws.com/cloudformation-examples/user-guide/cross-stack/SampleNetworkCrossStack.template)에서 제공됩니다. 스택에서 생성되는 리소스를 보려면 링크를 선택하여 템플릿을 엽니다. `Outputs` 섹션에서 샘플 템플릿에서 내보내는 네트워킹 리소스를 확인할 수 있습니다. 다른 스택의 네트워킹 리소스를 내보낼 경우 내보낸 리소스의 이름에 스택 이름이 접두사로 붙습니다. 사용자가 네트워킹 리소스를 가져올 때 리소스를 가져올 스택을 지정할 수 있습니다.

**네트워크 스택을 생성하려면**

1. AWS Management Console에 로그인하여 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)에서 CloudFormation 콘솔을 엽니다.

1. **스택** 페이지에서 오른쪽 상단의 **스택 생성**을 선택하고 **새 리소스 사용(표준)**을 선택합니다.

1. **기존 템플릿 선택**을 선택하고 **템플릿 지정** 섹션에서 **Amazon S3 URL**을 선택합니다.

1. **Amazon S3 URL**에 다음 URL을 붙여넣습니다. **https://s3.amazonaws.com/cloudformation-examples/user-guide/cross-stack/SampleNetworkCrossStack.template**.

1. **다음**을 선택합니다.

1. **스택 이름**에 **SampleNetworkCrossStack**을 입력하고 **다음**을 선택합니다.
**참고**  
이 스택의 이름을 기록해 둡니다. 웹 애플리케이션 스택을 시작할 때 스택 이름이 필요합니다.

1. **다음**을 선택합니다. 이 연습에서는 태그를 추가하거나 고급 설정을 지정할 필요가 없습니다.

1. 스택 이름과 템플릿 URL이 올바른지 확인한 다음 **스택 생성**을 선택합니다.

   CloudFormation에서 스택을 생성하는 데 몇 분 정도 걸릴 수 있습니다. 모든 리소스가 생성될 때까지 기다렸다가 웹 애플리케이션 스택 생성을 계속합니다.

1. 진행 상황을 모니터링하려면 스택 이벤트를 확인합니다. 자세한 내용은 [스택 진행 상황 모니터링](monitor-stack-progress.md) 섹션을 참조하세요.

## 샘플 템플릿을 사용하여 웹 애플리케이션 스택 생성
<a name="walkthrough-crossstackref-create-ec2-stack"></a>

웹 애플리케이션 스택에서는 네트워크 스택에서 보안 그룹 및 서브넷을 사용하는 EC2 인스턴스를 생성합니다.

네트워크 스택과 동일한 AWS 리전에서 이 스택을 생성해야 합니다.

스택 템플릿은 [https://s3.amazonaws.com/cloudformation-examples/user-guide/cross-stack/SampleWebAppCrossStack.template](https://s3.amazonaws.com/cloudformation-examples/user-guide/cross-stack/SampleWebAppCrossStack.template)에서 제공됩니다. 스택에서 생성되는 리소스를 보려면 링크를 선택하여 템플릿을 엽니다. `Resources` 섹션에서 EC2 인스턴스의 속성을 봅니다. `Fn::ImportValue` 함수를 사용하여 다른 스택에서 네트워킹 리소스를 가져오는 방법을 확인할 수 있습니다.

**웹 애플리케이션 스택을 생성하려면**

1. **스택** 페이지의 오른쪽 상단에서 **스택 생성**을 선택하고 **새 리소스 사용(표준)**을 선택합니다.

1. **기존 템플릿 선택**을 선택하고 **템플릿 지정** 섹션에서 **Amazon S3 URL**을 선택합니다.

1. **Amazon S3 URL**에 다음 URL을 붙여넣습니다. **https://s3.amazonaws.com/cloudformation-examples/user-guide/cross-stack/SampleWebAppCrossStack.template**.

1. **다음**을 선택합니다.

1. **스택 이름**에는 **SampleWebAppCrossStack**을 입력합니다. **파라미터** 섹션에서 **NetworkStackName** 파라미터에 대한 기본값을 사용한 다음 **다음**을 선택합니다.

   샘플 템플릿에서는 파라미터 값을 사용하여 값을 가져올 스택을 지정합니다.

1. **다음**을 선택합니다. 이 연습에서는 태그를 추가하거나 고급 설정을 지정할 필요가 없습니다.

1. 스택 이름과 템플릿 URL이 올바른지 확인한 다음 **스택 생성**을 선택합니다.

   CloudFormation에서 스택을 생성하는 데 몇 분 정도 걸릴 수 있습니다.

## 스택이 설계대로 작동하는지 확인
<a name="walkthrough-crossstackref-verify"></a>

스택이 생성된 이후에 리소스를 보고 인스턴스 ID를 기록해 둡니다. 스택 리소스 보기에 대한 자세한 내용은 [CloudFormation 콘솔에서 스택 정보 보기](cfn-console-view-stack-data-resources.md) 단원을 참조하십시오.

인스턴스의 보안 그룹과 서브넷을 확인하려면 [Amazon EC2 콘솔](https://console.aws.amazon.com/ec2/)에서 인스턴스의 속성을 봅니다. 인스턴스에서 `SampleNetworkCrossStack` 스택의 보안 그룹 및 서브넷을 사용하는 경우 교차 스택 참조를 성공적으로 생성한 것입니다.

콘솔을 사용하여 스택 출력과 예제 웹 사이트 URL을 보고 웹 애플리케이션이 실행 중인지 확인합니다. 자세한 내용은 [CloudFormation 콘솔에서 스택 정보 보기](cfn-console-view-stack-data-resources.md) 섹션을 참조하세요.

## AMI 매핑 오류 해결
<a name="walkthrough-crossstackref-troubleshooting-ami"></a>

`Template error: Unable to get mapping for AWSRegionArch2AMI::[region]::HVM64` 오류가 발생하면 AWS 리전에 대한 AMI 매핑이 템플릿에 포함되지 않습니다. 매핑을 업데이트하는 대신 Systems Manager 퍼블릭 파라미터를 사용하여 최신 AMI를 동적으로 참조하는 것이 좋습니다.

1. [https://s3.amazonaws.com/cloudformation-examples/user-guide/cross-stack/SampleWebAppCrossStack.template](https://s3.amazonaws.com/cloudformation-examples/user-guide/cross-stack/SampleWebAppCrossStack.template)에서 로컬 시스템에 `SampleWebAppCrossStack` 템플릿을 다운로드합니다.

1. 전체 `AWSRegionArch2AMI` 매핑 섹션을 삭제합니다.

1. 다음 Systems Manager 파라미터를 추가합니다.

   ```
   "LatestAmiId": {
     "Description": "The latest Amazon Linux 2 AMI from the Parameter Store",
       "Type": "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>",
       "Default": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
     }
   ```

1. 기존 `ImageId` 참조를 바꿉니다.

   ```
   "ImageId": { "Fn::FindInMap": [ "AWSRegionArch2AMI", { "Ref": "AWS::Region" } , "HVM64" ] }, 
   ```

   변경 후:

   ```
   "ImageId": { "Ref": "LatestAmiId" },
   ```

   이 파라미터는 스택을 배포하는 리전의 최신 Amazon Linux 2 AMI로 자동 확인됩니다.

   다른 Linux 배포판의 경우 적절한 파라미터 경로를 사용합니다. 자세한 내용은 *AWS Systems Manager 사용 설명서*의 [Parameter Store에서 퍼블릭 파라미터 검색](https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-finding-public-parameters.html)을 참조하세요.

1. 계정의 S3 버킷에 수정된 템플릿을 업로드합니다.

   ```
   aws s3 cp SampleWebAppCrossStack.template s3://amzn-s3-demo-bucket/
   ```

1. 스택을 생성할 때 예시 URL 대신 S3 템플릿 URL을 지정합니다.

## 리소스 정리
<a name="walkthrough-crossstackref-clean-up"></a>

원치 않는 서비스에 대해 요금이 청구되지 않도록 하려면 스택을 삭제합니다.

**스택을 삭제하려면**

1. CloudFormation 콘솔에서 `SampleWebAppCrossStack` 스택을 선택합니다.

1. **작업**을 선택한 다음 **스택 삭제**를 선택합니다.

1. 확인 메시지에서 **삭제**를 선택합니다.

1. 스택이 삭제된 후 `SampleNetworkCrossStack` 스택에 대해 동일한 단계를 반복합니다.
**참고**  
CloudFormation에서 `SampleWebAppCrossStack` 스택을 완전히 삭제할 때까지 기다립니다. EC2 인스턴스가 VPC에서 계속 실행 중인 경우 CloudFormation은 `SampleNetworkCrossStack` 스택에서 VPC를 삭제하지 않습니다.

# Amazon EC2에 애플리케이션 배포
<a name="deploying.applications"></a>

CloudFormation을 사용하여 Amazon EC2 인스턴스에서 애플리케이션을 자동으로 설치, 구성 및 시작할 수 있습니다. 그러면 인스턴스에 연결하지 않고 배포를 쉽게 복제하고 기존 설치를 업데이트할 수 있으므로, 많은 시간과 노력을 절약할 수 있습니다.

CloudFormation에는 `cloud-init`를 기반으로 하는 헬퍼 스크립트(`cfn-init`, `cfn-signal`, `cfn-get-metadata`, `cfn-hup`) 세트가 포함되어 있습니다. CloudFormation 템플릿에서 이러한 헬퍼 스크립트를 호출하여 동일한 템플릿에 있는 Amazon EC2 인스턴스에서 애플리케이션을 설치, 구성 및 업데이트합니다. 자세한 내용은 *CloudFormation 템플릿 참조 가이드*의 [CloudFormation 헬퍼 스크립트 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/cfn-helper-scripts-reference.html)를 참조하세요.

[시작하기 자습서](gettingstarted.walkthrough.md)에서는 기본 bash 스크립트와 `UserData`를 함께 사용하여 간단한 웹 서버를 생성했습니다. 이는 간단한 ‘Hello World’ 페이지에는 효과적이지만, 실제 애플리케이션에는 다음과 같은 보다 복잡한 구성이 필요한 경우가 많습니다.
+ 여러 소프트웨어 패키지가 올바른 순서로 설치되어야 합니다.
+ 특정 콘텐츠를 사용하여 복잡한 구성 파일을 생성해야 합니다.
+ 서비스가 시작되고 자동으로 실행되도록 구성된 상태여야 합니다.
+ 설정 프로세스의 오류 처리 및 검증이 구성되어 있어야 합니다.

CloudFormation의 헬퍼 스크립트는 `UserData`의 기본 bash 스크립트보다 더 강력하고 유지 관리가 용이한 EC2 인스턴스 구성 방법을 제공합니다. `cfn-init` 헬퍼 스크립트는 템플릿의 메타데이터에서 구성 데이터를 읽고 이를 인스턴스에 체계적으로 적용합니다.

이 자습서에서는 `cfn-init` 헬퍼 스크립트를 사용하고 부트스트래핑 프로세스를 모니터링하는 방법을 알아봅니다.

**참고**  
CloudFormation은 무료이지만 생성하는 Amazon EC2 리소스에 대해서는 요금이 부과됩니다. 그러나 AWS를 처음 사용하는 경우 [프리 티어](https://aws.amazon.com/free/)를 활용하여 이 학습 프로세스 중에 비용을 최소화하거나 제거할 수 있습니다.

**Topics**
+ [사전 조건](#bootstrapping-tutorial-prerequisites)
+ [부트스트랩 개념 이해](#bootstrapping-tutorial-understand-concepts)
+ [간단한 부트스트랩 예로 시작하기](#bootstrapping-tutorial-simple-example)
+ [파일 및 명령 추가](#bootstrapping-tutorial-add-complexity)
+ [네트워크 보안 추가](#bootstrapping-tutorial-security-group)
+ [완전한 부트스트랩 템플릿](#bootstrapping-tutorial-complete-template)
+ [콘솔을 사용하여 스택 생성](#bootstrapping-tutorial-create-stack)
+ [부트스트랩 프로세스 모니터링](#bootstrapping-tutorial-validate-bootstrap)
+ [부트스트래핑된 웹 서버 테스트](#bootstrapping-tutorial-test-web-server)
+ [부트스트랩 문제 해결](#bootstrapping-tutorial-troubleshooting)
+ [리소스 정리](#bootstrapping-tutorial-clean-up)
+ [다음 단계](#bootstrapping-tutorial-next-steps)

## 사전 조건
<a name="bootstrapping-tutorial-prerequisites"></a>
+ [첫 번째 스택 생성](gettingstarted.walkthrough.md) 자습서를 완료했거나, 그에 준하는 CloudFormation 관련 기본 지식이 있어야 합니다.
+ Amazon EC2 및 CloudFormation을 사용할 수 있는 권한을 보유한 IAM 사용자 또는 역할이 있는 AWS 계정에 대한 액세스 권한 또는 관리 사용자 액세스 권한이 있어야 합니다.
+ 인터넷에 액세스할 수 있는 가상 프라이빗 클라우드(VPC)가 있어야 합니다. 이 자습서 템플릿에는 최신 AWS 계정과 함께 자동으로 제공되는 기본 VPC가 필요합니다. 기본 VPC가 없거나 삭제된 경우에 적용되는 다른 해결 방법은 [첫 번째 스택 생성](gettingstarted.walkthrough.md) 자습서의 문제 해결 섹션을 참조하세요.

## 부트스트랩 개념 이해
<a name="bootstrapping-tutorial-understand-concepts"></a>

템플릿을 생성하기 전에 부트스트래핑의 작동과 관련한 주요 개념을 알아보겠습니다.

### `cfn-init` 헬퍼 스크립트
<a name="bootstrapping-tutorial-cfn-init-overview"></a>

CloudFormation은 Amazon EC2 인스턴스에서 소프트웨어를 설치하고 서비스를 시작하는 데 사용할 수 있는 Python 헬퍼 스크립트 세트를 제공합니다. `cfn-init` 스크립트는 템플릿에서 리소스 메타데이터를 읽고, 해당 구성을 인스턴스에 적용합니다.

이 프로세스는 다음과 같이 작동합니다.

1. 사용자가 EC2 리소스의 `Metadata` 섹션에서 구성을 정의합니다.

1. `UserData` 스크립트에서 `cfn-init`를 직접적으로 호출합니다.

1. `cfn-init`가 메타데이터를 읽고 구성을 적용합니다.

1. 인스턴스는 사용자가 지정한 설정에 따라 구성됩니다.

### 메타데이터 구조
<a name="bootstrapping-tutorial-metadata-structure"></a>

구성은 EC2 인스턴스 내에 특정한 구조로 정의됩니다.

```
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Metadata:                       # Metadata section for the resource
      AWS::CloudFormation::Init:    # Required key that cfn-init looks for
        config:                     # Configuration name (you can have multiple)
          packages:                 # Install packages
          files:                    # Create files
          commands:                 # Run commands
          services:                 # Start/stop services
```

`cfn-init` 스크립트는 패키지, 그룹, 사용자, 소스, 파일, 명령 및 서비스 순으로 이러한 섹션을 처리합니다.

## 간단한 부트스트랩 예로 시작하기
<a name="bootstrapping-tutorial-simple-example"></a>

Apache를 설치하고 시작하는 간단한 부트스트랩 예로 시작해 보겠습니다.

```
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Metadata:
      AWS::CloudFormation::Init:
        config:
          packages:                 # Install Apache web server
            yum:
              httpd: []
          services:                 # Start Apache and enable it to start on boot
            systemd:
              httpd:
                enabled: true
                ensureRunning: true
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: !Ref InstanceType
      UserData: !Base64             # Script that runs when instance starts
        Fn::Sub: |
          #!/bin/bash
          yum install -y aws-cfn-bootstrap
          /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource EC2Instance --region ${AWS::Region}
```

이 간단한 예는 핵심 개념을 보여줍니다.
+ `packages` 섹션에서는 yum을 사용하여 `httpd` 패키지를 설치합니다. 이는 Amazon Linux 및 yum을 사용하는 기타 Linux 배포판에서 작동합니다.
+ `services` 섹션은 `httpd`가 자동으로 시작되고 실행되도록 합니다.
+ `UserData`는 최신 부트스트랩 도구를 설치하고 `cfn-init`를 직접적으로 호출합니다.

## 파일 및 명령 추가
<a name="bootstrapping-tutorial-add-complexity"></a>

이제 EC2 인스턴스의 `/var/log` 디렉터리에 사용자 지정 웹 페이지와 로그 파일을 추가하여 이 예를 개선해 보겠습니다.

### 파일 생성
<a name="bootstrapping-tutorial-files-section"></a>

`files` 섹션에서는 특정 콘텐츠가 포함된 파일을 인스턴스에 생성할 수 있습니다. 세로 파이프(`|`)를 사용하면 텍스트의 리터럴 블록(HTML 코드)을 파일(`/var/www/html/index.html`)의 콘텐츠로 전달할 수 있습니다.

```
files:
  /var/www/html/index.html:
    content: |
      <body>
        <h1>Congratulations, you have successfully launched the AWS CloudFormation sample.</h1>
      </body>
```

### 명령 실행
<a name="bootstrapping-tutorial-commands-section"></a>

`commands` 섹션은 부트스트랩 프로세스 중에 셸 명령을 실행하는 데 사용됩니다. 이 명령은 EC2 인스턴스의 `/var/log/welcome.txt`에 로그 파일을 생성합니다. 이 로그 파일을 보려면 SSH 액세스에 사용할 Amazon EC2 키 페어와 인스턴스에 대한 SSH에 사용 가능한 IP 주소 범위가 필요합니다(여기에서는 다루지 않음).

```
commands:
  createWelcomeLog:
    command: "echo 'cfn-init ran successfully!' > /var/log/welcome.txt"
```

## 네트워크 보안 추가
<a name="bootstrapping-tutorial-security-group"></a>

여기서는 웹 서버를 설정하는 것이므로 웹 트래픽(HTTP)이 EC2 인스턴스에 도달하도록 허용해야 합니다. 이를 위해 IP 주소에서 포트 80으로 들어오는 트래픽을 허용하는 보안 그룹을 생성합니다. 또한 EC2 인스턴스는 패키지 업데이트를 설치하는 등의 경우에 인터넷으로 트래픽을 전송해야 합니다. 기본적으로 보안 그룹은 나가는 트래픽을 모두 허용합니다. 다음으로 `SecurityGroupIds` 속성을 사용하여 이 보안 그룹을 EC2 인스턴스와 연결합니다.

```
WebServerSecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: Allow HTTP access from my IP address
    SecurityGroupIngress:
      - IpProtocol: tcp
        Description: HTTP
        FromPort: 80
        ToPort: 80
        CidrIp: !Ref MyIP
```

## 완전한 부트스트랩 템플릿
<a name="bootstrapping-tutorial-complete-template"></a>

이제 이 모든 요소를 하나로 결합해 보겠습니다. 다음은 앞서 설명한 모든 개념을 결합한 완전한 템플릿입니다.

```
AWSTemplateFormatVersion: 2010-09-09
Description: Bootstrap an EC2 instance with Apache web server using cfn-init

Parameters:
  LatestAmiId:
    Description: The latest Amazon Linux 2 AMI from the Parameter Store
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'

  InstanceType:
    Description: EC2 instance type
    Type: String
    Default: t2.micro
    AllowedValues:
      - t3.micro
      - t2.micro
    ConstraintDescription: must be a valid EC2 instance type.

  MyIP:
    Description: Your IP address in CIDR format (e.g. 203.0.113.1/32)
    Type: String
    MinLength: 9
    MaxLength: 18
    Default: 0.0.0.0/0
    AllowedPattern: '^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$'
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.

Resources:
  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP access from my IP address
      SecurityGroupIngress:
        - IpProtocol: tcp
          Description: HTTP
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref MyIP

  WebServer:
    Type: AWS::EC2::Instance
    Metadata:
      AWS::CloudFormation::Init:
        config:
          packages:
            yum:
              httpd: []
          files:
            /var/www/html/index.html:
              content: |
                <body>
                  <h1>Congratulations, you have successfully launched the AWS CloudFormation sample.</h1>
                </body>
          commands:
            createWelcomeLog:
              command: "echo 'cfn-init ran successfully!' > /var/log/welcome.txt"
          services:
            systemd:
              httpd:
                enabled: true
                ensureRunning: true
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: !Ref InstanceType
      SecurityGroupIds:
        - !Ref WebServerSecurityGroup
      UserData: !Base64
        Fn::Sub: |
          #!/bin/bash
          yum install -y aws-cfn-bootstrap
          /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServer --region ${AWS::Region}
      Tags:
        - Key: Name
          Value: Bootstrap Tutorial Web Server

Outputs:
  WebsiteURL:
    Value: !Sub 'http://${WebServer.PublicDnsName}'
    Description: EC2 instance public DNS name
```

## 콘솔을 사용하여 스택 생성
<a name="bootstrapping-tutorial-create-stack"></a>

다음 절차에는 파일에서 샘플 스택 템플릿을 업로드하는 절차가 포함됩니다. 로컬 시스템에서 텍스트 편집기를 열고 템플릿을 추가합니다. `samplelinux2stack.template` 이름으로 파일을 저장합니다.

**스택 템플릿을 시작하려면**

1. AWS Management Console에 로그인하여 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)에서 CloudFormation 콘솔을 엽니다.

1. **스택 생성**, **새 리소스 사용(표준)**를 선택합니다.

1. **템플릿 지정**에서 **템플릿 파일 업로드**, **파일 선택**을 차례로 선택하여 `samplelinux2stack.template` 파일을 업로드하세요.

1. **다음**을 선택합니다.

1. **스택 세부 정보 지정** 페이지에서 스택 이름으로 **BootstrapTutorialStack**을 입력합니다.

1. **파라미터**에서 다음을 수행합니다.
   + **LatestAmiId**: 기본값을 그대로 둡니다.
   + **InstanceType**: EC2 인스턴스 유형으로 **t2.micro** 또는 **t3.micro**를 선택합니다.
   + **MyIP**: `/32` 접미사를 사용하여 퍼블릭 IP 주소를 입력합니다.

1. **다음**을 두 번 선택한 다음 **제출**을 선택하여 스택을 생성합니다.

## 부트스트랩 프로세스 모니터링
<a name="bootstrapping-tutorial-validate-bootstrap"></a>

추가 소프트웨어를 설치 및 구성하므로 부트스트랩 프로세스는 단순히 EC2를 실행하는 경우보다 오래 걸립니다.

**부트스트랩 진행 상황을 모니터링하려면**

1. CloudFormation 콘솔에서 스택을 선택하고 **이벤트** 탭을 엽니다.

1. `WebServer CREATE_IN_PROGRESS` 이벤트를 살펴봅니다. 부트스트랩 프로세스는 인스턴스가 시작된 후에 시작됩니다.

1. 부트스트랩 프로세스는 일반적으로 몇 분 정도 걸립니다. 완료되면 `WebServer CREATE_COMPLETE`가 표시됩니다.

부트스트랩 프로세스 중에 발생하는 상황을 확인하려면 인스턴스 로그를 참조합니다.

**부트스트랩 로그를 보려면(선택 사항)**

1. [EC2 콘솔](https://console.aws.amazon.com/ec2/)을 열고 인스턴스를 찾습니다.

1. 인스턴스를 선택하고 **작업**, **모니터링 및 문제 해결**, **시스템 로그 가져오기**를 차례로 선택하여 부트스트랩 진행 상태를 확인합니다.

1. 로그가 즉시 표시되지 않으면 기다렸다가 페이지를 새로 고칩니다.

## 부트스트래핑된 웹 서버 테스트
<a name="bootstrapping-tutorial-test-web-server"></a>

스택이 `CREATE_COMPLETE`로 표시되면 웹 서버를 테스트합니다.

**웹 서버를 테스트하려면**

1. CloudFormation 콘솔에서 스택의 **출력** 탭으로 이동합니다.

1. **WebsiteURL** 값을 클릭하여 새 탭에서 웹 서버를 엽니다.

1. `Congratulations, you have successfully launched the AWS CloudFormation sample`이라는 메시지와 함께 사용자 지정 웹 페이지가 표시됩니다.

**참고**  
페이지가 즉시 로드되지 않으면 1분 정도 기다렸다가 다시 시도합니다. 스택이 `CREATE_COMPLETE`로 표시된 후에도 부트스트랩 프로세스가 완료되는 중일 수 있습니다.

## 부트스트랩 문제 해결
<a name="bootstrapping-tutorial-troubleshooting"></a>

부트스트랩 프로세스가 실패하거나 웹 서버가 작동하지 않는 경우, 원인이 될 수 있는 일반적인 문제와 해결 방법은 다음과 같습니다.

### 일반적인 문제
<a name="bootstrapping-tutorial-common-issues"></a>
+ **스택 생성 실패** - **이벤트** 탭에서 구체적인 오류 메시지를 확인합니다.
+ **웹 서버에 액세스할 수 없음** - `MyIP` 파라미터에서 IP 주소가 올바른지 확인합니다. 끝에 `/32`를 포함해야 합니다.
+ **부트스트랩 프로세스 실패** - 인스턴스는 시작되지만 `cfn-init`가 실패합니다. 모니터링 섹션의 설명에 따라 시스템 로그를 확인합니다.

## 리소스 정리
<a name="bootstrapping-tutorial-clean-up"></a>

요금이 지속적으로 부과되지 않도록 스택과 해당 리소스를 삭제하여 정리할 수 있습니다.

**스택 및 스택의 리소스를 삭제하려면**

1. [CloudFormation 콘솔](https://console.aws.amazon.com/cloudformation/)을 엽니다.

1. **스택** 페이지에서 생성한 스택의 이름(**BootstrapTutorialStack**) 옆에 있는 옵션을 선택한 다음 **삭제**를 선택합니다.

1. 확인 메시지가 나타나면 **삭제**를 선택합니다.

1. **이벤트** 탭에서 스택 삭제 프로세스의 진행 상황을 모니터링합니다. **BootstrapTutorialStack**의 상태를 `DELETE_IN_PROGRESS`로 변경합니다. CloudFormation에서 스택 삭제를 완료하면 목록에서 해당 스택이 제거됩니다.

## 다음 단계
<a name="bootstrapping-tutorial-next-steps"></a>

축하합니다\$1 지금까지 CloudFormation을 사용하여 EC2 인스턴스를 부트스트래핑하는 방법을 배웠습니다. 이제 다음을 이해했습니다.
+ `cfn-init` 헬퍼 스크립트 사용 방법
+ 부트스트래핑을 위한 메타데이터를 구성하는 방법
+ 패키지를 설치하고, 파일을 생성하고, 명령을 실행하고, 서비스를 관리하는 방법
+ 부트스트랩 문제를 모니터링하는 방법

계속 학습하려면:
+ 실행 중인 스택을 업데이트하고 `cfn-hup` 헬퍼 스크립트를 사용하는 방법에 대해 알아봅니다. 자세한 내용은 [CloudFormation 스택 업데이트](updating.stacks.walkthrough.md) 섹션을 참조하세요.
+ Windows 스택을 부트스트래핑하는 방법을 알아봅니다. 자세한 내용은 [Windows 기반 CloudFormation 스택 부트스트래핑](cfn-windows-stacks-bootstrapping.md) 섹션을 참조하세요.
+ 구성 세트가 여러 개인 더 복잡한 부트스트랩 시나리오를 살펴봅니다. 자세한 내용은 *CloudFormation 템플릿 참조 안내서*의 [cfn-init](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/cfn-init.html) 및 [AWS::CloudFormation::Init](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-init.html)를 참조하세요.
+ 부트스트랩 완료 상태 보고를 위한 `cfn-signal`에 대해 알아봅니다. 자세한 내용은 *CloudFormation 템플릿 참조 안내서*의 [cfn-signal](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/cfn-signal.html)을 참조하세요.

# CloudFormation 스택 업데이트
<a name="updating.stacks.walkthrough"></a>

**참고**  
이 자습서는 [Amazon EC2에 애플리케이션 배포](deploying.applications.md) 자습서에 제공된 개념을 기반으로 합니다. 이 자습서를 완료하지 않은 경우 먼저 CloudFormation에서 EC2 부트스트래핑을 이해하는 것이 좋습니다.

이 주제에서는 실행 중인 스택에 대한 간단한 업데이트 진행 상황을 보여줍니다. 다음 단계를 살펴보겠습니다.

1. **초기 스택 생성** – 기본 Amazon Linux 2 AMI를 사용하여 스택을 생성하고, CloudFormation 헬퍼 스크립트를 사용하여 Apache Web Server 및 간단한 PHP 애플리케이션을 설치합니다.

1. **애플리케이션 업데이트** - CloudFormation을 사용하여 애플리케이션의 파일 중 하나를 업데이트하고 소프트웨어를 배포합니다.

1. **키 페어 추가** - Amazon EC2 키 페어를 인스턴스에 추가한 다음, 인스턴스에 대한 SSH 액세스를 허용하도록 보안 그룹을 업데이트합니다.

1. **인스턴스 유형 업데이트** - 기존 Amazon EC2 인스턴스의 인스턴스 유형을 변경합니다.

1. **AMI 업데이트** - 스택에서 Amazon EC2 인스턴스용 Amazon Machine Image(AMI)를 변경합니다.

**참고**  
CloudFormation은 무료이지만 생성하는 Amazon EC2 리소스에 대해서는 요금이 부과됩니다. 그러나 AWS를 처음 사용하는 경우 [프리 티어](https://aws.amazon.com/free/)를 활용하여 이 학습 프로세스 중에 비용을 최소화하거나 제거할 수 있습니다.

**Topics**
+ [1단계: 초기 스택 생성](#update-stack-initial-stack)
+ [2단계: 애플리케이션 업데이트](#update-stack-update-application)
+ [3단계: 키 페어를 사용하여 SSH 액세스 추가](#update-stack-add-key-pair)
+ [4단계: 인스턴스 유형 업데이트](#update-stack-update-instance-type)
+ [5단계: AMI 업데이트](#update-stack-update-ami)
+ [가용성 및 영향 고려 사항](#update.walkthrough.impact)
+ [관련 리소스](#update.walkthrough.related)

## 1단계: 초기 스택 생성
<a name="update-stack-initial-stack"></a>

이 주제의 나머지 부분에서 사용할 수 있는 스택을 생성하는 것부터 시작합니다. 간단한 템플릿 하나를 제공했습니다. 이 템플릿은 Apache Web Server에 호스팅되고 Amazon Linux 2 AMI에서 실행 중인 단일 인스턴스 PHP 웹 애플리케이션을 시작합니다.

Apache Web Server, PHP 및 간단한 PHP 애플리케이션은 기본적으로 Amazon Linux 2 AMI에 설치되는 CloudFormation 헬퍼 스크립트를 통해 모두 설치됩니다. 다음 템플릿 코드 조각에서는 설치할 패키지와 파일(여기서는 Amazon Linux 2 AMI용 Yum 리포지토리의 Apache Web Server 및 PHP 인프라)을 설명하는 메타데이터를 표시합니다. 이 코드 조각에서는 Apache Web Server가 실행 중임을 보장하는 `Services` 섹션도 보여줍니다.

```
WebServerInstance:
  Type: AWS::EC2::Instance
  Metadata:
    AWS::CloudFormation::Init:
      config:
        packages:
          yum:
            httpd: []
            php: []
        files:
          /var/www/html/index.php:
            content: |
              <?php
              echo '<h1>Hello World!</h1>';
              ?>
            mode: '000644'
            owner: apache
            group: apache
        services:
          systemd:
            httpd:
              enabled: true
              ensureRunning: true
```

애플리케이션 자체는 전체가 템플릿 안에 정의되어 있는 'Hello World' 예제입니다. 실제 애플리케이션의 경우, 파일이 Amazon S3, GitHub 또는 다른 리포지토리에 저장되어 템플릿에서 참조될 수도 있습니다. CloudFormation은 패키지(예: RPM 또는 RubyGems)를 다운로드하고 개별 파일을 참조하며 `.zip` 및 `.tar` 파일의 압축을 풀어서 Amazon EC2 인스턴스에 애플리케이션 아티팩트를 생성할 수 있습니다.

이 템플릿은 `cfn-hup` 대몬이 Amazon EC2 인스턴스에 대한 메타데이터에 정의된 구성의 변경 내용을 수신하도록 구성하고 활성화합니다. `cfn-hup` 대몬을 사용하여 Apache 또는 PHP 버전 등 애플리케이션 소프트웨어를 업데이트하거나 CloudFormation에서 PHP 애플리케이션 파일 자체를 업데이트할 수 있습니다. 템플릿의 동일한 Amazon EC2 리소스에서 가져온 다음 코드 조각에서는 메타데이터에 대한 업데이트를 확인하고 적용하기 위해 2분마다 `cfn-init`를 직접적으로 호출하도록 `cfn-hup`를 구성하는 데 필요한 부분을 보여줍니다. 그렇지 않으면 시작 시 `cfn-init`가 한 번만 실행됩니다.

```
files:
  /etc/cfn/cfn-hup.conf:
    content: !Sub |
      [main]
      stack=${AWS::StackId}
      region=${AWS::Region}
      # The interval used to check for changes to the resource metadata in minutes. Default is 15
      interval=2
    mode: '000400'
    owner: root
    group: root
  /etc/cfn/hooks.d/cfn-auto-reloader.conf:
    content: !Sub |
      [cfn-auto-reloader-hook]
      triggers=post.update
      path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
      action=/opt/aws/bin/cfn-init -s ${AWS::StackId} -r WebServerInstance --region ${AWS::Region}
      runas=root
services:
  systemd:
    cfn-hup:
      enabled: true
      ensureRunning: true
      files:
        - /etc/cfn/cfn-hup.conf
        - /etc/cfn/hooks.d/cfn-auto-reloader.conf
```

스택을 완료하기 위해 Amazon EC2 인스턴스 정의의 `Properties` 섹션에서 `UserData` 속성에는 패키지 및 파일을 설치하기 위해 `cfn-init`를 직접적으로 호출하는 `cloud-init` 스크립트가 포함됩니다. 자세한 내용은 *CloudFormation 템플릿 참조 가이드*의 [CloudFormation 헬퍼 스크립트 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/cfn-helper-scripts-reference.html)를 참조하세요. 템플릿은 Amazon EC2 보안 그룹도 생성합니다.

```
AWSTemplateFormatVersion: 2010-09-09

Parameters:
  LatestAmiId:
    Description: The latest Amazon Linux 2 AMI from the Parameter Store
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'

  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: t3.micro
    AllowedValues:
      - t3.nano
      - t3.micro
      - t3.small
      - t3.medium
      - t3a.nano
      - t3a.micro
      - t3a.small
      - t3a.medium
      - m5.large
      - m5.xlarge
      - m5.2xlarge
      - m5a.large
      - m5a.xlarge
      - m5a.2xlarge
      - c5.large
      - c5.xlarge
      - c5.2xlarge
      - r5.large
      - r5.xlarge
      - r5.2xlarge
      - r5a.large
      - r5a.xlarge
      - r5a.2xlarge
    ConstraintDescription: must be a valid EC2 instance type.
    
Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: !Ref InstanceType
      SecurityGroupIds:
        - !Ref WebServerSecurityGroup
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          # Get the latest CloudFormation package
          yum update -y aws-cfn-bootstrap
          # Run cfn-init
          /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region} || error_exit 'Failed to run cfn-init'        
          # Start up the cfn-hup daemon to listen for changes to the EC2 instance metadata
          /opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'
          # Signal success or failure
          /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
    Metadata:
      AWS::CloudFormation::Init:
        config:
          packages:
            yum:
              httpd: []
              php: []
          files:
            /var/www/html/index.php:
              content: |
                <?php
                echo "<h1>Hello World!</h1>";
                ?>
              mode: '000644'
              owner: apache
              group: apache
            /etc/cfn/cfn-hup.conf:
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
                # The interval used to check for changes to the resource metadata in minutes. Default is 15
                interval=2
              mode: '000400'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:
              content: !Sub |
                [cfn-auto-reloader-hook]
                triggers=post.update
                path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
                action=/opt/aws/bin/cfn-init -s ${AWS::StackId} -r WebServerInstance --region ${AWS::Region}
                runas=root
          services:
            systemd:
              httpd:
                enabled: true
                ensureRunning: true
              cfn-hup:
                enabled: true
                ensureRunning: true
                files:
                  - /etc/cfn/cfn-hup.conf
                  - /etc/cfn/hooks.d/cfn-auto-reloader.conf
    CreationPolicy:
      ResourceSignal:
        Timeout: PT5M

  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

Outputs:
  WebsiteURL:
    Value: !Sub 'http://${WebServerInstance.PublicDnsName}'
    Description: URL of the web application
```

**이 템플릿에서 스택을 시작하는 방법**

1. 템플릿을 복사하여 텍스트 파일로 시스템에 로컬로 저장하세요. 이후 단계에서는 이 파일을 사용해야 하므로 이 위치를 적어둡니다.

1. AWS Management Console에 로그인하여 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)에서 CloudFormation 콘솔을 엽니다.

1. **스택 생성, 새 리소스 사용(표준)**을 선택하세요.

1. **기존 템플릿 선택**을 선택합니다.

1. **템플릿 지정**에서 **템플릿 파일 업로드**를 선택하고 첫 번째 단계에서 생성한 파일로 이동한 후 **다음**을 선택하세요.

1. **스택 세부 정보 지정** 페이지에서 스택 이름으로 **UpdateTutorial**을 입력하세요.

1. **파라미터**에서 모든 파라미터를 동일하게 유지하고 **다음**을 두 번 선택하세요.

1. **검토 및 생성** 화면에서 **제출**을 선택하세요.

스택 상태가 `CREATE_COMPLETE`가 된 후에는 **출력** 탭에 웹 사이트의 URL이 표시됩니다. `WebsiteURL` 출력 값을 선택하면 새 PHP 애플리케이션의 작동이 표시됩니다.

## 2단계: 애플리케이션 업데이트
<a name="update-stack-update-application"></a>

이제 스택을 배포했으며, 애플리케이션을 업데이트하겠습니다. 애플리케이션에서 출력되는 텍스트를 조금 변경해 보겠습니다. 이렇게 하기 위해 이 템플릿 코드 조각에 표시된 대로 index.php 파일에 echo 명령을 추가하겠습니다.

```
files:
  /var/www/html/index.php:
    content: |
      <?php
      echo "<h1>Hello World!</h1>";
      echo "<p>This is an updated version of our application.</p>";
      ?>
    mode: '000644'
    owner: apache
    group: apache
```

텍스트 편집기를 사용하여 로컬로 저장한 템플릿 파일을 수동으로 편집합니다.

이제 스택을 업데이트하세요.

**업데이트된 템플릿으로 스택을 업데이트하는 방법**

1. CloudFormation 콘솔에서 **UpdateTutorial** 스택을 선택하세요.

1. **업데이트, 직접 업데이트**를 선택하세요.

1. **기존 템플릿 교체**를 선택하세요.

1. **템플릿 지정**에서 **템플릿 파일 업로드**를 선택하고 템플릿을 업로드한 후 **다음**을 선택하세요.

1. **스택 세부 정보 지정** 페이지에서 모든 파라미터를 동일하게 유지하고 **다음**을 두 번 선택하세요.

1. **검토** 페이지에서 변경 내용을 검토하세요. **변경 내용**에서 CloudFormation이 `WebServerInstance` 리소스를 업데이트함을 확인할 수 있습니다.

1. **제출**을 선택합니다.

스택이 `UPDATE_COMPLETE` 상태이면 `WebsiteURL` 출력 값을 다시 선택하여 애플리케이션에서 적용한 변경 내용을 확인합니다. `cfn-hup` 대몬은 2분마다 실행되므로 스택이 업데이트되고 나서 애플리케이션이 변경하는 데 최대 2분이 걸릴 수 있습니다.

업데이트된 리소스 세트를 확인하려면 CloudFormation 콘솔로 이동합니다. **이벤트** 탭에서 스택 이벤트를 살펴봅니다. 이 특수한 경우에 Amazon EC2 인스턴스 `WebServerInstance`의 메타데이터가 업데이트되고, 이때 변경 내용이 없는지 확인하기 위해 CloudFormation에서 다른 리소스(`WebServerSecurityGroup`)를 다시 평가합니다. 다른 스택 리소스는 수정되지 않았습니다. CloudFormation은 스택 내에서 스택 변경에 영향을 받는 리소스만 업데이트합니다. 이러한 변경에는 속성이나 메타데이터 변경과 같은 직접적인 변경도 있고, `Ref`, `GetAtt` 또는 기타 내장 템플릿 함수를 통한 데이터 흐름이나 종속성으로 인한 간접적인 변경도 있을 수 있습니다. 자세한 내용은 [내장 함수 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference.html)를 참조하세요.

이 간단한 업데이트에서 프로세스를 보여줍니다. 그러나 Amazon EC2 인스턴스로 배포되는 파일 및 패키지에 대한 보다 복잡한 변경도 가능합니다. 예를 들면 MySQL에 대한 PHP 지원과 함께 인스턴스에 MySQL을 추가해야 할 수도 있습니다. 이렇게 하려면 추가 서비스와 함께 추가적인 패키지 및 파일을 구성에 추가하고 나서 변경 내용을 배포하도록 스택을 업데이트하기만 하면 됩니다.

```
packages:
  yum:
    httpd: []
    php: []
    mysql: []
    php-mysql: []
    mysql-server: []
    mysql-libs: []

  ...

services:
  systemd:
    httpd:
      enabled: true
      ensureRunning: true
    cfn-hup:
      enabled: true
      ensureRunning: true
      files:
        - /etc/cfn/cfn-hup.conf
        - /etc/cfn/hooks.d/cfn-auto-reloader.conf
    mysqld:
      enabled: true
      ensureRunning: true
```

CloudFormation 메타데이터를 업데이트하여 애플리케이션에 사용되는 패키지의 새 버전으로 업데이트합니다. 이전 예제에서는 각 패키지의 버전 속성이 비어 있어서 `cfn-init`가 패키지의 최신 버전을 설치해야 했습니다.

```
packages:
  yum:
    httpd: []
    php: []
```

원할 경우 패키지의 버전 문자열을 지정할 수 있습니다. 이후 업데이트 스택 직접 호출에서 버전 문자열을 변경하는 경우 패키지의 새 버전이 배포됩니다. 다음은 RubyGems 패키지의 버전 번호를 사용하는 예입니다. 버전 관리를 지원하는 패키지마다 특정 버전이 있을 수 있습니다.

```
packages:
  rubygems:
    mysql: []
    rubygems-update:
      - "1.6.2"
    rake:
      - "0.8.7"
    rails:
      - "2.3.11"
```

## 3단계: 키 페어를 사용하여 SSH 액세스 추가
<a name="update-stack-add-key-pair"></a>

템플릿에 원래 지정되지 않았던 속성을 추가하도록 템플릿에서 리소스를 업데이트할 수도 있습니다. 이를 보여주기 위해 Amazon EC2 키 페어를 기존 EC2 인스턴스에 추가하고 나서 Amazon EC2 보안 그룹에서 포트 22를 열어 Secure Shell(SSH)을 사용해 인스턴스에 액세스할 수 있도록 하겠습니다.

**Amazon EC2 인스턴스에 SSH 액세스를 추가하려면**

1. 템플릿에 기존 Amazon EC2 키 페어 및 SSH 위치의 이름을 전달할 추가 파라미터 두 개를 추가합니다.

   ```
   Parameters:
     KeyName:
       Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
       Type: AWS::EC2::KeyPair::KeyName
       ConstraintDescription: must be the name of an existing EC2 KeyPair.
   
     SSHLocation:
       Description: The IP address that can be used to SSH to the EC2 instances in CIDR format (e.g. 203.0.113.1/32)
       Type: String
       MinLength: 9
       MaxLength: 18
       Default: 0.0.0.0/0
       AllowedPattern: '^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$'
       ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
   ```

1. `KeyName` 속성을 Amazon EC2 인스턴스에 추가합니다.

   ```
   WebServerInstance:
     Type: AWS::EC2::Instance
     Properties:
       ImageId: !Ref LatestAmiId
       InstanceType: !Ref InstanceType
       KeyName: !Ref KeyName
       SecurityGroupIds:
         - !Ref WebServerSecurityGroup
   ```

1. 포트 22 및 SSH 위치를 Amazon EC2 보안 그룹의 수신 규칙에 추가합니다.

   ```
   WebServerSecurityGroup:
     Type: AWS::EC2::SecurityGroup
     Properties:
       GroupDescription: Enable HTTP access via port 80 and SSH access via port 22
       SecurityGroupIngress:
         - IpProtocol: tcp
           FromPort: 80
           ToPort: 80
           CidrIp: 0.0.0.0/0
         - IpProtocol: tcp
           FromPort: 22
           ToPort: 22
           CidrIp: !Ref SSHLocation
   ```

1. [2단계: 애플리케이션 업데이트](#update-stack-update-application)에 설명된 동일한 단계를 사용하여 스택을 업데이트합니다.

## 4단계: 인스턴스 유형 업데이트
<a name="update-stack-update-instance-type"></a>

이제 인스턴스 유형을 변경하여 기본 인프라를 업데이트하는 방법을 살펴보겠습니다.

지금까지 생성한 스택에는 t3.micro Amazon EC2 인스턴스가 사용됩니다. 새로 생성한 웹 사이트의 트래픽 양이 t3.micro 인스턴스에서 처리할 수 있는 것보다 점점 더 많아지고 있어서 m5.large Amazon EC2 인스턴스 유형으로 이동하려 한다고 가정합니다. 인스턴스 유형의 아키텍처가 변경되는 경우 다른 AMI로 인스턴스가 생성되어야 합니다. 그러나 t3.micro 및 m5.large 모두 동일한 CPU 아키텍처를 사용하고 Amazon Linux 2(x86\$164) AMI를 실행합니다. 자세한 내용은 *Amazon EC2 사용 설명서*의 [인스턴스 유형 변경을 위한 호환성](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/resize-limitations.html)을 참조하세요.

이전 단계에서 수정한 템플릿을 사용하여 인스턴스 유형을 변경해 보겠습니다. `InstanceType`이 템플릿에 대한 입력 파라미터이므로 템플릿을 수정할 필요가 없습니다. **스택 세부 정보 지정** 페이지에서 파라미터 값을 변경할 수 있습니다.

**스택을 새 파라미터 값으로 업데이트하는 방법**

1. CloudFormation 콘솔에서 **UpdateTutorial** 스택을 선택하세요.

1. **업데이트, 직접 업데이트**를 선택하세요.

1. **현재 템플릿 사용**을 선택하고 **다음**을 선택하세요.

1. **스택 세부 정보 지정** 페이지에서 **InstanceType** 텍스트 상자의 값을 `t3.micro`에서 `m5.large`로 변경하세요. 그리고 **다음**을 두 번 선택하세요.

1. **검토** 페이지에서 변경 내용을 검토하세요. **변경 내용**에서 CloudFormation이 `WebServerInstance` 리소스를 업데이트함을 확인할 수 있습니다.

1. **제출**을 선택합니다.

인스턴스를 시작했다가 중지하여 EBS 지원 Amazon EC2 인스턴스의 인스턴스 유형을 동적으로 변경할 수 있습니다. CloudFormation에서는 인스턴스 유형을 업데이트하고 인스턴스를 다시 시작하여 변경을 최적화하려고 하므로 인스턴스 ID가 변경되지 않습니다. 하지만 인스턴스가 다시 시작되는 경우 인스턴스의 퍼블릭 IP 주소가 변경됩니다. 변경 후 탄력적 IP 주소가 올바르게 바인딩되도록 하기 위해 CloudFormation에서 탄력적 IP 주소도 업데이트합니다. CloudFormation 콘솔의 **이벤트** 탭에서 변경 내용을 확인할 수 있습니다.

AWS Management Console에서 인스턴스 유형을 확인하려면 Amazon EC2 콘솔을 열고 해당 인스턴스를 찾습니다.

## 5단계: AMI 업데이트
<a name="update-stack-update-ami"></a>

이제 차세대 Amazon Linux인 Amazon Linux 2023을 사용하도록 스택을 업데이트해 보겠습니다.

AMI 업데이트는 인스턴스를 교체해야 하는 주요 변경 사항입니다. AMI를 수정하기 위해 단순히 인스턴스를 시작했다가 중지할 수 없으므로 CloudFormation은 이 작업을 리소스의 변경 불가능 속성에 대한 변경으로 간주합니다. 변경 불가능한 속성을 변경하려면 CloudFormation에서 대체 리소스(이 경우에는 새 AMI를 실행 중인 Amazon EC2 인스턴스)를 시작해야 합니다.

Amazon Linux 2023을 사용하도록 스택 템플릿을 업데이트하는 방법을 살펴보겠습니다. 주요 변경 사항으로, AMI 파라미터 업데이트 및 `yum`에서 `dnf` 패키지 관리자로의 변경이 포함됩니다.

```
AWSTemplateFormatVersion: 2010-09-09

Parameters:
  LatestAmiId:
    Description: The latest Amazon Linux 2023 AMI from the Parameter Store
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: '/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64'

  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: t3.micro
    AllowedValues:
      - t3.nano
      - t3.micro
      - t3.small
      - t3.medium
      - t3a.nano
      - t3a.micro
      - t3a.small
      - t3a.medium
      - m5.large
      - m5.xlarge
      - m5.2xlarge
      - m5a.large
      - m5a.xlarge
      - m5a.2xlarge
      - c5.large
      - c5.xlarge
      - c5.2xlarge
      - r5.large
      - r5.xlarge
      - r5.2xlarge
      - r5a.large
      - r5a.xlarge
      - r5a.2xlarge
    ConstraintDescription: must be a valid EC2 instance type.

  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: must be the name of an existing EC2 KeyPair.

  SSHLocation:
    Description: The IP address that can be used to SSH to the EC2 instances in CIDR format (e.g. 203.0.113.1/32)
    Type: String
    MinLength: 9
    MaxLength: 18
    Default: 0.0.0.0/0
    AllowedPattern: '^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$'
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
    
Resources:
  WebServerInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyName
      SecurityGroupIds:
        - !Ref WebServerSecurityGroup
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          # Get the latest CloudFormation package
          dnf update -y aws-cfn-bootstrap
          # Run cfn-init
          /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region} || error_exit 'Failed to run cfn-init'        
          # Start up the cfn-hup daemon to listen for changes to the EC2 instance metadata
          /opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'
          # Signal success or failure
          /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerInstance --region ${AWS::Region}
    Metadata:
      AWS::CloudFormation::Init:
        config:
          packages:
            dnf:
              httpd: []
              php: []
          files:
            /var/www/html/index.php:
              content: |
                <?php
                echo "<h1>Hello World!</h1>";
                echo "<p>This is an updated version of our application.</p>";
                echo "<p>Running on Amazon Linux 2023!</p>";
                ?>
              mode: '000644'
              owner: apache
              group: apache
            /etc/cfn/cfn-hup.conf:
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
                # The interval used to check for changes to the resource metadata in minutes. Default is 15
                interval=2
              mode: '000400'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:
              content: !Sub |
                [cfn-auto-reloader-hook]
                triggers=post.update
                path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init
                action=/opt/aws/bin/cfn-init -s ${AWS::StackId} -r WebServerInstance --region ${AWS::Region}
                runas=root
          services:
            systemd:
              httpd:
                enabled: true
                ensureRunning: true
              cfn-hup:
                enabled: true
                ensureRunning: true
                files:
                  - /etc/cfn/cfn-hup.conf
                  - /etc/cfn/hooks.d/cfn-auto-reloader.conf
    CreationPolicy:
      ResourceSignal:
        Timeout: PT5M

  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80 and SSH access via port 22
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref SSHLocation

Outputs:
  WebsiteURL:
    Value: !Sub 'http://${WebServerInstance.PublicDnsName}'
    Description: URL of the web application
```

[2단계: 애플리케이션 업데이트](#update-stack-update-application)에 설명된 동일한 단계를 사용하여 스택을 업데이트합니다.

새 인스턴스를 실행한 후에는 CloudFormation에서 새 리소스를 가리키도록 스택의 다른 리소스를 업데이트합니다. 새로운 모든 리소스가 생성되면 이전 리소스가 삭제되며, 이를 `UPDATE_CLEANUP` 프로세스라고 합니다. 현재는 업데이트의 결과로서 스택 내 인스턴스의 인스턴스 ID와 애플리케이션 URL이 변경되었습니다. **이벤트** 테이블의 이벤트에는 리소스가 대체되었음을 나타내는 '요청된 업데이트에서 변경 불가능한 속성에 대한 변경을 포함하므로 새 물리적 리소스가 생성됨'이라는 설명이 포함됩니다.

또는 업데이트할 애플리케이션 코드를 AMI에 작성한 경우 새 애플리케이션을 로드하도록 동일한 스택 업데이트 메커니즘을 사용하여 AMI를 업데이트할 수 있습니다.

**사용자 지정 애플리케이션 코드로 AMI를 업데이트하는 방법**

1. 애플리케이션이나 운영 체제 변경 내용을 포함하는 새 AMI를 생성하세요. 자세한 내용은 *Amazon EC2 사용 설명서*의 [Amazon EBS 지원 AMI 생성](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/creating-an-ami-ebs.html)을 참조하세요.

1. 새 AMI ID를 통합하도록 템플릿을 업데이트합니다.

1. [2단계: 애플리케이션 업데이트](#update-stack-update-application)에 설명된 동일한 단계를 사용하여 스택을 업데이트합니다.

스택 업데이트 시, CloudFormation은 AMI ID가 변경되었음을 감지하고 나서 위에서 트리거했을 때와 동일한 방식으로 스택 업데이트를 시작합니다.

## 가용성 및 영향 고려 사항
<a name="update.walkthrough.impact"></a>

속성마다 스택의 리소스에 미치는 영향이 다릅니다. CloudFormation을 사용하여 속성을 업데이트할 수 있지만, 변경하기 전에 다음 질문을 고려해야 합니다.

1. 업데이트가 리소스 자체에 어떤 영향을 미치는가? 예를 들어 경보 임계값 업데이트는 업데이트 중에 경보를 비활성화합니다. 아시다시피, 인스턴스 유형을 변경하려면 인스턴스를 중지했다가 다시 시작해야 합니다. CloudFormation은 기본 리소스에 대해 업데이트 또는 수정 작업을 사용하여 리소스를 변경합니다. 업데이트 영향을 이해하려면 특정 리소스에 대한 설명서를 확인해야 합니다.

1. 변경이 가능한가? 불가능한가? Amazon EC2 인스턴스에서 AMI 변경과 같이 리소스 속성에 대한 일부 변경은 기본 서비스에서 지원되지 않습니다. 가능한 변경의 경우, CloudFormation은 기본 리소스에 대해 업데이트 또는 수정 유형의 API를 사용합니다. 불가능한 속성 변경의 경우, CloudFormation은 업데이트된 속성을 사용하여 새 리소스를 생성하고 나서 이전 리소스를 삭제하기 전에 새 리소스를 스택에 연결합니다. CloudFormation이 스택 리소스의 중단 시간을 줄이려고 노력하더라도, 리소스 대체는 다단계 프로세스이며 시간이 걸리는 작업입니다. 스택 구성 중에는 애플리케이션이 부분적으로만 작동합니다. 예를 들면 요청을 처리하거나 데이터베이스에 액세스하지 못할 수도 있습니다.

## 관련 리소스
<a name="update.walkthrough.related"></a>

CloudFormation을 사용하여 애플리케이션을 시작하고 다른 구성 및 배포 서비스(예: Puppet 및 Opscode Chef)와 통합하는 방법에 대한 자세한 내용은 다음 백서를 참조하세요.
+ [CloudFormation을 통해 애플리케이션 부트스트래핑](https://s3.amazonaws.com/cloudformation-examples/BoostrappingApplicationsWithAWSCloudFormation.pdf)
+ [CloudFormation과 Opscode Chef의 통합](https://s3.amazonaws.com/cloudformation-examples/IntegratingAWSCloudFormationWithOpscodeChef.pdf)
+ [CloudFormation과 Puppet의 통합](https://s3.amazonaws.com/cloudformation-examples/IntegratingAWSCloudFormationWithPuppet.pdf)

# 조정 및 로드 밸런싱된 애플리케이션 생성
<a name="walkthrough-autoscaling"></a>

이 연습에서는 조정 및 로드 밸런싱된 애플리케이션을 설정하는 데 도움이 되는 스택을 생성합니다. 이 연습에서는 스택을 생성하는 데 사용할 샘플 템플릿을 제공합니다. 예제 템플릿은 auto scaling, Application Load Balancer, 로드 밸런서 및 Auto Scaling 그룹에 대한 트래픽을 제어하는 보안 그룹, 조정 활동에 대한 알림을 게시하기 위한 Amazon SNS 알림 구성을 제공합니다.

이 템플릿은 하나 이상의 Amazon EC2 인스턴스와 Application Load Balancer를 생성합니다. 이 템플릿에서 스택을 생성할 경우 사용한 AWS 리소스에 대한 요금이 청구됩니다.

## 전체 스택 템플릿
<a name="example-templates-autoscaling-full-stack-template"></a>

템플릿으로 시작하겠습니다.

**YAML**

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  InstanceType:
    Description: The EC2 instance type
    Type: String
    Default: t3.micro
    AllowedValues:
      - t3.micro
      - t3.small
      - t3.medium
  KeyName:
    Description: Name of an existing EC2 key pair to allow SSH access to the instances
    Type: AWS::EC2::KeyPair::KeyName
  LatestAmiId:
    Description: The latest Amazon Linux 2 AMI from the Parameter Store
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
  OperatorEmail:
    Description: The email address to notify when there are any scaling activities
    Type: String
  SSHLocation:
    Description: The IP address range that can be used to SSH to the EC2 instances
    Type: String
    MinLength: 9
    MaxLength: 18
    Default: 0.0.0.0/0
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
  Subnets:
    Type: 'List<AWS::EC2::Subnet::Id>'
    Description: At least two public subnets in different Availability Zones in the selected VPC
  VPC:
    Type: AWS::EC2::VPC::Id
    Description: A virtual private cloud (VPC) that enables resources in public subnets to connect to the internet
Resources:
  ELBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ELB Security Group
      VpcId: !Ref VPC
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        CidrIp: 0.0.0.0/0
  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: EC2 Security Group
      VpcId: !Ref VPC
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        SourceSecurityGroupId:
          Fn::GetAtt:
          - ELBSecurityGroup
          - GroupId
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: !Ref SSHLocation
  EC2TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 30
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 15
      HealthyThresholdCount: 5
      Matcher:
        HttpCode: '200'
      Name: EC2TargetGroup
      Port: 80
      Protocol: HTTP
      TargetGroupAttributes:
      - Key: deregistration_delay.timeout_seconds
        Value: '20'
      UnhealthyThresholdCount: 3
      VpcId: !Ref VPC
  ALBListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref EC2TargetGroup
      LoadBalancerArn: !Ref ApplicationLoadBalancer
      Port: 80
      Protocol: HTTP
  ApplicationLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Scheme: internet-facing
      Subnets: !Ref Subnets
      SecurityGroups:
        - !GetAtt ELBSecurityGroup.GroupId
  LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties: 
      LaunchTemplateName: !Sub ${AWS::StackName}-launch-template
      LaunchTemplateData:
        ImageId: !Ref LatestAmiId
        InstanceType: !Ref InstanceType
        KeyName: !Ref KeyName
        SecurityGroupIds: 
          - !Ref EC2SecurityGroup
        UserData:
          Fn::Base64: !Sub |
            #!/bin/bash
            yum update -y
            yum install -y httpd
            systemctl start httpd
            systemctl enable httpd
            echo "<h1>Hello World!</h1>" > /var/www/html/index.html
  NotificationTopic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: !Ref OperatorEmail
          Protocol: email
  WebServerGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      LaunchTemplate:
        LaunchTemplateId: !Ref LaunchTemplate
        Version: !GetAtt LaunchTemplate.LatestVersionNumber
      MaxSize: '3'
      MinSize: '1'
      NotificationConfigurations:
        - TopicARN: !Ref NotificationTopic
          NotificationTypes: ['autoscaling:EC2_INSTANCE_LAUNCH', 'autoscaling:EC2_INSTANCE_LAUNCH_ERROR', 'autoscaling:EC2_INSTANCE_TERMINATE', 'autoscaling:EC2_INSTANCE_TERMINATE_ERROR']
      TargetGroupARNs:
        - !Ref EC2TargetGroup
      VPCZoneIdentifier: !Ref Subnets
```

**JSON**

```
{
  "AWSTemplateFormatVersion":"2010-09-09",
  "Parameters":{
    "InstanceType":{
      "Description":"The EC2 instance type",
      "Type":"String",
      "Default":"t3.micro",
      "AllowedValues":[
        "t3.micro",
        "t3.small",
        "t3.medium"
      ]
    },
    "KeyName":{
      "Description":"Name of an existing EC2 key pair to allow SSH access to the instances",
      "Type":"AWS::EC2::KeyPair::KeyName"
    },
    "LatestAmiId":{
      "Description":"The latest Amazon Linux 2 AMI from the Parameter Store",
      "Type":"AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>",
      "Default":"/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
    },
    "OperatorEmail":{
      "Description":"The email address to notify when there are any scaling activities",
      "Type":"String"
    },
    "SSHLocation":{
      "Description":"The IP address range that can be used to SSH to the EC2 instances",
      "Type":"String",
      "MinLength":9,
      "MaxLength":18,
      "Default":"0.0.0.0/0",
      "ConstraintDescription":"Must be a valid IP CIDR range of the form x.x.x.x/x."
    },
    "Subnets":{
      "Type":"List<AWS::EC2::Subnet::Id>",
      "Description":"At least two public subnets in different Availability Zones in the selected VPC"
    },
    "VPC":{
      "Type":"AWS::EC2::VPC::Id",
      "Description":"A virtual private cloud (VPC) that enables resources in public subnets to connect to the internet"
    }
  },
  "Resources":{
    "ELBSecurityGroup":{
      "Type":"AWS::EC2::SecurityGroup",
      "Properties":{
        "GroupDescription":"ELB Security Group",
        "VpcId":{
          "Ref":"VPC"
        },
        "SecurityGroupIngress":[
          {
            "IpProtocol":"tcp",
            "FromPort":80,
            "ToPort":80,
            "CidrIp":"0.0.0.0/0"
          }
        ]
      }
    },
    "EC2SecurityGroup":{
      "Type":"AWS::EC2::SecurityGroup",
      "Properties":{
        "GroupDescription":"EC2 Security Group",
        "VpcId":{
          "Ref":"VPC"
        },
        "SecurityGroupIngress":[
          {
            "IpProtocol":"tcp",
            "FromPort":80,
            "ToPort":80,
            "SourceSecurityGroupId":{
              "Fn::GetAtt":[
                "ELBSecurityGroup",
                "GroupId"
              ]
            }
          },
          {
            "IpProtocol":"tcp",
            "FromPort":22,
            "ToPort":22,
            "CidrIp":{
              "Ref":"SSHLocation"
            }
          }
        ]
      }
    },
    "EC2TargetGroup":{
      "Type":"AWS::ElasticLoadBalancingV2::TargetGroup",
      "Properties":{
        "HealthCheckIntervalSeconds":30,
        "HealthCheckProtocol":"HTTP",
        "HealthCheckTimeoutSeconds":15,
        "HealthyThresholdCount":5,
        "Matcher":{
          "HttpCode":"200"
        },
        "Name":"EC2TargetGroup",
        "Port":80,
        "Protocol":"HTTP",
        "TargetGroupAttributes":[
          {
            "Key":"deregistration_delay.timeout_seconds",
            "Value":"20"
          }
        ],
        "UnhealthyThresholdCount":3,
        "VpcId":{
          "Ref":"VPC"
        }
      }
    },
    "ALBListener":{
      "Type":"AWS::ElasticLoadBalancingV2::Listener",
      "Properties":{
        "DefaultActions":[
          {
            "Type":"forward",
            "TargetGroupArn":{
              "Ref":"EC2TargetGroup"
            }
          }
        ],
        "LoadBalancerArn":{
          "Ref":"ApplicationLoadBalancer"
        },
        "Port":80,
        "Protocol":"HTTP"
      }
    },
    "ApplicationLoadBalancer":{
      "Type":"AWS::ElasticLoadBalancingV2::LoadBalancer",
      "Properties":{
        "Scheme":"internet-facing",
        "Subnets":{
          "Ref":"Subnets"
        },
        "SecurityGroups":[
          {
            "Fn::GetAtt":[
              "ELBSecurityGroup",
              "GroupId"
            ]
          }
        ]
      }
    },
    "LaunchTemplate":{
      "Type":"AWS::EC2::LaunchTemplate",
      "Properties":{
        "LaunchTemplateName":{
          "Fn::Sub":"${AWS::StackName}-launch-template"
        },
        "LaunchTemplateData":{
          "ImageId":{
            "Ref":"LatestAmiId"
          },
          "InstanceType":{
            "Ref":"InstanceType"
          },
          "KeyName":{
            "Ref":"KeyName"
          },
          "SecurityGroupIds":[
            {
              "Ref":"EC2SecurityGroup"
            }
          ],
          "UserData":{
            "Fn::Base64":{
              "Fn::Join":[
                "",
                [
                  "#!/bin/bash\n",
                  "yum update -y\n",
                  "yum install -y httpd\n",
                  "systemctl start httpd\n",
                  "systemctl enable httpd\n",
                  "echo \"<h1>Hello World!</h1>\" > /var/www/html/index.html"
                ]
              ]
            }
          }
        }
      }
    },
    "NotificationTopic":{
      "Type":"AWS::SNS::Topic",
      "Properties":{
        "Subscription":[
          {
            "Endpoint":{
              "Ref":"OperatorEmail"
            },
            "Protocol":"email"
          }
        ]
      }
    },
    "WebServerGroup":{
      "Type":"AWS::AutoScaling::AutoScalingGroup",
      "Properties":{
        "LaunchTemplate":{
          "LaunchTemplateId":{
            "Ref":"LaunchTemplate"
          },
          "Version":{
            "Fn::GetAtt":[
              "LaunchTemplate",
              "LatestVersionNumber"
            ]
          }
        },
        "MaxSize":"3",
        "MinSize":"1",
        "NotificationConfigurations":[
          {
            "TopicARN":{
              "Ref":"NotificationTopic"
            },
            "NotificationTypes":[
              "autoscaling:EC2_INSTANCE_LAUNCH",
              "autoscaling:EC2_INSTANCE_LAUNCH_ERROR",
              "autoscaling:EC2_INSTANCE_TERMINATE",
              "autoscaling:EC2_INSTANCE_TERMINATE_ERROR"
            ]
          }
        ],
        "TargetGroupARNs":[
          {
            "Ref":"EC2TargetGroup"
          }
        ],
        "VPCZoneIdentifier":{
          "Ref":"Subnets"
        }
      }
    }
  }
}
```

## 템플릿 연습
<a name="example-templates-autoscaling-description"></a>

이 템플릿의 첫 번째 부분에서는 `Parameters`를 지정합니다. 각 파라미터마다 CloudFormation이 스택을 프로비저닝 할 실행 시간에 대한 값을 할당해야 합니다. 템플릿 뒷부분에 지정된 리소스는 이러한 값을 참조하고 데이터를 사용합니다.
+ `InstanceType`: Amazon EC2 Auto Scaling에서 프로비저닝하는 EC2 인스턴스의 유형입니다. 지정하지 않으면 기본적으로 `t3.micro`가 사용됩니다.
+ `KeyName`: 인스턴스에 대한 SSH 액세스를 허용하는 기존 EC2 키 페어입니다.
+ `LatestAmiId`: 인스턴스의 Amazon Machine Image(AMI)입니다. 지정하지 않으면 AWS에서 유지 관리하는 AWS Systems Manager 퍼블릭 파라미터를 사용하여 Amazon Linux 2 AMI로 인스턴스가 시작됩니다. 자세한 내용은 **AWS Systems Manager 사용 설명서의 [Finding public parameters](https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-finding-public-parameters.html)를 참조하세요.
+ `OperatorEmail`: 조정 활동 알림을 보낼 이메일 주소입니다.
+ `SSHLocation`: SSH를 인스턴스에 연결하는 데 사용할 수 있는 IP 주소 범위입니다.
+ `Subnets`: 서로 다른 가용 영역에 두 개 이상의 퍼블릭 서브넷을 보유해야 합니다.
+ `VPC`: 퍼블릭 서브넷의 리소스를 인터넷에 연결하는 계정의 Virtual Private Cloud(VPC)입니다.
**참고**  
기본 VPC와 기본 서브넷을 사용하여 인스턴스가 인터넷에 액세스하도록 허용할 수 있습니다. 자체 VPC를 사용 중인 경우, 작업 중인 지역의 각 가용 영역에 매핑된 서브넷이 VPC에 있는지 확인합니다. 로드 밸런서를 생성하려면 사용 가능한 퍼블릭 서브넷이 최소한 두 개 있어야 합니다.

이 템플릿의 다음 부분에서는 `Resources`를 지정합니다. 이 섹션에서는 스택 리소스와 해당 속성을 지정합니다.

[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) 리소스 `ELBSecurityGroup` 
+ `SecurityGroupIngress`에는 **모든 IP 주소(“CidrIp”: “0.0.0.0/0")에서 포트 80에 액세스할 수 있도록 하는 TCP 수신 규칙이 포함되어 있습니다.

[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) 리소스 `EC2SecurityGroup` 
+ `SecurityGroupIngress`에는 두 가지 수신 규칙, 즉 1) `SSHLocation` 입력 파라미터에 제공하는 IP 주소 범위에서 SSH(포트 22)에 액세스하도록 허용하는 TCP 수신 규칙과 2) 로드 밸런서의 보안 그룹을 지정하여 로드 밸런서에서 액세스하도록 허용하는 TCP 수신 규칙이 포함되어 있습니다. [GetAtt](resources-section-structure.md#resource-properties-getatt) 함수는 논리명이 `ELBSecurityGroup`인 보안 그룹의 ID를 가져오는 데 사용됩니다.

[AWS::ElasticLoadBalancingV2::TargetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html) 리소스 `EC2TargetGroup`
+ `Port`, `Protocol` 및 `HealthCheckProtocol`은 `ApplicationLoadBalancer`에서 트래픽을 라우팅하고 Elastic Load Balancing에서 EC2 인스턴스의 상태를 확인하는 데 사용되는 EC2 인스턴스 포트(80) 및 프로토콜(HTTP)을 지정합니다.
+ `HealthCheckIntervalSeconds`는 EC2 인스턴스에서 상태 확인 간에 30초의 간격을 두도록 합니다. `HealthCheckTimeoutSeconds`는 Elastic Load Balancing이 상태를 확인할 대상의 응답을 기다리는 시간의 길이로 정의됩니다(이 예에서는 15초). 제한 시간이 지난 후에는 Elastic Load Balancing이 EC2 인스턴스의 상태 확인을 비정상으로 표시합니다. EC2 인스턴스가 세 번 연속 상태 확인(`UnhealthyThresholdCount`)에 실패할 경우 Elastic Load Balancing은 해당 인스턴스에서 5회 연속 정상 상태 확인(`HealthyThresholdCount`)이 있을 때까지 해당 EC2 인스턴스에 대한 트래픽 라우팅을 중지합니다. 5회 연속 정상 상태 확인 시점에 Elastic Load Balancing은 인스턴스를 정상으로 간주하고 인스턴스에 대한 트래픽 라우팅을 다시 시작합니다.
+ `TargetGroupAttributes`는 대상 그룹의 등록 취소 지연 값을 20초로 업데이트합니다. 기본적으로 Elastic Load Balancing은 등록 취소 프로세스를 완료하기 전에 300초 동안 기다립니다.

[AWS::ElasticLoadBalancingV2::Listener](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-listener.html) 리소스 `ALBListener`
+ `DefaultActions`는 로드 밸런서가 수신하는 포트, 로드 밸런서가 요청을 전달하는 대상 그룹 및 요청을 라우팅하는 데 사용되는 프로토콜을 지정합니다.

[AWS::ElasticLoadBalancingV2::LoadBalancer](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-loadbalancer.html) 리소스 `ApplicationLoadBalancer`
+ `Subnets`은 `Subnets` 입력 파라미터 값을 로드 밸런서 노드가 생성될 퍼블릭 서브넷 목록으로 가져옵니다.
+ `SecurityGroup`은 로드 밸런서 노드에서 수신 트래픽을 제어하기 위해 가상 방화벽 역할을 하는 보안 그룹의 ID를 가져옵니다. [GetAtt](resources-section-structure.md#resource-properties-getatt) 함수는 논리명이 `ELBSecurityGroup`인 보안 그룹의 ID를 가져오는 데 사용됩니다.

[AWS::EC2::LaunchTemplate](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html) 리소스 `LaunchTemplate`
+ `ImageId`는 사용할 AMI로 `LatestAmiId` 입력 파라미터 값을 가져옵니다.
+ `KeyName`은 사용할 EC2 키 페어로 `KeyName` 입력 파라미터 값을 가져옵니다.
+ `SecurityGroupIds`는 EC2 인스턴스에서 수신 트래픽을 제어하기 위해 가상 방화벽 역할을 하는 논리명이 `EC2SecurityGroup`인 보안 그룹의 ID를 가져옵니다.
+ `UserData`는 인스턴스가 가동되어 실행된 후에 실행되는 구성 스크립트입니다. 이 예제에서 스크립트는 Apache를 설치하고 index.html 파일을 생성합니다.

[AWS::SNS::Topic](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-topic.html) 리소스 `NotificationTopic`
+ `Subscription`은 조정 활동이 있을 때 알림 수신자의 이메일 주소로 `OperatorEmail` 입력 파라미터 값을 가져옵니다.

[AWS::AutoScaling::AutoScalingGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html) 리소스 `WebServerGroup`
+ `MinSize` 및 `MaxSize`는 auto scaling의 최소 및 최대 EC2 인스턴스 수를 설정합니다.
+ `TargetGroupARNs`는 논리명이 `EC2TargetGroup`인 대상 그룹의 ARN을 가져옵니다. 이 auto scaling은 규모를 조정하면서 이 대상 그룹에 인스턴스를 자동으로 등록 및 등록 취소합니다.
+ `VPCZoneIdentifier`는 `Subnets` 입력 파라미터 값을 EC2 인스턴스가 생성될 수 있는 퍼블릭 서브넷 목록으로 가져옵니다.

## 1단계: 스택 시작
<a name="example-templates-autoscaling-launch-stack"></a>

스택을 시작하기 전에 Amazon EC2, Amazon EC2 Auto Scaling, AWS Systems Manager, Elastic Load Balancing, Amazon SNS, CloudFormation 등의 서비스를 모두 사용할 수 있는 AWS Identity and Access Management(IAM) 권한이 있는지 확인합니다.

다음 절차에는 파일에서 샘플 스택 템플릿을 업로드하는 절차가 포함됩니다. 로컬 시스템에서 텍스트 편집기를 열고 템플릿 중 하나를 추가합니다. `sampleloadbalancedappstack.template` 이름으로 파일을 저장합니다.

**스택 템플릿을 시작하려면**

1. AWS Management Console에 로그인하여 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)에서 CloudFormation 콘솔을 엽니다.

1. **스택 생성**, **새 리소스 사용(표준)**를 선택합니다.

1. **템플릿 지정**에서 **템플릿 파일 업로드**, **파일 선택**을 차례로 선택하여 `sampleloadbalancedappstack.template` 파일을 업로드하세요.

1. **다음**을 선택합니다.

1. **스택 세부 정보 지정** 페이지에 스택 이름(예: **SampleLoadBalancedAppStack**)을 입력합니다.

1. **파라미터**에서 스택의 매개 변수를 검토하고 **OperatorEmail**, **SSHLocation**, **KeyName**, **VPC**, **서브넷**을 포함하여 기본값이 없는 모든 파라미터의 값을 제공합니다.

1. **다음**을 두 번 선택합니다

1. **검토** 페이지에서 설정을 검토하고 확인합니다.

1. **제출**을 선택합니다.

   CloudFormation 콘솔의 **상태** 열에서 스택의 상태를 볼 수 있습니다. CloudFormation에서 스택이 생성되면 **CREATE\$1COMPLETE** 상태가 표시됩니다.
**참고**  
스택을 생성한 후 구독을 확인해야 이메일 주소로 알림 수신을 시작할 수 있습니다. 자세한 정보는 *Amazon EC2 Auto Scaling 사용 설명서*의 [auto scaling 조정 시 Amazon SNS 알림 수신](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-sns-notifications.html)을 참조하세요.

## 2단계: 샘플 리소스 정리
<a name="example-templates-autoscaling-clean-up"></a>

사용하지 않은 샘플 리소스에 요금이 부과되지 않도록 하려면 스택을 삭제하세요.

**스택을 삭제하려면**

1. CloudFormation 콘솔에서 **SampleLoadBalancedAppStack** 스택을 선택합니다.

1. **삭제**를 선택합니다.

1. 확인 메시지에서 **스택 삭제**를 선택합니다.

   **SampleLoadBalancedAppStack**의 상태가 **DELETE\$1IN\$1PROGRESS**로 변경됩니다. CloudFormation에서 스택 삭제를 완료하면 목록에서 해당 스택이 제거됩니다.

이 연습의 샘플 템플릿을 사용하여 자체 스택 템플릿을 구축합니다. 자세한 내용은 Amazon EC2 Auto Scaling 사용 설명서**의 [Tutorial: Set up a scaled and load-balanced application](https://docs.aws.amazon.com/autoscaling/ec2/userguide/tutorial-ec2-auto-scaling-load-balancer.html)을 참조하세요.

# 다른 AWS 계정의 VPC와 피어링
<a name="peer-with-vpc-in-another-account"></a>

[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-vpcpeeringconnection.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-vpcpeeringconnection.html)을 사용하여 다른 AWS 계정의 Virtual Private Cloud(VPC)와 피어링할 수 있습니다. 이렇게 하면 두 VPC 간에 네트워킹 연결이 생성되어 두 VPC 간에 트래픽을 라우팅할 수 있습니다. 따라서 두 VPC가 마치 동일한 네트워크 내에 있는 것처럼 통신할 수 있습니다. VPC 피어링 연결을 사용하면 데이터 액세스 및 데이터 전송을 원활하게 실행할 수 있습니다.

VPC 피어링 연결을 설정하려면 단일 CloudFormation 스택 내에서 개별 AWS 계정 2개를 승인해야 합니다.

VPC 피어링 및 제한 사항에 대한 자세한 내용은 [Amazon VPC 피어링 설명서](https://docs.aws.amazon.com/vpc/latest/peering/)를 참조하세요.

## 사전 조건
<a name="peer-with-vpc-in-another-account-prerequisites"></a>

1. 피어링 연결에는 피어 VPC ID, 피어 AWS 계정 ID 및 [크로스 계정 액세스 역할](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_aws-accounts.html)이 필요합니다.
**참고**  
이 연습에서는 두 가지 계정을 참조합니다. 첫 번째는 교차 계정 피어링을 허용하는 계정이고(*수락자 계정*), 두 번째는 피어링 연결을 요청하는 계정입니다(*요청자 계정*).

1. VPC 피어링 연결을 수락하려면 교차 계정 액세스 역할을 맡을 수 있어야 합니다. 이 리소스는 동일한 계정의 VPC 피어링 연결 리소스와 동일한 방식으로 동작합니다. IAM 관리자가 교차 계정 역할을 수임할 수 있는 권한을 부여하는 방법에 대한 자세한 내용은 *IAM 사용 설명서*의 [사용자에게 역할을 전환할 권한 부여](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_permissions-to-switch.html)를 참조하세요.

## 1단계: VPC 및 교차 계정 역할 생성
<a name="step-1-create-vpc-and-cross-account-role"></a>

이 단계에서는 *수락자 계정*에서 VPC 및 역할을 생성합니다.

**VPC 및 교차 계정 액세스 역할을 생성하려면 다음을 수행하세요.**

1. AWS Management Console에 로그인하여 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)에서 CloudFormation 콘솔을 엽니다.

1. **스택** 페이지의 오른쪽 상단에서 **스택 생성**을 선택하고 **새 리소스 사용(표준)**을 선택합니다.

1. **사전 조건 - 템플릿 준비**에 **기존 템플릿 선택**을 선택한 다음 **템플릿 파일 업로드**, **파일 선택**을 차례로 선택합니다.

1. 로컬 시스템에서 텍스트 편집기를 열고 다음 템플릿 중 하나를 추가합니다. 파일을 저장하고 콘솔로 돌아가 템플릿 파일로 선택합니다.  
**Example JSON**  

   ```
   {
     "AWSTemplateFormatVersion": "2010-09-09",
     "Description": "Create a VPC and an assumable role for cross account VPC peering.",
     "Parameters": {
       "PeerRequesterAccountId": {
         "Type": "String"
       }
     },
     "Resources": {
       "vpc": {
         "Type": "AWS::EC2::VPC",
         "Properties": {
           "CidrBlock": "10.1.0.0/16",
           "EnableDnsSupport": false,
           "EnableDnsHostnames": false,
           "InstanceTenancy": "default"
         }
       },
       "peerRole": {
         "Type": "AWS::IAM::Role",
         "Properties": {
           "AssumeRolePolicyDocument": {
             "Statement": [
               {
                 "Principal": {
                   "AWS": {
                     "Ref": "PeerRequesterAccountId"
                   }
                 },
                 "Action": [
                   "sts:AssumeRole"
                 ],
                 "Effect": "Allow"
               }
             ]
           },
           "Path": "/",
           "Policies": [
             {
               "PolicyName": "root",
               "PolicyDocument": {
                 "Version": "2012-10-17",		 	 	 
                 "Statement": [
                   {
                     "Effect": "Allow",
                     "Action": "ec2:AcceptVpcPeeringConnection",
                     "Resource": "*"
                   }
                 ]
               }
             }
           ]
         }
       }
     },
     "Outputs": {
       "VPCId": {
         "Value": {
           "Ref": "vpc"
         }
       },
       "RoleARN": {
         "Value": {
           "Fn::GetAtt": [
             "peerRole",
             "Arn"
           ]
         }
       }
     }
   }
   ```  
**Example YAML**  

   ```
   AWSTemplateFormatVersion: 2010-09-09
   Description: Create a VPC and an assumable role for cross account VPC peering.
   Parameters:
     PeerRequesterAccountId:
       Type: String
   Resources:
     vpc:
       Type: AWS::EC2::VPC
       Properties:
         CidrBlock: 10.1.0.0/16
         EnableDnsSupport: false
         EnableDnsHostnames: false
         InstanceTenancy: default
     peerRole:
       Type: AWS::IAM::Role
       Properties:
         AssumeRolePolicyDocument:
           Statement:
             - Principal:
                 AWS: !Ref PeerRequesterAccountId
               Action:
                 - 'sts:AssumeRole'
               Effect: Allow
         Path: /
         Policies:
           - PolicyName: root
             PolicyDocument:
               Version: 2012-10-17 		 	 	 
               Statement:
                 - Effect: Allow
                   Action: 'ec2:AcceptVpcPeeringConnection'
                   Resource: '*'
   Outputs:
     VPCId:
       Value: !Ref vpc
     RoleARN:
       Value: !GetAtt 
         - peerRole
         - Arn
   ```

1. **다음**을 선택합니다.

1. 스택에 이름(예: **VPC-owner**)을 지정한 다음 **PeerRequesterAccountId** 필드에 *요청자 계정*의 AWS 계정 ID를 입력합니다.

1. 기본값을 수락하고 **다음**을 선택합니다.

1. **CloudFormation에서 IAM 리소스를 생성할 수 있음을 승인합니다**를 선택하고 **스택 생성**을 선택하세요.

## 2단계: `AWS::EC2::VPCPeeringConnection`을 포함하는 템플릿 생성
<a name="step-2-create-template-for-vpc-peering-connection-owner"></a>

이제 VPC 및 크로스 계정 역할을 생성했으므로 다른 AWS 계정(*요청자 계정*)을 사용하여 VPC와 피어링할 수 있습니다.

**[AWS::EC2::VPCPeeringConnection](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-vpcpeeringconnection.html) 리소스가 포함된 템플릿을 생성하려면 다음을 수행하세요.**

1. CloudFormation 콘솔 홈페이지로 되돌아 갑니다.

1. **스택** 페이지의 오른쪽 상단에서 **스택 생성**을 선택하고 **새 리소스 사용(표준)**을 선택합니다.

1. **사전 조건 - 템플릿 준비**에 **기존 템플릿 선택**을 선택한 다음 **템플릿 파일 업로드**, **파일 선택**을 차례로 선택합니다.

1. 로컬 시스템에서 텍스트 편집기를 열고 다음 템플릿 중 하나를 추가합니다. 파일을 저장하고 콘솔로 돌아가 템플릿 파일로 선택합니다.  
**Example JSON**  

   ```
   {
     "AWSTemplateFormatVersion": "2010-09-09",
     "Description": "Create a VPC and a VPC Peering connection using the PeerRole to accept.",
     "Parameters": {
       "PeerVPCAccountId": {
         "Type": "String"
       },
       "PeerVPCId": {
         "Type": "String"
       },
       "PeerRoleArn": {
         "Type": "String"
       }
     },
     "Resources": {
       "vpc": {
         "Type": "AWS::EC2::VPC",
         "Properties": {
           "CidrBlock": "10.2.0.0/16",
           "EnableDnsSupport": false,
           "EnableDnsHostnames": false,
           "InstanceTenancy": "default"
         }
       },
       "vpcPeeringConnection": {
         "Type": "AWS::EC2::VPCPeeringConnection",
         "Properties": {
           "VpcId": {
             "Ref": "vpc"
           },
           "PeerVpcId": {
             "Ref": "PeerVPCId"
           },
           "PeerOwnerId": {
             "Ref": "PeerVPCAccountId"
           },
           "PeerRoleArn": {
             "Ref": "PeerRoleArn"
           }
         }
       }
     },
     "Outputs": {
       "VPCId": {
         "Value": {
           "Ref": "vpc"
         }
       },
       "VPCPeeringConnectionId": {
         "Value": {
           "Ref": "vpcPeeringConnection"
         }
       }
     }
   }
   ```  
**Example YAML**  

   ```
   AWSTemplateFormatVersion: 2010-09-09
   Description: Create a VPC and a VPC Peering connection using the PeerRole to accept.
   Parameters:
     PeerVPCAccountId:
       Type: String
     PeerVPCId:
       Type: String
     PeerRoleArn:
       Type: String
   Resources:
     vpc:
       Type: AWS::EC2::VPC
       Properties:
         CidrBlock: 10.2.0.0/16
         EnableDnsSupport: false
         EnableDnsHostnames: false
         InstanceTenancy: default
     vpcPeeringConnection:
       Type: AWS::EC2::VPCPeeringConnection
       Properties:
         VpcId: !Ref vpc
         PeerVpcId: !Ref PeerVPCId
         PeerOwnerId: !Ref PeerVPCAccountId
         PeerRoleArn: !Ref PeerRoleArn
   Outputs:
     VPCId:
       Value: !Ref vpc
     VPCPeeringConnectionId:
       Value: !Ref vpcPeeringConnection
   ```

1. **다음**을 선택합니다.

1. 스택에 이름을 제공합니다(예: **VPC-peering-connection**).

1. 기본값을 수락하고 **다음**을 선택합니다.

1. **CloudFormation에서 IAM 리소스를 생성할 수 있음을 승인합니다**를 선택하고 **스택 생성**을 선택하세요.

## 아주 제한적인 정책으로 템플릿 생성
<a name="create-template-with-highly-restrictive-policy"></a>

VPC를 다른 AWS 계정 계정에 피어링할 때 매우 제한적인 정책을 생성하고자 할 수 있습니다.

다음 예제 템플릿은 VPC 피어 소유자 템플릿(위 1단계에서 생성한 *수락자 계정*)을 더욱 제한적으로 변경하는 방법을 보여줍니다.

**Example JSON**  

```
{
  "AWSTemplateFormatVersion":"2010-09-09",
  "Description":"Create a VPC and an assumable role for cross account VPC peering.",
  "Parameters":{
    "PeerRequesterAccountId":{
      "Type":"String"
    }
  },
  "Resources":{
    "peerRole":{
      "Type":"AWS::IAM::Role",
      "Properties":{
        "AssumeRolePolicyDocument":{
          "Statement":[
            {
              "Action":[
                "sts:AssumeRole"
              ],
              "Effect":"Allow",
              "Principal":{
                "AWS":{
                  "Ref":"PeerRequesterAccountId"
                }
              }
            }
          ]
        },
        "Path":"/",
        "Policies":[
          {
            "PolicyDocument":{
              "Statement":[
                {
                  "Action":"ec2:acceptVpcPeeringConnection",
                  "Effect":"Allow",
                  "Resource":{
                    "Fn::Sub":"arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/${vpc}"
                  }
                },
                {
                  "Action":"ec2:acceptVpcPeeringConnection",
                  "Condition":{
                    "StringEquals":{
                      "ec2:AccepterVpc":{
                        "Fn::Sub":"arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/${vpc}"
                      }
                    }
                  },
                  "Effect":"Allow",
                  "Resource":{
                    "Fn::Sub":"arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc-peering-connection/*"
                  }
                }
              ],
              "Version":"2012-10-17" 		 	 	 
            },
            "PolicyName":"root"
          }
        ]
      }
    },
    "vpc":{
      "Type":"AWS::EC2::VPC",
      "Properties":{
        "CidrBlock":"10.1.0.0/16",
        "EnableDnsHostnames":false,
        "EnableDnsSupport":false,
        "InstanceTenancy":"default"
      }
    }
  },
  "Outputs":{
    "RoleARN":{
      "Value":{
        "Fn::GetAtt":[
          "peerRole",
          "Arn"
        ]
      }
    },
    "VPCId":{
      "Value":{
        "Ref":"vpc"
      }
    }
  }
}
```

**Example YAML**  

```
AWSTemplateFormatVersion: 2010-09-09
Description: Create a VPC and an assumable role for cross account VPC peering.
Parameters:
  PeerRequesterAccountId:
    Type: String
Resources:
  peerRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              AWS:
                Ref: PeerRequesterAccountId
      Path: /
      Policies:
        - PolicyDocument:
            Statement:
              - Action: 'ec2:acceptVpcPeeringConnection'
                Effect: Allow
                Resource:
                  'Fn::Sub': 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/${vpc}'
              - Action: 'ec2:acceptVpcPeeringConnection'
                Condition:
                  StringEquals:
                    'ec2:AccepterVpc':
                      'Fn::Sub': 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/${vpc}'
                Effect: Allow
                Resource:
                  'Fn::Sub': >-
                    arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc-peering-connection/*
            Version: 2012-10-17 		 	 	 
          PolicyName: root
  vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.1.0.0/16
      EnableDnsHostnames: false
      EnableDnsSupport: false
      InstanceTenancy: default
Outputs:
  RoleARN:
    Value:
      'Fn::GetAtt':
        - peerRole
        - Arn
  VPCId:
    Value:
      Ref: vpc
```

VPC에 액세스하려면 위의 2단계와 동일한 요청자 템플릿을 사용할 수 있습니다.

자세한 내용은 *Amazon VPC 피어링 가이드*의 [VPC 피어링에 대한 자격 증명 및 액세스 관리](https://docs.aws.amazon.com/vpc/latest/peering/security-iam.html)를 참조하세요.

# CloudFormation을 사용하여 CodeDeploy를 통한 ECS 블루/그린 배포 수행
<a name="blue-green"></a>

Amazon Elastic Container Service(Amazon ECS)에서 실행되는 애플리케이션을 업데이트하려면 CodeDeploy 블루/그린 배포 전략을 사용할 수 있습니다. 이 전략은 애플리케이션 버전 변경으로 인한 중단을 최소화하는 데 도움이 됩니다.

****블루/그린 배포에서는 현재의 라이브 환경(블루라고 함)과 함께 새 애플리케이션 환경(그린이라고 함)을 생성합니다. 블루 환경에서 그린 환경으로 라이브 트래픽을 라우팅하기 전에 그린 환경을 모니터링하고 테스트할 수 있습니다. 그린 환경에서 실시간 트래픽을 제공하고 나면 블루 환경을 안전하게 종료할 수 있습니다.

CloudFormation을 사용하여 ECS에서 CodeDeploy 블루/그린 배포를 수행하려면 다음 정보를 스택 템플릿에 포함하세요.
+ `AWS::CodeDeploy::BlueGreen` 후크를 설명하는 `Hooks` 섹션.
+  `AWS::CodeDeployBlueGreen` 변환을 지정하는 `Transform` 섹션.

다음 주제에서는 ECS에서의 블루/그린 배포를 위한 CloudFormation 템플릿을 설정하는 방법을 안내합니다.

**Topics**
+ [블루/그린 배포 관련 정보](about-blue-green-deployments.md)
+ [CloudFormation을 사용하여 ECS 블루/그린 배포를 관리할 때 고려 사항](blue-green-considerations.md)
+ [`AWS::CodeDeploy::BlueGreen` 후크 구문](blue-green-hook-syntax.md)
+ [블루/그린 배포 템플릿 예제](blue-green-template-example.md)

# 블루/그린 배포 관련 정보
<a name="about-blue-green-deployments"></a>

이 주제에서는 CloudFormation을 사용한 블루/그린 배포의 작동 방식에 대한 개요를 제공합니다. 또한 블루/그린 배포를 위해 CloudFormation 템플릿을 준비하는 방법도 설명합니다.

**Topics**
+ [작동 방식](#blue-green-how-it-works)
+ [그린 배포를 개시하는 리소스 업데이트](#blue-green-resources)
+ [템플릿 준비](#blue-green-setup)
+ [블루/그린 배포 모델링](#blue-green-required)
+ [변경 세트](#blue-green-changesets)
+ [스택 이벤트 모니터링](#blue-green-events)
+ [IAM 권한](#blue-green-iam)

## 작동 방식
<a name="blue-green-how-it-works"></a>

CloudFormation을 사용하여 CodeDeploy를 통해 ECS 블루/그린 배포를 수행하는 경우 사용할 트래픽 라우팅 및 안정화 설정 지정을 포함해 블루 및 그린 애플리케이션 환경 모두에 리소스를 정의하는 스택 템플릿을 먼저 생성합니다. 다음으로 해당 템플릿에서 스택을 생성합니다. 그러면 블루(현재) 애플리케이션이 생성됩니다. CloudFormation은 스택 생성 중에만 블루 리소스를 생성합니다. 그린 배포에 대한 리소스는 필요할 때까지 생성되지 않습니다.

따라서 향후 스택 업데이트에서 블루 애플리케이션의 작업 정의 또는 작업 세트 리소스를 업데이트하는 경우 CloudFormation은 다음을 수행합니다.
+ 필요한 모든 그린 애플리케이션 환경 리소스 생성
+ 지정된 트래픽 라우팅 파라미터를 기반으로 트래픽 이동
+ 블루 리소스 삭제

그린 배포가 성공하고 완료되기 전에 오류가 발생하면 CloudFormation은 전체 그린 배포가 시작되기 전의 상태로 스택을 롤백합니다.

## 그린 배포를 개시하는 리소스 업데이트
<a name="blue-green-resources"></a>

특정 ECS 리소스의 특정 속성을 업데이트하는 스택 업데이트를 수행하면 CloudFormation에서 그린 배포 프로세스를 개시합니다. 이 프로세스를 개시하는 리소스는 다음과 같습니다.
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-taskdefinition.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-taskdefinition.html)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-taskset.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-taskset.html) 

하지만 이러한 리소스에 대한 업데이트에 교체가 필요한 속성 변경이 포함되지 않는 경우 그린 배포가 개시되지 않습니다. 자세한 내용은 [스택 리소스의 업데이트 동작 이해](using-cfn-updating-stacks-update-behaviors.md) 섹션을 참조하세요.

동일한 스택 업데이트에서 다른 리소스에 대한 업데이트와 함께 위의 리소스에 대한 업데이트를 포함시킬 수 없다는 점이 중요합니다. 나열된 리소스와 동일한 스택 내의 다른 리소스를 모두 업데이트해야 하는 경우 다음 두 가지 옵션을 사용할 수 있습니다.
+ 두 개의 별도 스택 업데이트 작업을 수행합니다. 즉, 위의 리소스에 대한 업데이트만 포함시키는 작업과 기타 리소스에 대한 변경 사항을 포함시키는 별도의 스택 업데이트 작업을 수행합니다.
+ 템플릿에서 `Transform` 및 `Hooks` 섹션을 제거한 다음 스택 업데이트를 수행합니다. 이 경우 CloudFormation이 그린 배포를 수행하지 않습니다.

## ECS 블루/그린 배포를 수행하기 위한 템플릿 준비
<a name="blue-green-setup"></a>

스택에서 블루/그린 배포를 활성화하려면, 스택 업데이트를 수행하기 전에 다음 섹션을 스택 템플릿에 포함시키십시오.
+ `AWS::CodeDeployBlueGreen` 변환에 대한 참조를 템플릿에 추가합니다.

  ```
  "Transform": [
    "AWS::CodeDeployBlueGreen"
  ],
  ```
+ `AWS::CodeDeploy::BlueGreen` 후크를 호출하고 배포에 대한 속성을 지정하는 `Hooks` 섹션을 추가합니다. 자세한 내용은 [`AWS::CodeDeploy::BlueGreen` 후크 구문](blue-green-hook-syntax.md) 섹션을 참조하세요.
+ `Resources` 섹션에서 배포에 대한 블루 및 그린 리소스를 정의합니다.

템플릿을 처음으로 생성할 때(즉, 스택 자체를 만들기 전에) 이러한 섹션을 추가하거나 스택 업데이트를 수행하기 전에 기존 템플릿에 추가할 수 있습니다. 새 스택에 블루/그린 배포를 지정하는 경우 CloudFormation은 스택 생성 중에 블루 리소스만 생성하며 그린 배포에 대한 리소스는 스택 업데이트 중에 필요할 때까지 생성되지 않습니다.

## CloudFormation 리소스를 사용하여 블루/그린 배포 모델링
<a name="blue-green-required"></a>

ECS에서 CodeDeploy 블루/그린 배포를 수행하려면 CloudFormation 템플릿에 Amazon ECS 서비스 및 로드 밸런서와 같이 배포를 모델링하는 리소스를 포함해야 합니다. 이러한 리소스 의미에 대한 자세한 내용을 알아보려면 *AWS CodeDeploy 사용 설명서*의 [Amazon ECS 배포를 시작하기 전에](https://docs.aws.amazon.com/codedeploy/latest/userguide/deployment-steps-ecs.html#deployment-steps-prerequisites-ecs)를 참조하세요.


| 요구 사항 | 리소스 | 필수/선택 | 바뀌는 경우 블루/그린 배포 개시? | 
| --- | --- | --- | --- | 
| Amazon ECS 클러스터 | [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-cluster.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-cluster.html) | 선택 사항. 기본 클러스터를 사용할 수 있습니다. | 아니요 | 
| Amazon ECS 서비스 | [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-service.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-service.html) | 필수 사항입니다. | 아니요 | 
| 애플리케이션 또는 Network Load Balancer | [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-ecs-service-loadbalancer.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-ecs-service-loadbalancer.html) | 필수 사항입니다. | 아니요 | 
| 프로덕션 리스너 | [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-listener.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-listener.html) | 필수 사항입니다. | 아니요 | 
| 테스트 리스너  | [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-listener.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-listener.html) | 선택 사항. | 아니요 | 
| 대상 그룹 두 개 | [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html) | 필수 사항입니다. | 아니요 | 
| Amazon ECS 작업 정의  | [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-taskdefinition.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-taskdefinition.html) | 필수 사항입니다. | 예 | 
| Amazon ECS 애플리케이션의 컨테이너 | [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-ecs-taskdefinition-containerdefinition.html#cfn-ecs-taskdefinition-containerdefinition-name](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-ecs-taskdefinition-containerdefinition.html#cfn-ecs-taskdefinition-containerdefinition-name) | 필수 사항입니다. | 아니요 | 
| 대체 작업 세트의 포트 | [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-ecs-taskdefinition-portmapping.html#cfn-ecs-taskdefinition-portmapping-containerport](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-ecs-taskdefinition-portmapping.html#cfn-ecs-taskdefinition-portmapping-containerport) | 필수 사항입니다. | 아니요 | 

## 변경 세트
<a name="blue-green-changesets"></a>

그린 배포를 시작할 스택 업데이트를 수행하기 전에 변경 세트를 생성하는 것이 좋습니다. 이렇게 하면 스택 업데이트를 수행하기 전에 스택에 이루어질 실제 변경 사항을 확인할 수 있습니다. 리소스 변경 사항은 스택 업데이트 중에 수행되는 순서대로 나열되지 않을 수 있습니다. 자세한 내용은 [변경 세트를 사용하여 CloudFormation 스택 업데이트](using-cfn-updating-stacks-changesets.md) 섹션을 참조하세요.

## 스택 이벤트 모니터링
<a name="blue-green-events"></a>

**Stack**(스택) 페이지의 **Events**(이벤트) 탭에서 AWS CLI를 사용하여 ECS 배포의 각 단계에서 생성된 스택 이벤트를 볼 수 있습니다. 자세한 내용은 [스택 진행 상황 모니터링](monitor-stack-progress.md) 섹션을 참조하세요.

## 블루/그린 배포를 위한 IAM 권한
<a name="blue-green-iam"></a>

CloudFormation에서 블루-그린 배포를 성공적으로 수행하려면 다음 CodeDeploy 권한이 있어야 합니다.
+ `codedeploy:Get*`
+ `codedeploy:CreateCloudFormationDeployment`

자세한 내용은 **서비스 권한 부여 참조에서 [CodeDeploy에 사용되는 작업, 리소스 및 조건 키](https://docs.aws.amazon.com/service-authorization/latest/reference/list_awscodedeploy.html)를 참조하세요.

# CloudFormation을 사용하여 ECS 블루/그린 배포를 관리할 때 고려 사항
<a name="blue-green-considerations"></a>

CloudFormation을 사용하여 CodeDeploy를 통해 ECS 블루/그린 배포를 수행하는 프로세스는 CodeDeploy만 사용하는 표준 ECS 배포와는 다릅니다. 차이점을 자세히 알아보려면 **AWS CodeDeploy 사용 설명서의 [CodeDeploy와 CloudFormation을 통한 Amazon ECS 블루/그린 배포 간 차이점](https://docs.aws.amazon.com/codedeploy/latest/userguide/deployments-create-ecs-cfn.html#differences-ecs-bg-cfn)을 참조하세요.

CloudFormation을 사용하여 블루/그린 배포를 관리할 때는 다음과 같은 특정 제한 사항 및 고려 사항을 염두에 두어야 합니다.
+ 특정 리소스에 대한 업데이트만 그린 배포를 트리거합니다. 자세한 내용은 [그린 배포를 개시하는 리소스 업데이트](about-blue-green-deployments.md#blue-green-resources) 섹션을 참조하세요.
+ 그린 배포를 트리거하는 리소스에 대한 업데이트와 다른 리소스에 대한 업데이트를 동일한 스택 업데이트에 포함할 수 없습니다. 자세한 내용은 [그린 배포를 개시하는 리소스 업데이트](about-blue-green-deployments.md#blue-green-resources) 섹션을 참조하세요.
+ 하나의 ECS 서비스만 배포 대상으로 지정할 수 있습니다.
+ CloudFormation에 의해 난독화된 값이 있는 파라미터는 그린 배포 중에 CodeDeploy에서 업데이트할 수 없으며 오류 및 스택 업데이트 실패로 이어질 수 있습니다. 다음이 포함됩니다.
  + `NoEcho` 속성으로 정의된 파라미터
  + 동적 참조를 사용하여 외부 서비스에서 해당 값을 검색하는 파라미터 동적 참조에 대한 자세한 내용은 [동적 참조를 사용하여 다른 서비스에 저장된 값 가져오기](dynamic-references.md)의 내용을 참조하세요.
+ 아직 진행 중인 그린 배포를 취소하려면 CodeDeploy 또는 ECS가 아니라 CloudFormation에서 스택 업데이트를 취소하세요. 자세한 내용은 [스택 업데이트 취소](using-cfn-stack-update-cancel.md) 섹션을 참조하세요. 업데이트가 완료된 후에는 업데이트를 취소할 수 없습니다. 하지만 이전 설정을 사용하여 스택을 다시 업데이트할 수 있습니다.
+ 다음 CloudFormation 기능은 현재 ECS 블루/그린 배포를 정의하는 템플릿에서 지원되지 않습니다.
  + [출력](outputs-section-structure.md) 선언 또는 [Fn::ImportValue](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-importvalue.html) 사용으로 다른 스택에서 값 가져오기.
  + 리소스 가져오기. 리소스 가져오기에 대한 자세한 내용은 [CloudFormation 스택에 AWS 리소스 가져오기](import-resources.md)의 내용을 참조하세요.
  + 중첩 스택 리소스가 포함된 템플릿에 `AWS::CodeDeploy::BlueGreen` 후크 사용하기. 중첩 스택에 대한 자세한 내용은 [중첩 스택을 사용하여 템플릿을 재사용 가능한 조각으로 분할](using-cfn-nested-stacks.md) 섹션을 참조하세요.
  + 중첩 스택에서 `AWS::CodeDeploy::BlueGreen` 후크 사용하기.

# `AWS::CodeDeploy::BlueGreen` 후크 구문
<a name="blue-green-hook-syntax"></a>

다음 구문은 ECS 블루/그린 배포를 위한 `AWS::CodeDeploy::BlueGreen` 후크 구조를 설명합니다.

## 구문
<a name="cfn-blue-green-hook-syntax"></a>

```
"Hooks": {
  "Logical ID": {
    "Type": "AWS::CodeDeploy::BlueGreen",
    "Properties": {
      "TrafficRoutingConfig": {
        "Type": "Traffic routing type",
        "TimeBasedCanary": {
          "StepPercentage": Integer,
          "BakeTimeMins": Integer
        },
        "TimeBasedLinear": {
          "StepPercentage": Integer,
          "BakeTimeMins": Integer
        }
      },
      "AdditionalOptions": {"TerminationWaitTimeInMinutes": Integer},
      "LifecycleEventHooks": {
        "BeforeInstall": "FunctionName",
        "AfterInstall": "FunctionName",
        "AfterAllowTestTraffic": "FunctionName",
        "BeforeAllowTraffic": "FunctionName",
        "AfterAllowTraffic": "FunctionName"
      },
      "ServiceRole": "CodeDeployServiceRoleName",
      "Applications": [
        {
          "Target": {
            "Type": "AWS::ECS::Service",
            "LogicalID": "Logical ID of AWS::ECS::Service"
          },
          "ECSAttributes": {
            "TaskDefinitions": [
              "Logical ID of AWS::ECS::TaskDefinition (Blue)",
              "Logical ID of AWS::ECS::TaskDefinition (Green)"
            ],
            "TaskSets": [
              "Logical ID of AWS::ECS::TaskSet (Blue)",
              "Logical ID of AWS::ECS::TaskSet (Green)"
            ],
            "TrafficRouting": {
              "ProdTrafficRoute": {
                "Type": "AWS::ElasticLoadBalancingV2::Listener",
                "LogicalID": "Logical ID of AWS::ElasticLoadBalancingV2::Listener (Production)"
              },
              "TestTrafficRoute": {
                "Type": "AWS::ElasticLoadBalancingV2::Listener",
                "LogicalID": "Logical ID of AWS::ElasticLoadBalancingV2::Listener (Test)"
              },
              "TargetGroups": [
                "Logical ID of AWS::ElasticLoadBalancingV2::TargetGroup (Blue)",
                "Logical ID of AWS::ElasticLoadBalancingV2::TargetGroup (Green)"
              ]
            }
          }
        }
      ]
    }
  }
}
```

## 속성
<a name="cfn-blue-green-hook-properties"></a>

논리적 ID(**논리명이라고도 함)  
템플릿의 `Hooks` 섹션에서 선언된 후크의 논리적 ID입니다. 논리적 ID는 영숫자(A-Za-z0-9)여야 하며 템플릿 내에서 고유해야 합니다.  
*필수 항목 여부:* 예    
`Type`  
후크의 유형입니다. `AWS::CodeDeploy::BlueGreen`   
*필수 항목 여부:* 예  
`Properties`  
후크의 속성  
*필수 항목 여부:* 예    
`TrafficRoutingConfig`  
트래픽 라우팅 구성 설정  
*필수 항목 여부*: 아니요  
기본 구성은 시간 기반 카나리 트래픽 이동으로 15% 단계 비율 및 5분 베이크 시간입니다.    
`Type`  
배포 구성에 사용되는 트래픽 이동 유형  
유효한 값: AllAtOnce \$1 TimeBasedCanary \$1 TimeBasedLinear  
*필수 항목 여부:* 예    
`TimeBasedCanary`  
배포의 한 버전에서 다른 버전으로 트래픽을 2씩 증분하여 이동하는 구성을 지정합니다.  
*필수*: 조건부: 트래픽 라우팅 유형으로 `TimeBasedCanary`를 지정하는 경우 `TimeBasedCanary` 파라미터를 포함시켜야 합니다.    
`StepPercentage`  
`TimeBasedCanary` 배포의 첫 번째 증분에서 이동할 트래픽의 비율입니다. 단계 비율은 14% 이상이어야 합니다.  
*필수 항목 여부*: 아니요  
`BakeTimeMins`  
`TimeBasedCanary` 배포의 첫 번째와 두 번째 트래픽 이동 사이의 시간(분)입니다.  
*필수 항목 여부*: 아니요  
`TimeBasedLinear`  
동일한 증분(각 증분 사이에 동일한 시간(분) 지정)을 사용하여 배포의 한 버전에서 다른 버전으로 트래픽을 이동하는 구성을 지정합니다.  
*필수*: 조건부: 트래픽 라우팅 유형으로 `TimeBasedLinear`를 지정하는 경우 `TimeBasedLinear` 파라미터를 포함시켜야 합니다.    
`StepPercentage`  
`TimeBasedLinear` 배포의 각 증분이 시작될 때 이동되는 트래픽의 비율. 단계 비율은 14% 이상이어야 합니다.  
*필수 항목 여부*: 아니요  
`BakeTimeMins`  
`TimeBasedLinear` 배포의 각 증분 트래픽 이동 사이의 시간(분)  
*필수 항목 여부*: 아니요  
`AdditionalOptions`  
블루/그린 배포를 위한 추가 옵션  
*필수 항목 여부*: 아니요    
`TerminationWaitTimeInMinutes`  
블루 리소스를 종료하기 전에 대기할 시간(분)을 지정합니다.  
*필수 항목 여부*: 아니요  
`LifecycleEventHooks`  
수명 주기 이벤트 후크를 사용하여 CodeDeploy가 배포를 검증하기 위해 호출할 수 있는 Lambda 함수를 지정합니다. 배포 수명 주기 이벤트에 동일한 함수 또는 다른 함수를 사용할 수 있습니다. 검증 테스트가 완료되면 Lambda `AfterAllowTraffic` 함수는 CodeDeploy를 다시 호출하고 `Succeeded` 또는 `Failed` 결과를 전달합니다. 자세한 내용을 알아보려면 *AWS CodeDeploy 사용 설명서*의 [AppSpec '후크' 섹션](https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html)을 참조하세요.  
*필수 항목 여부*: 아니요    
`BeforeInstall`  
대체 작업 세트가 생성되기 전에 작업을 실행할 때 사용하는 함수  
*필수 항목 여부*: 아니요  
`AfterInstall`  
대체 작업 세트가 생성되었고 대상 그룹 중 하나가 연결된 후 작업을 실행할 때 사용하는 함수  
*필수 항목 여부*: 아니요  
`AfterAllowTestTraffic`  
테스트 리스너가 대체 작업 세트에 트래픽을 제공한 후 작업을 실행할 때 사용하는 함수  
*필수 항목 여부*: 아니요  
`BeforeAllowTraffic`  
트래픽이 대체 작업 세트로 이동되기 전에 두 번째 대상 그룹이 대체 작업 세트와 연결된 후 작업을 실행할 때 사용하는 함수  
*필수 항목 여부*: 아니요  
`AfterAllowTraffic`  
두 번째 대상 그룹이 대체 작업 세트에 트래픽을 제공한 후 작업을 실행할 때 사용하는 함수  
*필수 항목 여부*: 아니요  
`ServiceRole`  
블루 그린 배포를 수행할 때 사용하는 CloudFormation에 대한 실행 역할. 필요한 권한의 목록은 [블루/그린 배포를 위한 IAM 권한](about-blue-green-deployments.md#blue-green-iam) 섹션을 참조하세요.  
*필수 항목 여부*: 아니요  
`Applications`  
Amazon ECS 애플리케이션의 속성을 지정합니다.  
*필수 항목 여부:* 예    
`Target`  
  
*필수 항목 여부:* 예    
`Type`  
리소스의 유형.  
*필수 항목 여부:* 예  
`LogicalID`  
리소스의 논리적 ID  
*필수 항목 여부:* 예  
`ECSAttributes`  
Amazon ECS 애플리케이션 배포의 다양한 요구 사항을 나타내는 리소스  
*필수 항목 여부:* 예    
`TaskDefinitions`  
Amazon ECS 애플리케이션이 포함된 Docker 컨테이너를 실행하기 위한 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-taskdefinition.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-taskdefinition.html) 리소스의 논리적 ID  
*필수 항목 여부:* 예  
`TaskSets`  
애플리케이션의 작업 세트로 사용할 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-taskset.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-taskset.html) 리소스의 논리적 ID  
*필수 항목 여부:* 예  
`TrafficRouting`  
트래픽 라우팅에 사용되는 리소스를 지정합니다.  
*필수 항목 여부:* 예    
`ProdTrafficRoute`  
대상 그룹으로 트래픽을 보내는 데 로드 밸런서에서 사용할 리스너  
*필수 항목 여부:* 예    
`Type`  
리소스의 유형입니다. `AWS::ElasticLoadBalancingV2::Listener`   
*필수 항목 여부:* 예  
`LogicalID`  
리소스의 논리적 ID  
*필수 항목 여부:* 예  
`TestTrafficRoute`  
대상 그룹으로 트래픽을 보내는 데 로드 밸런서에서 사용할 리스너  
*필수 항목 여부:* 예    
`Type`  
리소스의 유형입니다. `AWS::ElasticLoadBalancingV2::Listener`   
*필수 항목 여부:* 예  
`LogicalID`  
리소스의 논리적 ID  
*필수 항목 여부*: 아니요  
`TargetGroups`  
트래픽을 등록된 대상으로 라우팅하기 위해 대상 그룹으로 사용할 리소스의 논리적 ID  
*필수 항목 여부:* 예

# 블루/그린 배포 템플릿 예제
<a name="blue-green-template-example"></a>

다음 예제 템플릿에서는 ECS에서의 CodeDeploy 블루/그린 배포를 설정합니다. 여기에서 단계당 트래픽 라우팅 진행률은 15%이고 각 단계 사이의 안정화 기간은 5분입니다.

템플릿을 이용해 스택을 생성하면 배포의 초기 구성이 프로비저닝됩니다. 따라서 `BlueTaskSet` 리소스(대체해야 하는 리소스)의 속성을 변경한 경우 CloudFormation은 스택 업데이트의 일부로 그린 배포를 시작합니다.

## JSON
<a name="blue-green-template-example.json"></a>

```
{
  "AWSTemplateFormatVersion":"2010-09-09",
  "Parameters":{
    "Vpc":{ "Type":"AWS::EC2::VPC::Id" },
    "Subnet1":{ "Type":"AWS::EC2::Subnet::Id" },
    "Subnet2":{ "Type":"AWS::EC2::Subnet::Id" }
  },
  "Transform":[ "AWS::CodeDeployBlueGreen" ],
  "Hooks":{
    "CodeDeployBlueGreenHook":{
      "Type":"AWS::CodeDeploy::BlueGreen",
      "Properties":{
        "TrafficRoutingConfig":{
          "Type":"TimeBasedCanary",
          "TimeBasedCanary":{
            "StepPercentage":15,
            "BakeTimeMins":5
          }
        },
        "Applications":[
          {
            "Target":{
              "Type":"AWS::ECS::Service",
              "LogicalID":"ECSDemoService"
            },
            "ECSAttributes":{
              "TaskDefinitions":[ "BlueTaskDefinition","GreenTaskDefinition" ],
              "TaskSets":[ "BlueTaskSet","GreenTaskSet" ],
              "TrafficRouting":{
                "ProdTrafficRoute":{
                  "Type":"AWS::ElasticLoadBalancingV2::Listener",
                  "LogicalID":"ALBListenerProdTraffic"
                },
                "TargetGroups":[ "ALBTargetGroupBlue","ALBTargetGroupGreen" ]
              }
            }
          }
        ]
      }
    }
  },
  "Resources":{
    "ExampleSecurityGroup":{
      "Type":"AWS::EC2::SecurityGroup",
      "Properties":{
        "GroupDescription":"Security group for ec2 access",
        "VpcId":{ "Ref":"Vpc" },
        "SecurityGroupIngress":[
          {
            "IpProtocol":"tcp",
            "FromPort":80,
            "ToPort":80,
            "CidrIp":"0.0.0.0/0"
          },
          {
            "IpProtocol":"tcp",
            "FromPort":8080,
            "ToPort":8080,
            "CidrIp":"0.0.0.0/0"
          },
          {
            "IpProtocol":"tcp",
            "FromPort":22,
            "ToPort":22,
            "CidrIp":"0.0.0.0/0"
          }
        ]
      }
    },
    "ALBTargetGroupBlue":{
      "Type":"AWS::ElasticLoadBalancingV2::TargetGroup",
      "Properties":{
        "HealthCheckIntervalSeconds":5,
        "HealthCheckPath":"/",
        "HealthCheckPort":"80",
        "HealthCheckProtocol":"HTTP",
        "HealthCheckTimeoutSeconds":2,
        "HealthyThresholdCount":2,
        "Matcher":{ "HttpCode":"200" },
        "Port":80,
        "Protocol":"HTTP",
        "Tags":[{ "Key":"Group","Value":"Example" }],
        "TargetType":"ip",
        "UnhealthyThresholdCount":4,
        "VpcId":{ "Ref":"Vpc" }
      }
    },
    "ALBTargetGroupGreen":{
      "Type":"AWS::ElasticLoadBalancingV2::TargetGroup",
      "Properties":{
        "HealthCheckIntervalSeconds":5,
        "HealthCheckPath":"/",
        "HealthCheckPort":"80",
        "HealthCheckProtocol":"HTTP",
        "HealthCheckTimeoutSeconds":2,
        "HealthyThresholdCount":2,
        "Matcher":{ "HttpCode":"200" },
        "Port":80,
        "Protocol":"HTTP",
        "Tags":[{ "Key":"Group","Value":"Example" }],
        "TargetType":"ip",
        "UnhealthyThresholdCount":4,
        "VpcId":{ "Ref":"Vpc" }
      }
    },
    "ExampleALB":{
      "Type":"AWS::ElasticLoadBalancingV2::LoadBalancer",
      "Properties":{
        "Scheme":"internet-facing",
        "SecurityGroups":[{ "Ref":"ExampleSecurityGroup" }],
        "Subnets":[{ "Ref":"Subnet1" },{ "Ref":"Subnet2" }],
        "Tags":[{ "Key":"Group","Value":"Example" }],
        "Type":"application",
        "IpAddressType":"ipv4"
      }
    },
    "ALBListenerProdTraffic":{
      "Type":"AWS::ElasticLoadBalancingV2::Listener",
      "Properties":{
        "DefaultActions":[
          {
            "Type":"forward",
            "ForwardConfig":{
              "TargetGroups":[
                {
                  "TargetGroupArn":{ "Ref":"ALBTargetGroupBlue" },
                  "Weight":1
                }
              ]
            }
          }
        ],
        "LoadBalancerArn":{ "Ref":"ExampleALB" },
        "Port":80,
        "Protocol":"HTTP"
      }
    },
    "ALBListenerProdRule":{
      "Type":"AWS::ElasticLoadBalancingV2::ListenerRule",
      "Properties":{
        "Actions":[
          {
            "Type":"forward",
            "ForwardConfig":{
              "TargetGroups":[
                {
                  "TargetGroupArn":{ "Ref":"ALBTargetGroupBlue" },
                  "Weight":1
                }
              ]
            }
          }
        ],
        "Conditions":[
          {
            "Field":"http-header",
            "HttpHeaderConfig":{
              "HttpHeaderName":"User-Agent",
              "Values":[ "Mozilla" ]
            }
          }
        ],
        "ListenerArn":{ "Ref":"ALBListenerProdTraffic" },
        "Priority":1
      }
    },
    "ECSTaskExecutionRole":{
      "Type":"AWS::IAM::Role",
      "Properties":{
        "AssumeRolePolicyDocument":{
          "Version": "2012-10-17",		 	 	 
          "Statement":[
            {
              "Sid":"",
              "Effect":"Allow",
              "Principal":{
                "Service":"ecs-tasks.amazonaws.com"
              },
              "Action":"sts:AssumeRole"
            }
          ]
        },
        "ManagedPolicyArns":[ "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" ]
      }
    },
    "BlueTaskDefinition":{
      "Type":"AWS::ECS::TaskDefinition",
      "Properties":{
        "ExecutionRoleArn":{
          "Fn::GetAtt":[ "ECSTaskExecutionRole","Arn" ]
        },
        "ContainerDefinitions":[
          {
            "Name":"DemoApp",
            "Image":"nginxdemos/hello:latest",
            "Essential":true,
            "PortMappings":[
              {
                "HostPort":80,
                "Protocol":"tcp",
                "ContainerPort":80
              }
            ]
          }
        ],
        "RequiresCompatibilities":[ "FARGATE" ],
        "NetworkMode":"awsvpc",
        "Cpu":"256",
        "Memory":"512",
        "Family":"ecs-demo"
      }
    },
    "ECSDemoCluster":{
      "Type":"AWS::ECS::Cluster",
      "Properties":{}
    },
    "ECSDemoService":{
      "Type":"AWS::ECS::Service",
      "Properties":{
        "Cluster":{ "Ref":"ECSDemoCluster" },
        "DesiredCount":1,
        "DeploymentController":{ "Type":"EXTERNAL" }
      }
    },
    "BlueTaskSet":{
      "Type":"AWS::ECS::TaskSet",
      "Properties":{
        "Cluster":{ "Ref":"ECSDemoCluster" },
        "LaunchType":"FARGATE",
        "NetworkConfiguration":{
          "AwsVpcConfiguration":{
            "AssignPublicIp":"ENABLED",
            "SecurityGroups":[{ "Ref":"ExampleSecurityGroup" }],
            "Subnets":[{ "Ref":"Subnet1" },{ "Ref":"Subnet2" }]
          }
        },
        "PlatformVersion":"1.4.0",
        "Scale":{
          "Unit":"PERCENT",
          "Value":100
        },
        "Service":{ "Ref":"ECSDemoService"},
        "TaskDefinition":{ "Ref":"BlueTaskDefinition" },
        "LoadBalancers":[
          {
            "ContainerName":"DemoApp",
            "ContainerPort":80,
            "TargetGroupArn":{ "Ref":"ALBTargetGroupBlue" }
          }
        ]
      }
    },
    "PrimaryTaskSet":{
      "Type":"AWS::ECS::PrimaryTaskSet",
      "Properties":{
        "Cluster":{ "Ref":"ECSDemoCluster" },
        "Service":{ "Ref":"ECSDemoService" },
        "TaskSetId":{ "Fn::GetAtt":[ "BlueTaskSet","Id" ]
        }
      }
    }
  }
}
```

## YAML
<a name="blue-green-template-example.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  Vpc:
    Type: AWS::EC2::VPC::Id
  Subnet1:
    Type: AWS::EC2::Subnet::Id
  Subnet2:
    Type: AWS::EC2::Subnet::Id
Transform:
  - 'AWS::CodeDeployBlueGreen'
Hooks:
  CodeDeployBlueGreenHook:
    Type: AWS::CodeDeploy::BlueGreen
    Properties:
      TrafficRoutingConfig:
        Type: TimeBasedCanary
        TimeBasedCanary:
          StepPercentage: 15
          BakeTimeMins: 5
      Applications:
        - Target:
            Type: AWS::ECS::Service
            LogicalID: ECSDemoService
          ECSAttributes:
            TaskDefinitions:
              - BlueTaskDefinition
              - GreenTaskDefinition
            TaskSets:
              - BlueTaskSet
              - GreenTaskSet
            TrafficRouting:
              ProdTrafficRoute:
                Type: AWS::ElasticLoadBalancingV2::Listener
                LogicalID: ALBListenerProdTraffic
              TargetGroups:
                - ALBTargetGroupBlue
                - ALBTargetGroupGreen
Resources:
  ExampleSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for ec2 access
      VpcId: !Ref Vpc
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 8080
          ToPort: 8080
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
  ALBTargetGroupBlue:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 5
      HealthCheckPath: /
      HealthCheckPort: '80'
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 2
      HealthyThresholdCount: 2
      Matcher:
        HttpCode: '200'
      Port: 80
      Protocol: HTTP
      Tags:
        - Key: Group
          Value: Example
      TargetType: ip
      UnhealthyThresholdCount: 4
      VpcId: !Ref Vpc
  ALBTargetGroupGreen:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 5
      HealthCheckPath: /
      HealthCheckPort: '80'
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 2
      HealthyThresholdCount: 2
      Matcher:
        HttpCode: '200'
      Port: 80
      Protocol: HTTP
      Tags:
        - Key: Group
          Value: Example
      TargetType: ip
      UnhealthyThresholdCount: 4
      VpcId: !Ref Vpc
  ExampleALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Scheme: internet-facing
      SecurityGroups:
        - !Ref ExampleSecurityGroup
      Subnets:
        - !Ref Subnet1
        - !Ref Subnet2
      Tags:
        - Key: Group
          Value: Example
      Type: application
      IpAddressType: ipv4
  ALBListenerProdTraffic:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          ForwardConfig:
            TargetGroups:
              - TargetGroupArn: !Ref ALBTargetGroupBlue
                Weight: 1
      LoadBalancerArn: !Ref ExampleALB
      Port: 80
      Protocol: HTTP
  ALBListenerProdRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions:
        - Type: forward
          ForwardConfig:
            TargetGroups:
              - TargetGroupArn: !Ref ALBTargetGroupBlue
                Weight: 1
      Conditions:
        - Field: http-header
          HttpHeaderConfig:
            HttpHeaderName: User-Agent
            Values:
              - Mozilla
      ListenerArn: !Ref ALBListenerProdTraffic
      Priority: 1
  ECSTaskExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: ''
            Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy'
  BlueTaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      ExecutionRoleArn: !GetAtt 
        - ECSTaskExecutionRole
        - Arn
      ContainerDefinitions:
        - Name: DemoApp
          Image: 'nginxdemos/hello:latest'
          Essential: true
          PortMappings:
            - HostPort: 80
              Protocol: tcp
              ContainerPort: 80
      RequiresCompatibilities:
        - FARGATE
      NetworkMode: awsvpc
      Cpu: '256'
      Memory: '512'
      Family: ecs-demo
  ECSDemoCluster:
    Type: AWS::ECS::Cluster
    Properties: {}
  ECSDemoService:
    Type: AWS::ECS::Service
    Properties:
      Cluster: !Ref ECSDemoCluster
      DesiredCount: 1
      DeploymentController:
        Type: EXTERNAL
  BlueTaskSet:
    Type: AWS::ECS::TaskSet
    Properties:
      Cluster: !Ref ECSDemoCluster
      LaunchType: FARGATE
      NetworkConfiguration:
        AwsVpcConfiguration:
          AssignPublicIp: ENABLED
          SecurityGroups:
            - !Ref ExampleSecurityGroup
          Subnets:
            - !Ref Subnet1
            - !Ref Subnet2
      PlatformVersion: 1.4.0
      Scale:
        Unit: PERCENT
        Value: 100
      Service: !Ref ECSDemoService
      TaskDefinition: !Ref BlueTaskDefinition
      LoadBalancers:
        - ContainerName: DemoApp
          ContainerPort: 80
          TargetGroupArn: !Ref ALBTargetGroupBlue
  PrimaryTaskSet:
    Type: AWS::ECS::PrimaryTaskSet
    Properties:
      Cluster: !Ref ECSDemoCluster
      Service: !Ref ECSDemoService
      TaskSetId: !GetAtt 
        - BlueTaskSet
        - Id
```

# CloudFormation 템플릿 스니펫
<a name="template-snippets"></a>

이 단원에는 CloudFormation 템플릿의 여러 부분을 선언하는 방법을 알려 주는 다양한 시나리오 예제가 나와 있습니다. 코드 조각을 출발점으로 하여 사용자 지정 템플릿의 섹션을 구성할 수도 있습니다.

**Topics**
+ [일반 템플릿 코드 조각](quickref-general.md)
+ [Auto Scaling CloudFormation 템플릿 코드 조각](quickref-autoscaling.md)
+ [AWS 빌링 콘솔 템플릿 코드 조각](quickref-billingconductor.md)
+ [CloudFormation 템플릿 코드 조각](quickref-cloudformation.md)
+ [Amazon CloudFront 템플릿 코드 조각](quickref-cloudfront.md)
+ [Amazon CloudWatch 템플릿 코드 조각](quickref-cloudwatch.md)
+ [Amazon CloudWatch Logs 템플릿 코드 조각](quickref-cloudwatchlogs.md)
+ [Amazon DynamoDB 템플릿 코드 조각](quickref-dynamodb.md)
+ [Amazon EC2 CloudFormation 템플릿 코드 조각](quickref-ec2.md)
+ [Amazon Elastic Container Service 샘플 템플릿](quickref-ecs.md)
+ [Amazon Elastic File System 샘플 템플릿](quickref-efs.md)
+ [Elastic Beanstalk 템플릿 코드 조각](quickref-elasticbeanstalk.md)
+ [Elastic Load Balancing 템플릿 코드 조각](quickref-elb.md)
+ [AWS Identity and Access Management 템플릿 코드 조각](quickref-iam.md)
+ [AWS Lambda 템플릿](quickref-lambda.md)
+ [Amazon Redshift 템플릿 코드 조각](quickref-redshift.md)
+ [Amazon RDS 템플릿 코드 조각](quickref-rds.md)
+ [Route 53 템플릿 코드 조각](quickref-route53.md)
+ [Amazon S3 템플릿 코드 조각](quickref-s3.md)
+ [Amazon SNS 템플릿 코드 조각](quickref-sns.md)
+ [Amazon SQS 템플릿 코드 조각](scenario-sqs-queue.md)
+ [Amazon Timestream 템플릿 코드 조각](scenario-timestream-queue.md)

# 일반 템플릿 코드 조각
<a name="quickref-general"></a>

다음은 AWS 서비스에 특정하지 않은 여러 CloudFormation 템플릿의 특징을 보여주는 예제입니다.

**Topics**
+ [Base64로 인코딩된 UserData 속성](#scenario-userdata-base64)
+ [AccessKey 및 SecretKey가 있는 Base64로 인코딩된 UserData 속성](#scenario-userdata-base64-with-keys)
+ [리터럴 문자열 파라미터가 하나 있는 Parameters 섹션](#scenario-one-string-parameter)
+ [정규식 제약 조건이 포함된 문자열 파라미터가 있는 Parameters 섹션](#scenario-constraint-string-parameter)
+ [MinValue 및 MaxValue 제약 조건이 포함된 숫자 파라미터가 있는 Parameters 섹션](#scenario-one-number-min-parameter)
+ [AllowedValues 제약 조건이 포함된 숫자 파라미터가 있는 Parameters 섹션](#scenario-one-number-parameter)
+ [리터럴 CommaDelimitedList 파라미터가 하나 있는 Parameters 섹션](#scenario-one-list-parameter)
+ [가상 파라미터를 기반으로 한 파라미터 값이 있는 Parameters 섹션](#scenario-one-pseudo-parameter)
+ [매핑이 3개 있는 Mapping 섹션](#scenario-mapping-with-four-maps)
+ [리터럴 문자열 기반 Description](#scenario-description-from-literal-string)
+ [리터럴 문자열 출력이 하나 있는 Outputs 섹션](#scenario-output-with-literal-string)
+ [리소스 참조 및 가상 참조 출력이 각각 하나씩 있는 Outputs 섹션](#scenario-output-with-ref-and-pseudo-ref)
+ [함수, 리터럴 문자열, 참조 및 가상 파라미터를 기반으로 한 출력이 있는 Outputs 섹션](#scenario-output-with-complex-spec)
+ [템플릿 포맷 버전](#scenario-format-version)
+ [AWS Tags 속성](#scenario-format-aws-tag)

## Base64로 인코딩된 UserData 속성
<a name="scenario-userdata-base64"></a>

이 예제는 `Fn::Base64` 및 `Fn::Join` 함수를 사용하여 `UserData` 속성의 조합을 보여줍니다. 참조 `MyValue` 및 `MyName`은 템플릿의 `Parameters` 섹션에 정의되어야 하는 파라미터입니다. 리터럴 문자열 `Hello World`는 이 예제에서 `UserData`의 일부로 전달하는 또 다른 값입니다.

### JSON
<a name="quickref-general-example-1.json"></a>

```
1. "UserData" : {
2.     "Fn::Base64" : {
3.         "Fn::Join" : [ ",", [
4.             { "Ref" : "MyValue" },
5.             { "Ref" : "MyName" },
6.             "Hello World" ] ]
7.     }
8. }
```

### YAML
<a name="quickref-general-example-1.yaml"></a>

```
1. UserData:
2.   Fn::Base64: !Sub |
3.      Ref: MyValue
4.      Ref: MyName
5.      Hello World
```

## AccessKey 및 SecretKey가 있는 Base64로 인코딩된 UserData 속성
<a name="scenario-userdata-base64-with-keys"></a>

이 예제는 `Fn::Base64` 및 `Fn::Join` 함수를 사용하여 `UserData` 속성의 조합을 보여줍니다. 여기에는 `AccessKey` 및 `SecretKey` 정보가 포함됩니다. 참조 `AccessKey` 및 `SecretKey`는 템플릿의 파라미터 섹션에 정의되어야 하는 파라미터입니다.

### JSON
<a name="quickref-general-example-2.json"></a>

```
1. "UserData" : {
2.     "Fn::Base64" : {
3.         "Fn::Join" : [ "", [
4.             "ACCESS_KEY=", { "Ref" : "AccessKey" },
5.             "SECRET_KEY=", { "Ref" : "SecretKey" } ]
6.         ]
7.     }
8. }
```

### YAML
<a name="quickref-general-example-2.yaml"></a>

```
1. UserData:
2.   Fn::Base64: !Sub |
3.      ACCESS_KEY=${AccessKey}
4.      SECRET_KEY=${SecretKey}
```

## 리터럴 문자열 파라미터가 하나 있는 Parameters 섹션
<a name="scenario-one-string-parameter"></a>

다음 예제에서는 `String` 유형 파라미터 하나가 선언된 유효한 파라미터 섹션 선언을 보여줍니다.

### JSON
<a name="quickref-general-example-3.json"></a>

```
1. "Parameters" : {
2.     "UserName" : {
3.         "Type" : "String",
4.         "Default" : "nonadmin",
5.         "Description" : "Assume a vanilla user if no command-line spec provided"
6.     }
7. }
```

### YAML
<a name="quickref-general-example-3.yaml"></a>

```
1. Parameters:
2.   UserName:
3.     Type: String
4.     Default: nonadmin
5.     Description: Assume a vanilla user if no command-line spec provided
```

## 정규식 제약 조건이 포함된 문자열 파라미터가 있는 Parameters 섹션
<a name="scenario-constraint-string-parameter"></a>

다음 예제에서는 `String` 유형 파라미터 하나가 선언된 유효한 파라미터 섹션 선언을 보여줍니다. `AdminUserAccount` 파라미터의 기본값은 `admin`입니다. 이 파라미터 값은 최소 길이가 1자, 최대 길이가 16자여야 하며 영문자 및 숫자를 포함해야 하지만 영문자로 시작해야 합니다.

### JSON
<a name="quickref-general-example-4.json"></a>

```
 1. "Parameters" : {
 2.     "AdminUserAccount": {
 3.       "Default": "admin",
 4.       "NoEcho": "true",
 5.       "Description" : "The admin account user name",
 6.       "Type": "String",
 7.       "MinLength": "1",
 8.       "MaxLength": "16",
 9.       "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*"
10.     }
11. }
```

### YAML
<a name="quickref-general-example-4.yaml"></a>

```
1. Parameters:
2.   AdminUserAccount:
3.     Default: admin
4.     NoEcho: true
5.     Description: The admin account user name
6.     Type: String
7.     MinLength: 1
8.     MaxLength: 16
9.     AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'
```

## MinValue 및 MaxValue 제약 조건이 포함된 숫자 파라미터가 있는 Parameters 섹션
<a name="scenario-one-number-min-parameter"></a>

다음 예제에서는 `Number` 유형 파라미터 하나가 선언된 유효한 파라미터 섹션 선언을 보여줍니다. `WebServerPort` 파라미터는 기본값이 80이고, 최솟값은 1, 최댓값은 65,535입니다.

### JSON
<a name="quickref-general-example-5.json"></a>

```
1. "Parameters" : {
2.     "WebServerPort": {
3.       "Default": "80",
4.       "Description" : "TCP/IP port for the web server",
5.       "Type": "Number",
6.       "MinValue": "1",
7.       "MaxValue": "65535"
8.     }
9. }
```

### YAML
<a name="quickref-general-example-5.yaml"></a>

```
1. Parameters:
2.   WebServerPort:
3.     Default: 80
4.     Description: TCP/IP port for the web server
5.     Type: Number
6.     MinValue: 1
7.     MaxValue: 65535
```

## AllowedValues 제약 조건이 포함된 숫자 파라미터가 있는 Parameters 섹션
<a name="scenario-one-number-parameter"></a>

다음 예제에서는 `Number` 유형 파라미터 하나가 선언된 유효한 파라미터 섹션 선언을 보여줍니다. `WebServerPort` 파라미터는 기본값이 80이고, 80\$18,888의 값만 허용합니다.

### JSON
<a name="quickref-general-example-6.json"></a>

```
1. "Parameters" : {
2.     "WebServerPortLimited": {
3.       "Default": "80",
4.       "Description" : "TCP/IP port for the web server",
5.       "Type": "Number",
6.       "AllowedValues" : ["80", "8888"]
7.     }
8. }
```

### YAML
<a name="quickref-general-example-6.yaml"></a>

```
1. Parameters:
2.   WebServerPortLimited:
3.     Default: 80
4.     Description: TCP/IP port for the web server
5.     Type: Number
6.     AllowedValues:
7.     - 80
8.     - 8888
```

## 리터럴 CommaDelimitedList 파라미터가 하나 있는 Parameters 섹션
<a name="scenario-one-list-parameter"></a>

다음 예제는 단일 `CommaDelimitedList` 유형 파라미터가 선언된 유효한 `Parameters` 섹션 선언을 보여줍니다. `NoEcho` 속성은 `TRUE`로 설정되어 있으며, 아래 지정된 위치에 저장된 정보를 제외하고 **describe-stacks** 출력에서 값이 별표(\$1\$1\$1\$1\$1)로 마스킹 처리됩니다.

**중요**  
`NoEcho` 속성을 사용해도 다음에 저장된 정보는 마스킹되지 않습니다.  
`Metadata` 템플릿 섹션. CloudFormation은 `Metadata` 섹션에 포함된 정보를 변환, 수정 또는 삭제하지 않습니다. 자세한 내용은 [메타데이터](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html)를 참조하십시오.
`Outputs` 템플릿 섹션. 자세한 내용은 [출력](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html)을 참조하십시오.
리소스 정의의 `Metadata` 속성입니다. 자세한 내용은 [`Metadata` 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-metadata.html)을 참조하세요.
이러한 메커니즘을 사용하여 암호나 보안 정보와 같은 중요한 정보를 포함하지 않는 것이 좋습니다.

**중요**  
AWS Systems Manager Parameter Store 또는 AWS Secrets Manager와 같이 CloudFormation 외부에서 저장 및 관리되는 중요한 정보를 참조하려면 CloudFormation 템플릿에 직접 중요한 정보를 포함하는 대신 스택 템플릿에 있는 동적 파라미터를 사용하는 것이 좋습니다.  
자세한 내용은 [템플릿에 자격 증명을 포함하지 않음](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/security-best-practices.html#creds)을 참조하십시오.

### JSON
<a name="quickref-general-example-7.json"></a>

```
1. "Parameters" : {
2.     "UserRoles" : {
3.         "Type" : "CommaDelimitedList",
4.         "Default" : "guest,newhire",
5.         "NoEcho" : "TRUE"
6.     }
7. }
```

### YAML
<a name="quickref-general-example-7.yaml"></a>

```
1. Parameters:
2.   UserRoles:
3.     Type: CommaDelimitedList
4.     Default: "guest,newhire"
5.     NoEcho: true
```

## 가상 파라미터를 기반으로 한 파라미터 값이 있는 Parameters 섹션
<a name="scenario-one-pseudo-parameter"></a>

다음 예제에서는 가상 파라미터 `AWS::StackName` 및 `AWS::Region`을 사용하는 EC2 사용자 데이터의 명령을 보여줍니다. 가상 parameters에 대한 자세한 내용은 [가상 파라미터를 사용하여 AWS 값 가져오기](pseudo-parameter-reference.md) 단원을 참조하십시오.

### JSON
<a name="quickref-general-example-10.json"></a>

```
 1.           "UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
 2.              "#!/bin/bash -xe\n",
 3.              "yum install -y aws-cfn-bootstrap\n",
 4. 
 5.              "/opt/aws/bin/cfn-init -v ",
 6.              "         --stack ", { "Ref" : "AWS::StackName" },
 7.              "         --resource LaunchConfig ",
 8.              "         --region ", { "Ref" : "AWS::Region" }, "\n",
 9. 
10.              "/opt/aws/bin/cfn-signal -e $? ",
11.              "         --stack ", { "Ref" : "AWS::StackName" },
12.              "         --resource WebServerGroup ",
13.              "         --region ", { "Ref" : "AWS::Region" }, "\n"
14.         ]]}}
15.       }
```

### YAML
<a name="quickref-general-example-10.yaml"></a>

```
1. UserData:
2.   Fn::Base64: !Sub |
3.      #!/bin/bash -xe
4.      yum update -y aws-cfn-bootstrap
5.      /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfig --region ${AWS::Region}
6.      /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerGroup --region ${AWS::Region}
```

## 매핑이 3개 있는 Mapping 섹션
<a name="scenario-mapping-with-four-maps"></a>

다음 예제는 매핑이 3개 있는 유효한 `Mapping` 섹션 선언을 보여줍니다. `Stop`, `SlowDown` 또는 `Go`의 매핑 키와 일치하는 경우 맵은 해당하는 `RGBColor` 속성에 할당된 RGB 값을 제공합니다.

### JSON
<a name="quickref-general-example-11.json"></a>

```
 1. "Mappings" : {
 2.     "LightColor" : {
 3.         "Stop" : {
 4.             "Description" : "red",
 5.             "RGBColor" : "RED 255 GREEN 0 BLUE 0"
 6.         },
 7.         "SlowDown" : {
 8.             "Description" : "yellow",
 9.             "RGBColor" : "RED 255 GREEN 255 BLUE 0"
10.         },
11.         "Go" : {
12.             "Description" : "green",
13.             "RGBColor" : "RED 0 GREEN 128 BLUE 0"
14.         }
15.     }
16. }
```

### YAML
<a name="quickref-general-example-11.yaml"></a>

```
 1. Mappings:
 2.   LightColor:
 3.     Stop:
 4.       Description: red
 5.       RGBColor: "RED 255 GREEN 0 BLUE 0"
 6.     SlowDown:
 7.       Description: yellow
 8.       RGBColor: "RED 255 GREEN 255 BLUE 0"
 9.     Go:
10.       Description: green
11.       RGBColor: "RED 0 GREEN 128 BLUE 0"
```

## 리터럴 문자열 기반 Description
<a name="scenario-description-from-literal-string"></a>

다음 예제는 값이 리터럴 문자열을 기반으로 하는 유효한 `Description` 섹션 선언을 보여줍니다. 이 코드 조각은 템플릿, 파라미터, 리소스, 속성 또는 출력에 대한 코드 조각일 수 있습니다.

### JSON
<a name="quickref-general-example-8.json"></a>

```
1. "Description" : "Replace this value"
```

### YAML
<a name="quickref-general-example-8.yaml"></a>

```
1. Description: "Replace this value"
```

## 리터럴 문자열 출력이 하나 있는 Outputs 섹션
<a name="scenario-output-with-literal-string"></a>

이 예제에서는 리터럴 문자열을 기반으로 한 출력 할당을 보여줍니다.

### JSON
<a name="quickref-general-example-12.json"></a>

```
1. "Outputs" : {
2.     "MyPhone" : {
3.         "Value" : "Please call 555-5555",
4.         "Description" : "A random message for aws cloudformation describe-stacks"
5.     }
6. }
```

### YAML
<a name="quickref-general-example-12.yaml"></a>

```
1. Outputs:
2.   MyPhone:
3.     Value: Please call 555-5555
4.     Description: A random message for aws cloudformation describe-stacks
```

## 리소스 참조 및 가상 참조 출력이 각각 하나씩 있는 Outputs 섹션
<a name="scenario-output-with-ref-and-pseudo-ref"></a>

이 예제는 출력 할당이 2개 있는 `Outputs` 섹션이 표시됩니다. 출력 할당 하나는 리소스를 기반으로 하고, 다른 하나는 가상 참조를 기반으로 합니다.

### JSON
<a name="quickref-general-example-13.json"></a>

```
1. "Outputs" : {
2.    "SNSTopic" : { "Value" : { "Ref" : "MyNotificationTopic" } },
3.    "StackName" : { "Value" : { "Ref" : "AWS::StackName" } }
4. }
```

### YAML
<a name="quickref-general-example-13.yaml"></a>

```
1. Outputs:
2.   SNSTopic:
3.     Value: !Ref MyNotificationTopic
4.   StackName:
5.     Value: !Ref AWS::StackName
```

## 함수, 리터럴 문자열, 참조 및 가상 파라미터를 기반으로 한 출력이 있는 Outputs 섹션
<a name="scenario-output-with-complex-spec"></a>

이 예제에서는 출력 할당이 한 개 있는 출력 섹션이 표시됩니다. 퍼센트 기호를 구분 기호로 사용하여 값을 연결하기 위해 Join 함수가 사용됩니다.

### JSON
<a name="quickref-general-example-14.json"></a>

```
1. "Outputs" : {
2.     "MyOutput" : {
3.         "Value" : { "Fn::Join" :
4.             [ "%", [ "A-string", {"Ref" : "AWS::StackName" } ] ]
5.         }
6.     }
7. }
```

### YAML
<a name="quickref-general-example-14.yaml"></a>

```
1. Outputs:
2.   MyOutput:
3.     Value: !Join [ %, [ 'A-string', !Ref 'AWS::StackName' ]]
```

## 템플릿 포맷 버전
<a name="scenario-format-version"></a>

다음 코드 조각은 유효한 `AWSTemplateFormatVersion` 섹션 선언을 보여줍니다.

### JSON
<a name="quickref-general-example-9.json"></a>

```
1. "AWSTemplateFormatVersion" : "2010-09-09"
```

### YAML
<a name="quickref-general-example-9.yaml"></a>

```
1. AWSTemplateFormatVersion: '2010-09-09'
```

## AWS Tags 속성
<a name="scenario-format-aws-tag"></a>

이 예제는 AWS `Tags` 속성을 보여줍니다. 이 속성은 리소스의 속성 섹션 내에서 지정합니다. 리소스가 생성되면 선언한 태그로 리소스에 태그가 지정됩니다.

### JSON
<a name="quickref-general-example-15.json"></a>

```
 1. "Tags" : [
 2.       {
 3.         "Key" : "keyname1",
 4.         "Value" : "value1"
 5.       },
 6.       {
 7.         "Key" : "keyname2",
 8.         "Value" : "value2"
 9.       }
10.     ]
```

### YAML
<a name="quickref-general-example-15.yaml"></a>

```
1. Tags: 
2.   - 
3.     Key: "keyname1"
4.     Value: "value1"
5.   - 
6.     Key: "keyname2"
7.     Value: "value2"
```

# Auto Scaling CloudFormation 템플릿 코드 조각
<a name="quickref-autoscaling"></a>

Amazon EC2 Auto Scaling을 사용하여 조정 정책 또는 예약된 조정을 통해 Amazon EC2 인스턴스를 자동으로 조정할 수 있습니다. Auto Scaling 그룹은 조정 정책, 예약된 작업, 상태 확인, 수명 주기 후크, 로드 밸런싱과 같은 자동 조정 및 플릿 관리 기능을 지원하는 Amazon EC2 인스턴스의 모음입니다.

Application Auto Scaling은 조정 정책 또는 예약된 조정으로 Amazon EC2 이외의 리소스를 자동으로 조정합니다.

CloudFormation 템플릿을 사용하여 Auto Scaling 그룹, 조정 정책, 예약된 작업, 기타 Auto Scaling 리소스를 인프라의 일부로 생성하고 구성할 수 있습니다. 템플릿을 사용하면 반복 가능하고 일관된 방식으로 Auto Scaling 리소스 배포를 쉽게 관리하고 자동화할 수 있습니다.

다음 예시 템플릿 코드 조각은 Amazon EC2 Auto Scaling 및 Application Auto Scalin을 위한 CloudFormation 리소스 또는 구성 요소에 대해 설명합니다. 이러한 코드 조각은 템플릿에 통합되도록 설계되었으며 독립적으로 실행되도록 설계되지 않았습니다.

**Topics**
+ [Amazon EC2 Auto Scaling 리소스 구성](quickref-ec2-auto-scaling.md)
+ [Application Auto Scaling 리소스 구성](quickref-application-auto-scaling.md)

# CloudFormation을 사용한 Amazon EC2 Auto Scaling 리소스 구성
<a name="quickref-ec2-auto-scaling"></a>

다음 예에서는 Amazon EC2 Auto Scaling과 함께 사용할 템플릿에 포함할 수 있는 다양한 스니펫을 보여줍니다.

**Topics**
+ [단일 인스턴스 Auto Scaling 그룹 생성](#scenario-single-instance-as-group)
+ [연결된 로드 밸런서를 사용하여 Auto Scaling 그룹 생성](#scenario-as-group)
+ [알림을 사용하여 Auto Scaling 그룹 생성](#scenario-as-notification)
+ [`CreationPolicy` 및 `UpdatePolicy`를 사용하는 Auto Scaling 그룹 생성](#scenario-as-updatepolicy)
+ [단계 조정 정책 삭제](#scenario-step-scaling-policy)
+ [혼합 인스턴스 그룹 예제](#scenario-mixed-instances-group-template-examples)
+ [시작 구성 예제](#scenario-launch-config-template-examples)

## 단일 인스턴스 Auto Scaling 그룹 생성
<a name="scenario-single-instance-as-group"></a>

이 예에서는 시작하는 데 도움이 되는 단일 인스턴스가 포함된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html) 리소스를 보여줍니다. auto scaling의 `VPCZoneIdentifier` 속성은 3개의 서로 다른 가용 영역에 있는 기존 서브넷 목록을 지정합니다. 스택을 만들기 전에 계정에서 적용 가능한 서브넷 ID를 지정해야 합니다. `LaunchTemplate` 속성은 템플릿의 다른 곳에 정의된 논리명이 `myLaunchTemplate`인 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html) 리소스를 참조합니다.

**참고**  
시작 템플릿의 예는 Amazon EC2 코드 조각 섹션의 [CloudFormation을 사용하여 시작 템플릿 생성](quickref-ec2-launch-templates.md) 및 `AWS::EC2::LaunchTemplate` 리소스의 [예](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html#aws-resource-ec2-launchtemplate--examples) 섹션을 참조하세요.

### JSON
<a name="quickref-autoscaling-example-1.json"></a>

```
 1. "myASG" : {
 2.    "Type" : "AWS::AutoScaling::AutoScalingGroup",
 3.    "Properties" : {
 4.       "VPCZoneIdentifier" : [ "subnetIdAz1", "subnetIdAz2", "subnetIdAz3" ],
 5.       "LaunchTemplate" : {
 6.         "LaunchTemplateId" : {
 7.           "Ref" : "myLaunchTemplate"
 8.         },
 9.         "Version" : {
10.           "Fn::GetAtt" : [
11.             "myLaunchTemplate",
12.             "LatestVersionNumber"
13.           ]
14.         }
15.       },
16.       "MaxSize" : "1",
17.       "MinSize" : "1"
18.    }
19. }
```

### YAML
<a name="quickref-autoscaling-example-1.yaml"></a>

```
 1. myASG:
 2.   Type: AWS::AutoScaling::AutoScalingGroup
 3.   Properties:
 4.     VPCZoneIdentifier:
 5.       - subnetIdAz1
 6.       - subnetIdAz2
 7.       - subnetIdAz3
 8.     LaunchTemplate:
 9.       LaunchTemplateId: !Ref myLaunchTemplate
10.       Version: !GetAtt myLaunchTemplate.LatestVersionNumber
11.     MaxSize: '1'
12.     MinSize: '1'
```

## 연결된 로드 밸런서를 사용하여 Auto Scaling 그룹 생성
<a name="scenario-as-group"></a>

이 예에서는 여러 서버에 대한 로드 밸런싱을 위한 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html) 리소스를 보여줍니다. 동일한 템플릿의 다른 곳에서 선언된 AWS 리소스의 논리적 이름을 지정합니다.

1. `VPCZoneIdentifier` 속성은 Auto Scaling 그룹의 EC2 인스턴스가 생성될 두 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-subnet.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-subnet.html) 리소스의 논리명인 `myPublicSubnet1` 및 `myPublicSubnet2`를 지정합니다.

1. `LaunchTemplate` 속성은 논리명이 `myLaunchTemplate`인 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html) 리소스를 지정합니다.

1. `TargetGroupARNs` 속성은 트래픽을 Auto Scaling 그룹으로 라우팅하는 데 사용되는 Application Load Balancer 또는 Network Load Balancer의 대상 그룹을 나열합니다. 이 예에서는 논리명이 `myTargetGroup`인 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html) 리소스에 하나의 대상 그룹이 지정됩니다.

### JSON
<a name="quickref-autoscaling-example-2.json"></a>

```
 1. "myServerGroup" : {
 2.    "Type" : "AWS::AutoScaling::AutoScalingGroup",
 3.    "Properties" : {
 4.       "VPCZoneIdentifier" : [ { "Ref" : "myPublicSubnet1" }, { "Ref" : "myPublicSubnet2" } ],
 5.       "LaunchTemplate" : {
 6.         "LaunchTemplateId" : {
 7.           "Ref" : "myLaunchTemplate"
 8.         },
 9.         "Version" : {
10.           "Fn::GetAtt" : [
11.             "myLaunchTemplate",
12.             "LatestVersionNumber"
13.           ]
14.         }
15.       },
16.       "MaxSize" : "5",
17.       "MinSize" : "1",
18.       "TargetGroupARNs" : [ { "Ref" : "myTargetGroup" } ]
19.    }
20. }
```

### YAML
<a name="quickref-autoscaling-example-2.yaml"></a>

```
 1. myServerGroup:
 2.   Type: AWS::AutoScaling::AutoScalingGroup
 3.   Properties:
 4.     VPCZoneIdentifier:
 5.       - !Ref myPublicSubnet1
 6.       - !Ref myPublicSubnet2
 7.     LaunchTemplate:
 8.       LaunchTemplateId: !Ref myLaunchTemplate
 9.       Version: !GetAtt myLaunchTemplate.LatestVersionNumber
10.     MaxSize: '5'
11.     MinSize: '1'
12.     TargetGroupARNs:
13.       - !Ref myTargetGroup
```

### 다음 사항도 참조하세요.
<a name="scenario-as-group-see-also"></a>

Application Load Balancer에 대한 `ALBRequestCountPerTarget` 사전 정의 지표에 따라 대상 추적 조정 정책을 사용하여 auto scaling을 생성하는 자세한 예제는 `AWS::AutoScaling::ScalingPolicy` 리소스의 [예제](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-scalingpolicy.html#aws-resource-autoscaling-scalingpolicy--examples) 섹션을 참조하세요.

## 알림을 사용하여 Auto Scaling 그룹 생성
<a name="scenario-as-notification"></a>

이 예에서는 지정된 이벤트가 발생하면 Amazon SNS 알림을 보내는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html) 리소스를 보여줍니다. `NotificationConfigurations` 속성은 CloudFormation에서 알림을 보내는 SNS 주제와 CloudFormation에서 알림을 보내는 원인 이벤트를 지정합니다. `NotificationTypes`에 지정된 이벤트가 발생하면 CloudFormation에서 `TopicARN`에 지정된 SNS 주제에 알림을 보냅니다. 스택을 시작하면 CloudFormation에서 동일한 템플릿 내에 선언된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-subscription.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-subscription.html) 리소스(`snsTopicForAutoScalingGroup`)를 생성합니다.

auto scaling의 `VPCZoneIdentifier` 속성은 3개의 서로 다른 가용 영역에 있는 기존 서브넷 목록을 지정합니다. 스택을 만들기 전에 계정에서 적용 가능한 서브넷 ID를 지정해야 합니다. `LaunchTemplate` 속성은 동일한 템플릿의 다른 곳에서 선언된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html) 리소스의 논리명을 참조합니다.

### JSON
<a name="quickref-autoscaling-example-3.json"></a>

```
 1. "myASG" : {
 2.   "Type" : "AWS::AutoScaling::AutoScalingGroup",
 3.   "DependsOn": [
 4.     "snsTopicForAutoScalingGroup"
 5.   ],
 6.   "Properties" : {
 7.     "VPCZoneIdentifier" : [ "subnetIdAz1", "subnetIdAz2", "subnetIdAz3" ],
 8.     "LaunchTemplate" : {
 9.       "LaunchTemplateId" : {
10.         "Ref" : "logicalName"
11.       },
12.       "Version" : {
13.         "Fn::GetAtt" : [
14.           "logicalName",
15.           "LatestVersionNumber"
16.         ]
17.       }
18.     },
19.     "MaxSize" : "5",
20.     "MinSize" : "1",
21.     "NotificationConfigurations" : [
22.       {
23.         "TopicARN" : { "Ref" : "snsTopicForAutoScalingGroup" },
24.         "NotificationTypes" : [
25.           "autoscaling:EC2_INSTANCE_LAUNCH",
26.           "autoscaling:EC2_INSTANCE_LAUNCH_ERROR",
27.           "autoscaling:EC2_INSTANCE_TERMINATE",
28.           "autoscaling:EC2_INSTANCE_TERMINATE_ERROR",
29.           "autoscaling:TEST_NOTIFICATION"
30.         ]
31.       }
32.     ]
33.   }
34. }
```

### YAML
<a name="quickref-autoscaling-example-3.yaml"></a>

```
 1. myASG:
 2.   Type: AWS::AutoScaling::AutoScalingGroup
 3.   DependsOn:
 4.     - snsTopicForAutoScalingGroup
 5.   Properties:
 6.     VPCZoneIdentifier:
 7.       - subnetIdAz1
 8.       - subnetIdAz2
 9.       - subnetIdAz3
10.     LaunchTemplate:
11.       LaunchTemplateId: !Ref logicalName
12.       Version: !GetAtt logicalName.LatestVersionNumber
13.     MaxSize: '5'
14.     MinSize: '1'
15.     NotificationConfigurations:
16.       - TopicARN: !Ref snsTopicForAutoScalingGroup
17.         NotificationTypes:
18.           - autoscaling:EC2_INSTANCE_LAUNCH
19.           - autoscaling:EC2_INSTANCE_LAUNCH_ERROR
20.           - autoscaling:EC2_INSTANCE_TERMINATE
21.           - autoscaling:EC2_INSTANCE_TERMINATE_ERROR
22.           - autoscaling:TEST_NOTIFICATION
```

## `CreationPolicy` 및 `UpdatePolicy`를 사용하는 Auto Scaling 그룹 생성
<a name="scenario-as-updatepolicy"></a>

다음 예는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html) 리소스에 `CreationPolicy` 및 `UpdatePolicy` 속성을 추가하는 방법을 보여줍니다.

샘플 생성 정책은 auto scaling이 준비가 되면 CloudFormation이 `Count` 개수의 성공 신호를 받을 때까지 `CREATE_COMPLETE` 상태가 되지 않도록 합니다. auto scaling이 준비되었음을 알리기 위해 시작 템플릿의 사용자 데이터(표시되지 않음)에 추가된 `cfn-signal` 헬퍼 스크립트가 인스턴스에서 실행됩니다. 인스턴스가 지정된 `Timeout` 내에 신호를 보내지 않으면 CloudFormation은 인스턴스가 생성되지 않은 것으로 가정하고, 리소스 생성이 실패하고, CloudFormation은 스택을 롤백합니다.

샘플 업데이트 정책은 CloudFormation에 `AutoScalingRollingUpdate` 속성을 사용하여 롤링 업데이트를 수행하도록 지시합니다. 롤링 업데이트는 `MaxBatchSize`에 기반한 작은 배치(이 예에서는 인스턴스 단위)의 Auto Scaling 그룹, `PauseTime`에 기반한 업데이트의 배치 간 일시 중지 시간을 변경합니다. `MinInstancesInService` 속성은 CloudFormation에서 이전 인스턴스를 업데이트하는 동안 Auto Scaling 그룹 내에서 작동해야 하는 최소 인스턴스 수를 지정합니다.

`WaitOnResourceSignals` 속성이 `true`로 설정되어 있습니다. 업데이트를 계속 진행하려면 CloudFormation이 지정된 `PauseTime` 내에 각각의 새 인스턴스로부터 신호를 수신해야 합니다. 스택 업데이트가 진행되는 동안 `HealthCheck`, `ReplaceUnhealthy`, `AZRebalance`, `AlarmNotification` 및 `ScheduledActions` 같은 EC2 Auto Scaling 프로세스가 일시 중단됩니다. 참고: 이 경우 롤링 업데이트가 제대로 작동하지 않을 수 있으므로 `Launch`, `Terminate` 또는 `AddToLoadBalancer`(Auto Scaling 그룹이 Elastic Load Balancing와 함께 사용되는 경우) 프로세스 유형을 일시 중지하지 마십시오.

auto scaling의 `VPCZoneIdentifier` 속성은 3개의 서로 다른 가용 영역에 있는 기존 서브넷 목록을 지정합니다. 스택을 만들기 전에 계정에서 적용 가능한 서브넷 ID를 지정해야 합니다. `LaunchTemplate` 속성은 동일한 템플릿의 다른 곳에서 선언된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html) 리소스의 논리명을 참조합니다.

`CreationPolicy` 및 `UpdatePolicy` 속성에 대한 자세한 내용은 [리소스 속성 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-product-attribute-reference.html) 섹션을 참조하세요.

### JSON
<a name="quickref-autoscaling-example-4.json"></a>

```
{
  "Resources":{
    "myASG":{
      "CreationPolicy":{
        "ResourceSignal":{
          "Count":"3",
          "Timeout":"PT15M"
        }
      },
      "UpdatePolicy":{
        "AutoScalingRollingUpdate":{
          "MinInstancesInService":"3",
          "MaxBatchSize":"1",
          "PauseTime":"PT12M5S",
          "WaitOnResourceSignals":"true",
          "SuspendProcesses":[
            "HealthCheck",
            "ReplaceUnhealthy",
            "AZRebalance",
            "AlarmNotification",
            "ScheduledActions",
            "InstanceRefresh"
          ]
        }
      },
      "Type":"AWS::AutoScaling::AutoScalingGroup",
      "Properties":{
        "VPCZoneIdentifier":[ "subnetIdAz1", "subnetIdAz2", "subnetIdAz3" ],
        "LaunchTemplate":{
          "LaunchTemplateId":{
            "Ref":"logicalName"
          },
          "Version":{
            "Fn::GetAtt":[
              "logicalName",
              "LatestVersionNumber"
            ]
          }
        },
        "MaxSize":"5",
        "MinSize":"3"
      }
    }
  }
}
```

### YAML
<a name="quickref-autoscaling-example-4.yaml"></a>

```
---
Resources:
  myASG:
    CreationPolicy:
      ResourceSignal:
        Count: '3'
        Timeout: PT15M
    UpdatePolicy:
      AutoScalingRollingUpdate:
        MinInstancesInService: '3'
        MaxBatchSize: '1'
        PauseTime: PT12M5S
        WaitOnResourceSignals: true
        SuspendProcesses:
          - HealthCheck
          - ReplaceUnhealthy
          - AZRebalance
          - AlarmNotification
          - ScheduledActions
          - InstanceRefresh
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      VPCZoneIdentifier:
        - subnetIdAz1
        - subnetIdAz2
        - subnetIdAz3
      LaunchTemplate:
        LaunchTemplateId: !Ref logicalName
        Version: !GetAtt logicalName.LatestVersionNumber
      MaxSize: '5'
      MinSize: '3'
```

## 단계 조정 정책 삭제
<a name="scenario-step-scaling-policy"></a>

이 예에서는 단계 조정 정책을 사용하여 Auto Scaling 그룹을 스케일 아웃하는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-scalingpolicy.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-scalingpolicy.html) 리소스를 보여줍니다. `AdjustmentType` 속성은 `ChangeInCapacity`를 지정합니다. 이는 `ScalingAdjustment`가 추가하거나(`ScalingAdjustment`가 양수인 경우) 삭제할(음수인 경우) 인스턴스 수를 나타낸다는 것을 의미합니다. 이 예에서 `ScalingAdjustment`는 1입니다. 따라서 경보 임계값을 초과하면 그룹의 EC2 인스턴스 수가 1씩 증가합니다.

[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudwatch-alarm.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudwatch-alarm.html) 리소스 `CPUAlarmHigh`는 경보가 ALARM 상태일 때 실행할 작업(`AlarmActions`)으로 조정 정책 `ASGScalingPolicyHigh`를 지정합니다. `Dimensions` 속성은 동일한 템플릿의 다른 곳에서 선언된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html) 리소스의 논리명을 참조합니다.

### JSON
<a name="quickref-autoscaling-example-5.json"></a>

```
 1. {
 2.   "Resources":{
 3.     "ASGScalingPolicyHigh":{
 4.       "Type":"AWS::AutoScaling::ScalingPolicy",
 5.       "Properties":{
 6.         "AutoScalingGroupName":{ "Ref":"logicalName" },
 7.         "PolicyType":"StepScaling",
 8.         "AdjustmentType":"ChangeInCapacity",
 9.         "StepAdjustments":[
10.           {
11.             "MetricIntervalLowerBound":0,
12.             "ScalingAdjustment":1
13.           }
14.         ]
15.       }
16.     },
17.     "CPUAlarmHigh":{
18.       "Type":"AWS::CloudWatch::Alarm",
19.       "Properties":{
20.         "EvaluationPeriods":"2",
21.         "Statistic":"Average",
22.         "Threshold":"90",
23.         "AlarmDescription":"Scale out if CPU > 90% for 2 minutes",
24.         "Period":"60",
25.         "AlarmActions":[ { "Ref":"ASGScalingPolicyHigh" } ],
26.         "Namespace":"AWS/EC2",
27.         "Dimensions":[
28.           {
29.             "Name":"AutoScalingGroupName",
30.             "Value":{ "Ref":"logicalName" }
31.           }
32.         ],
33.         "ComparisonOperator":"GreaterThanThreshold",
34.         "MetricName":"CPUUtilization"
35.       }
36.     }
37.   }
38. }
```

### YAML
<a name="quickref-autoscaling-example-5.yaml"></a>

```
 1. ---
 2. Resources:
 3.   ASGScalingPolicyHigh:
 4.     Type: AWS::AutoScaling::ScalingPolicy
 5.     Properties:
 6.       AutoScalingGroupName: !Ref logicalName
 7.       PolicyType: StepScaling
 8.       AdjustmentType: ChangeInCapacity
 9.       StepAdjustments: 
10.         - MetricIntervalLowerBound: 0
11.           ScalingAdjustment: 1
12.   CPUAlarmHigh:
13.     Type: AWS::CloudWatch::Alarm
14.     Properties:
15.       EvaluationPeriods: 2
16.       Statistic: Average
17.       Threshold: 90
18.       AlarmDescription: 'Scale out if CPU > 90% for 2 minutes'
19.       Period: 60
20.       AlarmActions:
21.         - !Ref ASGScalingPolicyHigh
22.       Namespace: AWS/EC2
23.       Dimensions:
24.         - Name: AutoScalingGroupName
25.           Value:
26.             !Ref logicalName
27.       ComparisonOperator: GreaterThanThreshold
28.       MetricName: CPUUtilization
```

### 다음 사항도 참조하세요.
<a name="scenario-as-policy-see-also"></a>

조정 정책에 대한 추가 예제 템플릿을 알아보려면 `AWS::AutoScaling::ScalingPolicy` 리소스의 [예제](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-scalingpolicy.html#aws-resource-autoscaling-scalingpolicy--examples) 섹션을 참조하세요.

## 혼합 인스턴스 그룹 예제
<a name="scenario-mixed-instances-group-template-examples"></a>

### 속성 기반 인스턴스 유형 선택을 사용하여 Auto Scaling 그룹 생성
<a name="scenario-mixed-instances-group-instance-requirements"></a>

이 예는 속성 기반 인스턴스 유형 선택을 사용하여 혼합 인스턴스 그룹을 시작하기 위한 정보를 포함하는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html) 리소스를 보여줍니다. `VCpuCount` 속성의 최솟값과 최댓값을 지정하고 `MemoryMiB` 속성의 최솟값을 지정합니다. auto scaling에서 사용하는 모든 인스턴스 유형은 필요한 인스턴스 속성과 일치해야 합니다.

auto scaling의 `VPCZoneIdentifier` 속성은 3개의 서로 다른 가용 영역에 있는 기존 서브넷 목록을 지정합니다. 스택을 만들기 전에 계정에서 적용 가능한 서브넷 ID를 지정해야 합니다. `LaunchTemplate` 속성은 동일한 템플릿의 다른 곳에서 선언된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html) 리소스의 논리명을 참조합니다.

#### JSON
<a name="quickref-mixed-instances-group-example-2.json"></a>

```
 1. {
 2.   "Resources":{
 3.     "myASG":{
 4.       "Type":"AWS::AutoScaling::AutoScalingGroup",
 5.       "Properties":{
 6.         "VPCZoneIdentifier":[
 7.           "subnetIdAz1",
 8.           "subnetIdAz2",
 9.           "subnetIdAz3"
10.         ],
11.         "MixedInstancesPolicy":{
12.           "LaunchTemplate":{
13.             "LaunchTemplateSpecification":{
14.               "LaunchTemplateId":{
15.                 "Ref":"logicalName"
16.               },
17.               "Version":{
18.                 "Fn::GetAtt":[
19.                   "logicalName",
20.                   "LatestVersionNumber"
21.                 ]
22.               }
23.             },
24.             "Overrides":[
25.               {
26.                 "InstanceRequirements":{
27.                   "VCpuCount":{
28.                     "Min":2,
29.                     "Max":4
30.                   },
31.                   "MemoryMiB":{
32.                     "Min":2048
33.                   }
34.                 }
35.               }
36.             ]
37.           }
38.         },
39.         "MaxSize":"5",
40.         "MinSize":"1"
41.       }
42.     }
43.   }
44. }
```

#### YAML
<a name="quickref-mixed-instances-group-example-1.yaml"></a>

```
 1. ---
 2. Resources:
 3.   myASG:
 4.     Type: AWS::AutoScaling::AutoScalingGroup
 5.     Properties:
 6.       VPCZoneIdentifier:
 7.         - subnetIdAz1
 8.         - subnetIdAz2
 9.         - subnetIdAz3
10.       MixedInstancesPolicy:
11.         LaunchTemplate:
12.           LaunchTemplateSpecification:
13.             LaunchTemplateId: !Ref logicalName
14.             Version: !GetAtt logicalName.LatestVersionNumber
15.           Overrides:
16.             - InstanceRequirements:
17.                 VCpuCount:
18.                   Min: 2
19.                   Max: 4
20.                 MemoryMiB:
21.                   Min: 2048
22.       MaxSize: '5'
23.       MinSize: '1'
```

## 시작 구성 예제
<a name="scenario-launch-config-template-examples"></a>

### 시작 구성 생성
<a name="scenario-as-launch-config"></a>

이 예에서는 `ImageId`, `InstanceType`, `SecurityGroups` 속성에 대한 값을 지정하는 Auto Scaling 그룹에 대한 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-launchconfiguration.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-launchconfiguration.html) 리소스를 보여줍니다. `SecurityGroups` 속성은 템플릿에 지정된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) 리소스의 논리명과 `myExistingEC2SecurityGroup`이라는 기존 EC2 보안 그룹을 모두 지정합니다.

#### JSON
<a name="quickref-launch-config-example-1.json"></a>

```
1. "mySimpleConfig" : {
2.    "Type" : "AWS::AutoScaling::LaunchConfiguration",
3.    "Properties" : {
4.       "ImageId" : "ami-02354e95b3example",
5.       "InstanceType" : "t3.micro",
6.       "SecurityGroups" : [ { "Ref" : "logicalName" }, "myExistingEC2SecurityGroup" ]
7.    }
8. }
```

#### YAML
<a name="quickref-launch-config-example-1.yaml"></a>

```
1. mySimpleConfig:
2.   Type: AWS::AutoScaling::LaunchConfiguration
3.   Properties:
4.     ImageId: ami-02354e95b3example
5.     InstanceType: t3.micro
6.     SecurityGroups:
7.       - !Ref logicalName
8.       - myExistingEC2SecurityGroup
```

### 시작 구성을 사용하는 Auto Scaling 그룹 생성
<a name="scenario-single-instance-as-group-launch-configuration"></a>

이 예에서는 단일 인스턴스가 있는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html) 리소스를 보여줍니다. auto scaling의 `VPCZoneIdentifier` 속성은 3개의 서로 다른 가용 영역에 있는 기존 서브넷 목록을 지정합니다. 스택을 만들기 전에 계정에서 적용 가능한 서브넷 ID를 지정해야 합니다. `LaunchConfigurationName` 속성은 템플릿에 정의된 논리명이 `mySimpleConfig`인 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-launchconfiguration.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-launchconfiguration.html) 리소스를 참조합니다.

#### JSON
<a name="quickref-launch-config-example-2.json"></a>

```
1. "myASG" : {
2.    "Type" : "AWS::AutoScaling::AutoScalingGroup",
3.    "Properties" : {
4.       "VPCZoneIdentifier" : [ "subnetIdAz1", "subnetIdAz2", "subnetIdAz3" ],
5.       "LaunchConfigurationName" : { "Ref" : "mySimpleConfig" },
6.       "MaxSize" : "1",
7.       "MinSize" : "1"
8.    }
9. }
```

#### YAML
<a name="quickref-launch-config-example-2.yaml"></a>

```
 1. myASG:
 2.   Type: AWS::AutoScaling::AutoScalingGroup
 3.   Properties:
 4.     VPCZoneIdentifier:
 5.       - subnetIdAz1
 6.       - subnetIdAz2
 7.       - subnetIdAz3
 8.     LaunchConfigurationName: !Ref mySimpleConfig
 9.     MaxSize: '1'
10.     MinSize: '1'
```

# CloudFormation을 사용한 Application Auto Scaling 리소스 구성
<a name="quickref-application-auto-scaling"></a>

이 섹션에서는 다양한 AWS 리소스의 Application Auto Scaling 조정 정책 및 예약된 작업에 대한 CloudFormation 템플릿 예제를 보여줍니다.

**중요**  
Application Auto Scaling 코드 조각이 템플릿에 포함된 경우 템플릿을 통해 생성되는 조정 가능 리소스에 대해 `DependsOn` 속성을 사용하여 종속성을 선언해야 할 수 있습니다. 그러면 기본 병렬 처리가 재정의되고 CloudFormation이 지정된 순서로 리소스에서 작동합니다. 이렇게 하지 않으면 리소스가 완전히 설정되기 전에 조정 구성이 적용될 수 있습니다.  
자세한 내용은 [DependsOn 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-dependson.html)을 참조하세요.

**Topics**
+ [AppStream 플릿에 대한 조정 정책 생성](#w2aac11c41c15c19b9)
+ [Aurora DB 클러스터에 대한 조정 정책 생성](#w2aac11c41c15c19c11)
+ [DynamoDB 테이블에 대한 조정 정책 생성](#w2aac11c41c15c19c13)
+ [Amazon ECS 서비스에 대한 조정 정책 생성(지표: 평균 CPU 및 메모리)](#w2aac11c41c15c19c15)
+ [Amazon ECS 서비스에 대한 조정 정책 생성(지표: 대상당 평균 요청 수)](#w2aac11c41c15c19c17)
+ [Lambda 함수에 대해 cron 표현식을 사용하는 예약된 작업 생성](#w2aac11c41c15c19c19)
+ [스팟 플릿에 대해 `at` 표현식을 사용하는 예약된 작업 생성](#w2aac11c41c15c19c21)

## AppStream 플릿에 대한 조정 정책 생성
<a name="w2aac11c41c15c19b9"></a>

이 코드 조각은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalingpolicy.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalingpolicy.html) 리소스를 사용하여 정책을 생성하고 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-appstream-fleet.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-appstream-fleet.html) 리소스에 적용하는 방법을 보여줍니다. [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html) 리소스는 해당 정책이 적용되는 조정 가능 대상을 선언합니다. Application Auto Scaling에서는 플릿 인스턴스의 수를 최소 1개와 최대 20개 사이에서 조정할 수 있습니다. 이 정책은 300초(5분)의 스케일 아웃 및 스케일 인 휴지 기간과 함께 플릿의 평균 용량 사용률을 75%로 유지합니다.

`Fn::Join` 및 `Rev` 내장 함수를 사용하여 동일한 템플릿에 지정된 `AWS::AppStream::Fleet` 리소스의 논리명으로 `ResourceId` 속성을 구성합니다. 자세한 내용은 [내장 함수 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference.html)를 참조하세요.

### JSON
<a name="quickref-autoscaling-example-6.json"></a>

```
{
  "Resources" : {
    "ScalableTarget" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalableTarget",
      "Properties" : {
        "MaxCapacity" : 20,
        "MinCapacity" : 1,
        "RoleARN" : { "Fn::Sub" : "arn:aws:iam::${AWS::AccountId}:role/aws-service-role/appstream.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_AppStreamFleet" },
        "ServiceNamespace" : "appstream",
        "ScalableDimension" : "appstream:fleet:DesiredCapacity",
        "ResourceId" : {
          "Fn::Join" : [
            "/",
            [
              "fleet",
              {
                "Ref" : "logicalName"
              }
            ]
          ]
        }
      }
    },
    "ScalingPolicyAppStreamFleet" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalingPolicy",
      "Properties" : {
        "PolicyName" : { "Fn::Sub" : "${AWS::StackName}-target-tracking-cpu75" },
        "PolicyType" : "TargetTrackingScaling",
        "ServiceNamespace" : "appstream",
        "ScalableDimension" : "appstream:fleet:DesiredCapacity",
        "ResourceId" : {
          "Fn::Join" : [
            "/",
            [
              "fleet",
              {
                "Ref" : "logicalName"
              }
            ]
          ]
        },
        "TargetTrackingScalingPolicyConfiguration" : {
          "TargetValue" : 75,
          "PredefinedMetricSpecification" : {
            "PredefinedMetricType" : "AppStreamAverageCapacityUtilization"
          },
          "ScaleInCooldown" : 300,
          "ScaleOutCooldown" : 300
        }
      }
    } 
  }
}
```

### YAML
<a name="quickref-autoscaling-example-6.yaml"></a>

```
---
Resources:
  ScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MaxCapacity: 20
      MinCapacity: 1
      RoleARN: 
        Fn::Sub: 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/appstream.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_AppStreamFleet'
      ServiceNamespace: appstream
      ScalableDimension: appstream:fleet:DesiredCapacity
      ResourceId: !Join
        - /
        - - fleet
          - !Ref logicalName
  ScalingPolicyAppStreamFleet:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub ${AWS::StackName}-target-tracking-cpu75
      PolicyType: TargetTrackingScaling
      ServiceNamespace: appstream
      ScalableDimension: appstream:fleet:DesiredCapacity
      ResourceId: !Join
        - /
        - - fleet
          - !Ref logicalName
      TargetTrackingScalingPolicyConfiguration:
        TargetValue: 75
        PredefinedMetricSpecification:
          PredefinedMetricType: AppStreamAverageCapacityUtilization
        ScaleInCooldown: 300
        ScaleOutCooldown: 300
```

## Aurora DB 클러스터에 대한 조정 정책 생성
<a name="w2aac11c41c15c19c11"></a>

이 코드 조각에서는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbcluster.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbcluster.html) 리소스를 등록합니다. [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html) 리소스는 DB 클러스터가 1개에서 8개까지 Aurora 복제본을 보유하도록 동적으로 조정되어야 함을 나타냅니다. 또한 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalingpolicy.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalingpolicy.html) 리소스를 사용하여 클러스터에 대상 추적 조정 정책을 적용합니다.

이 구성에서 `RDSReaderAverageCPUUtilization` 사전 정의 지표는 해당 Aurora DB 클러스터에 있는 모든 Aurora 복제본에 대해 평균 CPU 사용률 40%를 기반으로 Aurora DB 클러스터를 조정합니다. 구성에서는 스케일 인 휴지 기간 10분과 스케일 아웃 휴지 기간 5분을 제공합니다.

이 예에서는 `Fn::Sub` 내장 함수를 사용하여 동일한 템플릿에 지정된 `AWS::RDS::DBCluster` 리소스의 논리명으로 `ResourceId` 속성을 구성합니다. 자세한 내용은 [내장 함수 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference.html)를 참조하세요.

### JSON
<a name="quickref-autoscaling-example-7.json"></a>

```
{
  "Resources" : {
    "ScalableTarget" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalableTarget",
      "Properties" : {
        "MaxCapacity" : 8,
        "MinCapacity" : 1,
        "RoleARN" : { "Fn::Sub" : "arn:aws:iam::${AWS::AccountId}:role/aws-service-role/rds.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_RDSCluster" },
        "ServiceNamespace" : "rds",
        "ScalableDimension" : "rds:cluster:ReadReplicaCount",
        "ResourceId" : { "Fn::Sub" : "cluster:${logicalName}" }
      }
    },
    "ScalingPolicyDBCluster" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalingPolicy",
      "Properties" : {
        "PolicyName" : { "Fn::Sub" : "${AWS::StackName}-target-tracking-cpu40" },
        "PolicyType" : "TargetTrackingScaling",
        "ServiceNamespace" : "rds",
        "ScalableDimension" : "rds:cluster:ReadReplicaCount",
        "ResourceId" : { "Fn::Sub" : "cluster:${logicalName}" }, 
        "TargetTrackingScalingPolicyConfiguration" : {
          "TargetValue" : 40,
          "PredefinedMetricSpecification" : {
            "PredefinedMetricType" : "RDSReaderAverageCPUUtilization"
          },
          "ScaleInCooldown" : 600,
          "ScaleOutCooldown" : 300
        }
      }
    }
  }
}
```

### YAML
<a name="quickref-autoscaling-example-7.yaml"></a>

```
---
Resources:
  ScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MaxCapacity: 8
      MinCapacity: 1
      RoleARN: 
        Fn::Sub: 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/rds.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_RDSCluster'
      ServiceNamespace: rds
      ScalableDimension: rds:cluster:ReadReplicaCount
      ResourceId: !Sub cluster:${logicalName}
  ScalingPolicyDBCluster:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub ${AWS::StackName}-target-tracking-cpu40
      PolicyType: TargetTrackingScaling
      ServiceNamespace: rds
      ScalableDimension: rds:cluster:ReadReplicaCount
      ResourceId: !Sub cluster:${logicalName}
      TargetTrackingScalingPolicyConfiguration:
        TargetValue: 40
        PredefinedMetricSpecification:
          PredefinedMetricType: RDSReaderAverageCPUUtilization
        ScaleInCooldown: 600
        ScaleOutCooldown: 300
```

## DynamoDB 테이블에 대한 조정 정책 생성
<a name="w2aac11c41c15c19c13"></a>

이 코드 조각은 `TargetTrackingScaling` 정책 유형으로 정책을 생성하고 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalingpolicy.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalingpolicy.html) 리소스를 사용하는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-dynamodb-table.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-dynamodb-table.html) 리소스에 적용하는 방법을 보여줍니다. [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html) 리소스는 최소 5개 및 최대 15개의 쓰기 용량 단위로 이 정책이 적용되는 조정 가능 대상을 선언합니다. 조정 정책은 테이블의 쓰기 용량 처리량을 조정하여 `DynamoDBWriteCapacityUtilization` 사전 정의 지표에 따라 대상 사용률을 50%로 유지합니다.

`Fn::Join` 및 `Ref` 내장 함수를 사용하여 동일한 템플릿에 지정된 `AWS::DynamoDB::Table` 리소스의 논리명으로 `ResourceId` 속성을 구성합니다. 자세한 내용은 [내장 함수 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference.html)를 참조하세요.

**참고**  
DynamoDB 리소스용 CloudFormation 템플릿을 생성하는 방법에 대한 자세한 내용을 알아보려면 AWS Database 블로그의 [How to use CloudFormation to configure auto scaling for Amazon DynamoDB tables and indexes](https://aws.amazon.com/blogs/database/how-to-use-aws-cloudformation-to-configure-auto-scaling-for-amazon-dynamodb-tables-and-indexes/) 게시물을 참조하세요.

### JSON
<a name="quickref-autoscaling-example-8.json"></a>

```
{
  "Resources" : {
    "WriteCapacityScalableTarget" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalableTarget",
      "Properties" : {
        "MaxCapacity" : 15,
        "MinCapacity" : 5,
        "RoleARN" : { "Fn::Sub" : "arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable" },
        "ServiceNamespace" : "dynamodb",
        "ScalableDimension" : "dynamodb:table:WriteCapacityUnits",
        "ResourceId" : {
          "Fn::Join" : [
            "/",
            [
              "table",
              {
                "Ref" : "logicalName"
              }
            ]
          ]
        }
      }
    },
    "WriteScalingPolicy" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalingPolicy",
      "Properties" : {
        "PolicyName" : "WriteScalingPolicy",
        "PolicyType" : "TargetTrackingScaling",
        "ScalingTargetId" : { "Ref" : "WriteCapacityScalableTarget" },
        "TargetTrackingScalingPolicyConfiguration" : {
          "TargetValue" : 50.0,
          "ScaleInCooldown" : 60,
          "ScaleOutCooldown" : 60,
          "PredefinedMetricSpecification" : {
            "PredefinedMetricType" : "DynamoDBWriteCapacityUtilization"
          }
        }
      }
    }
  }
}
```

### YAML
<a name="quickref-autoscaling-example-8.yaml"></a>

```
---
Resources:
  WriteCapacityScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MaxCapacity: 15
      MinCapacity: 5
      RoleARN: 
        Fn::Sub: 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable'
      ServiceNamespace: dynamodb
      ScalableDimension: dynamodb:table:WriteCapacityUnits
      ResourceId: !Join
        - /
        - - table
          - !Ref logicalName
  WriteScalingPolicy:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: WriteScalingPolicy
      PolicyType: TargetTrackingScaling
      ScalingTargetId: !Ref WriteCapacityScalableTarget
      TargetTrackingScalingPolicyConfiguration:
        TargetValue: 50.0
        ScaleInCooldown: 60
        ScaleOutCooldown: 60
        PredefinedMetricSpecification:
          PredefinedMetricType: DynamoDBWriteCapacityUtilization
```

## Amazon ECS 서비스에 대한 조정 정책 생성(지표: 평균 CPU 및 메모리)
<a name="w2aac11c41c15c19c15"></a>

이 코드 조각은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalingpolicy.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalingpolicy.html) 리소스를 사용하여 정책을 생성하고 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-service.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-service.html) 리소스에 적용하는 방법을 보여줍니다. [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html) 리소스는 해당 정책이 적용되는 조정 가능 대상을 선언합니다. Application Auto Scaling에서는 작업 수를 최소 1개와 최대 6개 사이에서 조정할 수 있습니다.

이는 `TargetTrackingScaling` 정책 유형을 사용하여 두 개의 조정 정책을 만듭니다. 이 정책은 서비스의 평균 CPU 및 메모리 사용량을 기준으로 ECS 서비스를 확장하는 데 사용됩니다. `Fn::Join` 및 `Ref` 내장 함수를 사용하여 동일한 템플릿에 지정된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-cluster.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ecs-cluster.html)(`myContainerCluster`) 및 `AWS::ECS::Service`(`myService`) 리소스의 논리명으로 `ResourceId` 속성을 구성합니다. 자세한 내용은 [내장 함수 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference.html)를 참조하세요.

### JSON
<a name="quickref-autoscaling-example-9.json"></a>

```
{
  "Resources" : {
    "ECSScalableTarget" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalableTarget",
      "Properties" : {
        "MaxCapacity" : "6",
        "MinCapacity" : "1",
        "RoleARN" : { "Fn::Sub" : "arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService" },
        "ServiceNamespace" : "ecs",
        "ScalableDimension" : "ecs:service:DesiredCount",
        "ResourceId" : {
          "Fn::Join" : [
            "/",
            [
              "service",
              {
                "Ref" : "myContainerCluster"
              },
              {
                "Fn::GetAtt" : [
                  "myService",
                  "Name"
                ]
              }
            ]
          ]
        }
      }
    },
    "ServiceScalingPolicyCPU" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalingPolicy",
      "Properties" : {
        "PolicyName" : { "Fn::Sub" : "${AWS::StackName}-target-tracking-cpu70" },
        "PolicyType" : "TargetTrackingScaling",
        "ScalingTargetId" : { "Ref" : "ECSScalableTarget" },
        "TargetTrackingScalingPolicyConfiguration" : {
          "TargetValue" : 70.0,
          "ScaleInCooldown" : 180,
          "ScaleOutCooldown" : 60,
          "PredefinedMetricSpecification" : {
            "PredefinedMetricType" : "ECSServiceAverageCPUUtilization"
          }
        }
      }
    },
    "ServiceScalingPolicyMem" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalingPolicy",
      "Properties" : {
        "PolicyName" : { "Fn::Sub" : "${AWS::StackName}-target-tracking-mem90" },
        "PolicyType" : "TargetTrackingScaling",
        "ScalingTargetId" : { "Ref" : "ECSScalableTarget" },
        "TargetTrackingScalingPolicyConfiguration" : {
          "TargetValue" : 90.0,
          "ScaleInCooldown" : 180,
          "ScaleOutCooldown" : 60,
          "PredefinedMetricSpecification" : {
            "PredefinedMetricType" : "ECSServiceAverageMemoryUtilization"
          }
        }
      }
    }
  }
}
```

### YAML
<a name="quickref-autoscaling-example-9.yaml"></a>

```
---
Resources:
  ECSScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MaxCapacity: 6
      MinCapacity: 1  
      RoleARN: 
        Fn::Sub: 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService'
      ServiceNamespace: ecs
      ScalableDimension: 'ecs:service:DesiredCount'
      ResourceId: !Join 
        - /
        - - service
          - !Ref myContainerCluster
          - !GetAtt myService.Name
  ServiceScalingPolicyCPU:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub ${AWS::StackName}-target-tracking-cpu70
      PolicyType: TargetTrackingScaling
      ScalingTargetId: !Ref ECSScalableTarget
      TargetTrackingScalingPolicyConfiguration:
        TargetValue: 70.0
        ScaleInCooldown: 180
        ScaleOutCooldown: 60
        PredefinedMetricSpecification:
          PredefinedMetricType: ECSServiceAverageCPUUtilization
  ServiceScalingPolicyMem:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: !Sub ${AWS::StackName}-target-tracking-mem90
      PolicyType: TargetTrackingScaling
      ScalingTargetId: !Ref ECSScalableTarget
      TargetTrackingScalingPolicyConfiguration:
        TargetValue: 90.0
        ScaleInCooldown: 180
        ScaleOutCooldown: 60
        PredefinedMetricSpecification:
          PredefinedMetricType: ECSServiceAverageMemoryUtilization
```

## Amazon ECS 서비스에 대한 조정 정책 생성(지표: 대상당 평균 요청 수)
<a name="w2aac11c41c15c19c17"></a>

다음 예에서는 `ALBRequestCountPerTarget` 사전 정의 지표가 있는 대상 추적 조정 정책을 ECS 서비스에 적용합니다. 이 정책은 분당 대상당 요청 수가 목표 값을 초과하는 경우 ECS 서비스에 용량을 추가하는 데 사용됩니다. `DisableScaleIn`의 값이 `true`로 설정되어 있기 때문에 대상 추적 정책은 확장 가능한 대상에서 용량을 제거하지 않습니다.

`Fn::Join` 및 `Fn::GetAtt` 내장 함수를 사용하여 동일한 템플릿에 지정된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-loadbalancer.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-loadbalancer.html)(`myLoadBalancer`) 및 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancingv2-targetgroup.html)(`myTargetGroup`) 리소스의 논리명으로 `ResourceLabel` 속성을 구성합니다. 자세한 내용은 [내장 함수 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference.html)를 참조하세요.

확장 가능한 대상의 `MaxCapacity` 및 `MinCapacity` 속성과 확장 정책의 `TargetValue` 속성은 스택을 만들거나 업데이트할 때 템플릿에 전달하는 파라미터 값을 참조합니다.

### JSON
<a name="quickref-autoscaling-example-10.json"></a>

```
{
  "Resources" : {
    "ECSScalableTarget" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalableTarget",
      "Properties" : {
        "MaxCapacity" : { "Ref" : "MaxCount" },
        "MinCapacity" : { "Ref" : "MinCount" },
        "RoleARN" : { "Fn::Sub" : "arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService" },
        "ServiceNamespace" : "ecs",
        "ScalableDimension" : "ecs:service:DesiredCount",
        "ResourceId" : {
          "Fn::Join" : [
            "/",
            [
              "service",
              {
                "Ref" : "myContainerCluster"
              },
              {
                "Fn::GetAtt" : [
                  "myService",
                  "Name"
                ]
              }
            ]
          ]
        }
      }
    },
    "ServiceScalingPolicyALB" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalingPolicy",
      "Properties" : {
        "PolicyName" : "alb-requests-per-target-per-minute",
        "PolicyType" : "TargetTrackingScaling",
        "ScalingTargetId" : { "Ref" : "ECSScalableTarget" },
        "TargetTrackingScalingPolicyConfiguration" : {
          "TargetValue" : { "Ref" : "ALBPolicyTargetValue" },
          "ScaleInCooldown" : 180,
          "ScaleOutCooldown" : 30,
          "DisableScaleIn" : true,
          "PredefinedMetricSpecification" : {
            "PredefinedMetricType" : "ALBRequestCountPerTarget",
            "ResourceLabel" : {
              "Fn::Join" : [
                "/",
                [
                  {
                    "Fn::GetAtt" : [
                      "myLoadBalancer",
                      "LoadBalancerFullName"
                    ]
                  },
                  {
                    "Fn::GetAtt" : [
                      "myTargetGroup",
                      "TargetGroupFullName"
                    ]
                  }
                ]
              ]
            }
          }
        }
      }
    }
  }
}
```

### YAML
<a name="quickref-autoscaling-example-10.yaml"></a>

```
---
Resources:
  ECSScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MaxCapacity: !Ref MaxCount
      MinCapacity: !Ref MinCount  
      RoleARN: 
        Fn::Sub: 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService'
      ServiceNamespace: ecs
      ScalableDimension: 'ecs:service:DesiredCount'
      ResourceId: !Join 
        - /
        - - service
          - !Ref myContainerCluster
          - !GetAtt myService.Name
  ServiceScalingPolicyALB:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: alb-requests-per-target-per-minute
      PolicyType: TargetTrackingScaling
      ScalingTargetId: !Ref ECSScalableTarget
      TargetTrackingScalingPolicyConfiguration:
        TargetValue: !Ref ALBPolicyTargetValue
        ScaleInCooldown: 180
        ScaleOutCooldown: 30
        DisableScaleIn: true
        PredefinedMetricSpecification:
          PredefinedMetricType: ALBRequestCountPerTarget
          ResourceLabel: !Join 
            - '/' 
            - - !GetAtt myLoadBalancer.LoadBalancerFullName
              - !GetAtt myTargetGroup.TargetGroupFullName
```

## Lambda 함수에 대해 cron 표현식을 사용하는 예약된 작업 생성
<a name="w2aac11c41c15c19c19"></a>

이 코드 조각은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html) 리소스를 사용하여 `BLUE`라는 함수 별칭([https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-alias.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-alias.html))에 대해 프로비저닝된 동시성을 등록합니다. 또한 Cron 식을 사용하여 반복 일정으로 예약 작업을 만듭니다. 반복 일정의 시간대는 UTC입니다.

`RoleARN` 속성의 `Fn::Join` 및 `Ref` 내장 함수를 사용하여 서비스 연결 역할의 ARN을 지정합니다. `Fn::Sub` 내장 함수를 사용하여 동일한 템플릿에 지정된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html) 또는 [https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) 리소스의 논리명으로 `ResourceId` 속성을 구성합니다. 자세한 내용은 [내장 함수 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference.html)를 참조하세요.

**참고**  
게시되지 않은 버전(`$LATEST`)을 가리키는 별칭에는 프로비저닝된 동시성을 할당할 수 없습니다.  
Lambda 리소스에 대한 CloudFormation 템플릿을 생성하는 방법에 대한 자세한 내용을 알아보려면 AWS Compute 블로그의 [Scheduling AWS Lambda Provisioned Concurrency for recurring peak usage](https://aws.amazon.com/blogs/compute/scheduling-aws-lambda-provisioned-concurrency-for-recurring-peak-usage/) 게시물을 참조하세요.

### JSON
<a name="quickref-autoscaling-example-11.json"></a>

```
{
  "ScalableTarget" : {
    "Type" : "AWS::ApplicationAutoScaling::ScalableTarget",
    "Properties" : {
      "MaxCapacity" : 250,
      "MinCapacity" : 0,
      "RoleARN" : {
        "Fn::Join" : [
          ":",
          [
            "arn:aws:iam:",
            {
              "Ref" : "AWS::AccountId"
            },
            "role/aws-service-role/lambda.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_LambdaConcurrency"
          ]
        ]
      },
      "ServiceNamespace" : "lambda",
      "ScalableDimension" : "lambda:function:ProvisionedConcurrency",
      "ResourceId" : { "Fn::Sub" : "function:${logicalName}:BLUE" },
      "ScheduledActions" : [
        {
          "ScalableTargetAction" : {
            "MinCapacity" : "250"
          },
          "ScheduledActionName" : "my-scale-out-scheduled-action",
          "Schedule" : "cron(0 18 * * ? *)",
          "EndTime" : "2022-12-31T12:00:00.000Z"
        }
      ]
    }
  }
}
```

### YAML
<a name="quickref-autoscaling-example-11.yaml"></a>

```
ScalableTarget:
  Type: AWS::ApplicationAutoScaling::ScalableTarget
  Properties:
    MaxCapacity: 250
    MinCapacity: 0
    RoleARN: !Join 
      - ':'
      - - 'arn:aws:iam:'
        - !Ref 'AWS::AccountId'
        - role/aws-service-role/lambda.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_LambdaConcurrency
    ServiceNamespace: lambda
    ScalableDimension: lambda:function:ProvisionedConcurrency
    ResourceId: !Sub function:${logicalName}:BLUE
    ScheduledActions:
      - ScalableTargetAction:
          MinCapacity: 250
        ScheduledActionName: my-scale-out-scheduled-action
        Schedule: 'cron(0 18 * * ? *)'
        EndTime: '2022-12-31T12:00:00.000Z'
```

## 스팟 플릿에 대해 `at` 표현식을 사용하는 예약된 작업 생성
<a name="w2aac11c41c15c19c21"></a>

이 코드 조각은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-applicationautoscaling-scalabletarget.html) 리소스를 사용하여 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-spotfleet.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-spotfleet.html) 리소스에 대해 한 번만 발생하는 두 개의 예약된 작업을 생성하는 방법을 보여 줍니다. 각 일회성 예약된 작업의 시간대는 UTC입니다.

`Fn::Join` 및 `Ref` 내장 함수를 통해 동일한 템플릿에 지정된 `AWS::EC2::SpotFleet` 리소스의 논리명으로 `ResourceId` 속성을 구성합니다. 자세한 내용은 [내장 함수 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference.html)를 참조하세요.

**참고**  
스팟 플릿 요청에는 `maintain` 유형의 요청이 있어야 합니다. 1회 요청 또는 스팟 블록에는 자동 조정이 지원되지 않습니다.

### JSON
<a name="quickref-autoscaling-example-12.json"></a>

```
{
  "Resources" : {
    "SpotFleetScalableTarget" : {
      "Type" : "AWS::ApplicationAutoScaling::ScalableTarget",
      "Properties" : {
        "MaxCapacity" : 0,
        "MinCapacity" : 0,
        "RoleARN" : { "Fn::Sub" : "arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ec2.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_EC2SpotFleetRequest" },
        "ServiceNamespace" : "ec2",
        "ScalableDimension" : "ec2:spot-fleet-request:TargetCapacity",
        "ResourceId" : {
          "Fn::Join" : [
            "/",
            [
              "spot-fleet-request",
              {
                "Ref" : "logicalName"
              }
            ]
          ]
        },
        "ScheduledActions" : [
          {
            "ScalableTargetAction" : {
              "MaxCapacity" : "10",
              "MinCapacity" : "10"
            },
            "ScheduledActionName" : "my-scale-out-scheduled-action",
            "Schedule" : "at(2022-05-20T13:00:00)"
          },
          {
            "ScalableTargetAction" : {
              "MaxCapacity" : "0",
              "MinCapacity" : "0"
            },
            "ScheduledActionName" : "my-scale-in-scheduled-action",
            "Schedule" : "at(2022-05-20T21:00:00)"
          }
        ]
      }
    }
  }
}
```

### YAML
<a name="quickref-autoscaling-example-12.yaml"></a>

```
---
Resources:
  SpotFleetScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MaxCapacity: 0
      MinCapacity: 0
      RoleARN: 
        Fn::Sub: 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/ec2.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_EC2SpotFleetRequest'
      ServiceNamespace: ec2
      ScalableDimension: 'ec2:spot-fleet-request:TargetCapacity'
      ResourceId: !Join 
        - /
        - - spot-fleet-request
          - !Ref logicalName
      ScheduledActions:
        - ScalableTargetAction:
            MaxCapacity: 10
            MinCapacity: 10
          ScheduledActionName: my-scale-out-scheduled-action
          Schedule: 'at(2022-05-20T13:00:00)'
        - ScalableTargetAction:
            MaxCapacity: 0
            MinCapacity: 0
          ScheduledActionName: my-scale-in-scheduled-action
          Schedule: 'at(2022-05-20T21:00:00)'
```

# AWS 빌링 콘솔 템플릿 코드 조각
<a name="quickref-billingconductor"></a>

이 예제에서는 10% 글로벌 마크업 요금 규칙을 사용하여 하나의 요금제를 생성합니다. 이 요금제는 과금 그룹에 연결되어 있습니다. 과금 그룹에는 과금 그룹 총 비용에 10 USD 청구와 10% 청구를 추가로 적용하는 2개의 사용자 지정 항목도 있습니다.

## JSON
<a name="quickref-billingconductor-example-1.json"></a>

```
 1. {
 2.    "Parameters": {
 3.       "LinkedAccountIds": {
 4.          "Type": "ListNumber"
 5.       },
 6.       "PrimaryAccountId": {
 7.          "Type": "Number"
 8.       }
 9.    },
10.    "Resources": {
11.       "TestPricingRule": {
12.          "Type": "AWS::BillingConductor::PricingRule",
13.          "Properties": {
14.             "Name": "TestPricingRule",
15.             "Description": "Test pricing rule created through Cloudformation. Mark everything by 10%.",
16.             "Type": "MARKUP",
17.             "Scope": "GLOBAL",
18.             "ModifierPercentage": 10
19.          }
20.       },
21.       "TestPricingPlan": {
22.          "Type": "AWS::BillingConductor::PricingPlan",
23.          "Properties": {
24.             "Name": "TestPricingPlan",
25.             "Description": "Test pricing plan created through Cloudformation.",
26.             "PricingRuleArns": [
27.                {"Fn::GetAtt": ["TestPricingRule", "Arn"]}
28.             ]
29.          }
30.       },
31.       "TestBillingGroup": {
32.          "Type": "AWS::BillingConductor::BillingGroup",
33.          "Properties": {
34.             "Name": "TestBillingGroup",
35.             "Description": "Test billing group created through Cloudformation with 1 linked account. The linked account is also the primary account.",
36.             "PrimaryAccountId": {
37.                "Ref": "PrimaryAccountId"
38.             },
39.             "AccountGrouping": {
40.                "LinkedAccountIds": null
41.             },
42.             "ComputationPreference": {
43.                "PricingPlanArn": {
44.                  "Fn::GetAtt": ["TestPricingPlan", "Arn"]
45.                }
46.             }
47.          }
48.       },
49.       "TestFlatCustomLineItem": {
50.          "Type": "AWS::BillingConductor::CustomLineItem",
51.          "Properties": {
52.             "Name": "TestFlatCustomLineItem",
53.             "Description": "Test flat custom line item created through Cloudformation for a $10 charge.",
54.             "BillingGroupArn": {
55.               "Fn::GetAtt": ["TestBillingGroup", "Arn"]
56.             },
57.             "CustomLineItemChargeDetails": {
58.                "Flat": {
59.                   "ChargeValue": 10
60.                },
61.                "Type": "FEE"
62.             }
63.          }
64.       },
65.       "TestPercentageCustomLineItem": {
66.          "Type": "AWS::BillingConductor::CustomLineItem",
67.          "Properties": {
68.             "Name": "TestPercentageCustomLineItem",
69.             "Description": "Test percentage custom line item created through Cloudformation for a %10 additional charge on the overall total bill of the billing group.",
70.             "BillingGroupArn": {
71.               "Fn::GetAtt": ["TestBillingGroup", "Arn"]
72.             },
73.             "CustomLineItemChargeDetails": {
74.                "Percentage": {
75.                   "PercentageValue": 10,
76.                   "ChildAssociatedResources": [
77.                      {"Fn::GetAtt": ["TestBillingGroup", "Arn"]}
78.                   ]
79.                },
80.                "Type": "FEE"
81.             }
82.          }
83.       }
84.    }
85. }
```

## YAML
<a name="quickref-billingconductor-example-1.yaml"></a>

```
 1. Parameters:
 2.   LinkedAccountIds:
 3.     Type: ListNumber
 4.   PrimaryAccountId:
 5.     Type: Number
 6. Resources:
 7.   TestPricingRule:
 8.     Type: AWS::BillingConductor::PricingRule
 9.     Properties:
10.       Name: 'TestPricingRule'
11.       Description: 'Test pricing rule created through Cloudformation. Mark everything by 10%.'
12.       Type: 'MARKUP'
13.       Scope: 'GLOBAL'
14.       ModifierPercentage: 10
15.   TestPricingPlan:
16.     Type: AWS::BillingConductor::PricingPlan
17.     Properties:
18.       Name: 'TestPricingPlan'
19.       Description: 'Test pricing plan created through Cloudformation.'
20.       PricingRuleArns:
21.         - !GetAtt TestPricingRule.Arn
22.   TestBillingGroup:
23.     Type: AWS::BillingConductor::BillingGroup
24.     Properties:
25.       Name: 'TestBillingGroup'
26.       Description: 'Test billing group created through Cloudformation with 1 linked account. The linked account is also the primary account.'
27.       PrimaryAccountId: !Ref PrimaryAccountId
28.       AccountGrouping:
29.         LinkedAccountIds: !Ref LinkedAccountIds
30.       ComputationPreference:
31.         PricingPlanArn: !GetAtt TestPricingPlan.Arn
32.   TestFlatCustomLineItem:
33.     Type: AWS::BillingConductor::CustomLineItem
34.     Properties:
35.       Name: 'TestFlatCustomLineItem'
36.       Description: 'Test flat custom line item created through Cloudformation for a $10 charge.'
37.       BillingGroupArn: !GetAtt TestBillingGroup.Arn
38.       CustomLineItemChargeDetails:
39.         Flat:
40.           ChargeValue: 10
41.         Type: 'FEE'
42.   TestPercentageCustomLineItem:
43.     Type: AWS::BillingConductor::CustomLineItem
44.     Properties:
45.       Name: 'TestPercentageCustomLineItem'
46.       Description: 'Test percentage custom line item created through Cloudformation for a %10 additional charge on the overall total bill of the billing group.'
47.       BillingGroupArn: !GetAtt TestBillingGroup.Arn
48.       CustomLineItemChargeDetails:
49.         Percentage:
50.           PercentageValue: 10
51.           ChildAssociatedResources:
52.             - !GetAtt TestBillingGroup.Arn
53.         Type: 'FEE'
```

# CloudFormation 템플릿 코드 조각
<a name="quickref-cloudformation"></a>

**Topics**
+ [중첩 스택](#w2aac11c41c23b5)
+ [대기 조건](#w2aac11c41c23b7)

## 중첩 스택
<a name="w2aac11c41c23b5"></a>

### 템플릿에 스택 중첩
<a name="scenario-stack"></a>

이 예제 템플릿에는 `myStack`이라는 중첩 스택 리소스가 포함되어 있습니다. CloudFormation은 템플릿에서 스택을 생성할 때 `myStack`을 생성하는데, 이 스택에서 템플릿은 `TemplateURL` 속성에 지정됩니다. 출력 값 `StackRef`는 `myStack`의 스택 ID이고 `OutputFromNestedStack` 값은 `myStack` 리소스의 출력 값 `BucketName`을 반환합니다. `Outputs.nestedstackoutputname` 형식은 중첩 스택의 출력 값을 지정하는 용도로 예약되어 있으며 포함 템플릿 내 어디서든 사용할 수 있습니다.

자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-stack.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-stack.html) 섹션을 참조하세요.

#### JSON
<a name="quickref-cloudformation-example-1.json"></a>

```
 1. {
 2.     "AWSTemplateFormatVersion" : "2010-09-09",
 3.     "Resources" : {
 4.         "myStack" : {
 5. 	       "Type" : "AWS::CloudFormation::Stack",
 6. 	       "Properties" : {
 7. 	        "TemplateURL" : "https://s3.amazonaws.com/cloudformation-templates-us-east-1/S3_Bucket.template",
 8.               "TimeoutInMinutes" : "60"
 9. 	       }
10.         }
11.     },
12.     "Outputs": {
13.        "StackRef": {"Value": { "Ref" : "myStack"}},
14.        "OutputFromNestedStack" : {
15.              "Value" : { "Fn::GetAtt" : [ "myStack", "Outputs.BucketName" ] }
16.        }
17.     }
18. }
```

#### YAML
<a name="quickref-cloudformation-example-1.yaml"></a>

```
 1. AWSTemplateFormatVersion: '2010-09-09'
 2. Resources:
 3.   myStack:
 4.     Type: AWS::CloudFormation::Stack
 5.     Properties:
 6.       TemplateURL: https://s3.amazonaws.com/cloudformation-templates-us-east-1/S3_Bucket.template
 7.       TimeoutInMinutes: '60'
 8. Outputs:
 9.   StackRef:
10.     Value: !Ref myStack
11.   OutputFromNestedStack:
12.     Value: !GetAtt myStack.Outputs.BucketName
```

### 템플릿 내 입력 파라미터를 사용하여 스택 중첩
<a name="scenario-stack-parameters"></a>

이 예제 템플릿에는 입력 파라미터를 지정하는 스택 리소스가 들어 있습니다. CloudFormation이 템플릿에서 스택을 생성하는 경우, `myStackWithParams` 스택을 생성하는 데 사용되는 템플릿의 입력 파라미터로 `Parameters` 속성 안에 선언되는 값 페어를 사용합니다. 이 예제에는 `InstanceType` 및 `KeyName` 파라미터가 지정되어 있습니다.

자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-stack.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-stack.html) 섹션을 참조하세요.

#### JSON
<a name="quickref-cloudformation-example-2.json"></a>

```
 1. {
 2.     "AWSTemplateFormatVersion" : "2010-09-09",
 3.     "Resources" : {
 4.         "myStackWithParams" : {
 5.   	       "Type" : "AWS::CloudFormation::Stack",
 6. 	       "Properties" : {
 7. 	           "TemplateURL" : "https://s3.amazonaws.com/cloudformation-templates-us-east-1/EC2ChooseAMI.template",
 8. 	           "Parameters" : {
 9. 	               "InstanceType" : "t2.micro",
10. 	               "KeyName" : "mykey"
11. 	           }
12.    	       }
13.         }
14.     }
15. }
```

#### YAML
<a name="quickref-cloudformation-example-2.yaml"></a>

```
1. AWSTemplateFormatVersion: '2010-09-09'
2. Resources:
3.   myStackWithParams:
4.     Type: AWS::CloudFormation::Stack
5.     Properties:
6.       TemplateURL: https://s3.amazonaws.com/cloudformation-templates-us-east-1/EC2ChooseAMI.template
7.       Parameters:
8.         InstanceType: t2.micro
9.         KeyName: mykey
```

## 대기 조건
<a name="w2aac11c41c23b7"></a>

### Amazon EC2 인스턴스에 대기 조건 사용
<a name="scenario-waitcondition"></a>

**중요**  
Amazon EC2 및 Auto Scaling 리소스의 경우 대기 조건 대신 CreationPolicy 속성을 사용하는 것이 좋습니다. 그러한 리소스에 CreationPolicy 속성을 추가하고 cfn-signal 헬퍼 스크립트를 사용하여 인스턴스 생성 프로세스가 완료되면 신호를 보내도록 합니다.

생성 정책을 사용할 수 없는 경우 다음 예제 템플릿을 참조할 수 있습니다. 이 템플릿에서는 대기 조건을 사용하여 Amazon EC2 인스턴스를 선언합니다. `myWaitCondition` 대기 조건은 신호 전송에 `myWaitConditionHandle`을 사용하고, `DependsOn` 속성을 사용하여 Amazon EC2 인스턴스 리소스가 생성된 후 대기 조건이 트리거되도록 지정하고, `Timeout` 속성을 사용하여 대기 조건의 기간을 4,500초로 지정합니다. 또한, 대기 조건에 신호를 전송하는 미리 서명된 URL이 `Ec2Instance` 리소스의 `UserData` 속성을 사용하여 Amazon EC2 인스턴스에 전달되므로, 해당 Amazon EC2 인스턴스에서 실행 중인 애플리케이션이나 스크립트에서 미리 서명된 URL을 검색한 후 이 URL을 사용하여 대기 조건에 성공 또는 실패 신호를 전송할 수 있습니다. `cfn-signal`을 사용하거나 대기 조건에 신호를 전송하는 애플리케이션 또는 스크립트를 생성해야 합니다. 출력 값 `ApplicationData`에는 대기 조건 신호에서 다시 전달된 데이터가 포함되어 있습니다.

자세한 내용은 [CloudFormation 템플릿에서 대기 조건 생성](using-cfn-waitcondition.md) 섹션을 참조하세요.

#### JSON
<a name="quickref-cloudformation-example-3.json"></a>

```
 1. {
 2.     "AWSTemplateFormatVersion" : "2010-09-09",
 3.     "Mappings" : {
 4.         "RegionMap" : {
 5.             "us-east-1" : {
 6.                 "AMI" : "ami-0123456789abcdef0"
 7.             },
 8.             "us-west-1" : {
 9.                 "AMI" : "ami-0987654321fedcba0"
10.             },
11.             "eu-west-1" : {
12.                 "AMI" : "ami-0abcdef123456789a"
13.             },
14.             "ap-northeast-1" : {
15.                 "AMI" : "ami-0fedcba987654321b"
16.             },
17.             "ap-southeast-1" : {
18.                 "AMI" : "ami-0c1d2e3f4a5b6c7d8"
19.             }
20.         }
21.     },
22.     "Resources" : {
23.         "Ec2Instance" : {
24.             "Type" : "AWS::EC2::Instance",
25.             "Properties" : {
26.                 "UserData" : { "Fn::Base64" : {"Ref" : "myWaitHandle"}},
27.                 "ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]}
28.             }
29.         },
30.         "myWaitHandle" : {
31.             "Type" : "AWS::CloudFormation::WaitConditionHandle",
32.             "Properties" : {
33.             }
34.         },
35.         "myWaitCondition" : {
36.             "Type" : "AWS::CloudFormation::WaitCondition",
37.             "DependsOn" : "Ec2Instance",
38.             "Properties" : {
39.                 "Handle" : { "Ref" : "myWaitHandle" },
40.                 "Timeout" : "4500"
41.             }
42.         }
43.     },
44.     "Outputs" : {
45.         "ApplicationData" : {
46.             "Value" : { "Fn::GetAtt" : [ "myWaitCondition", "Data" ]},
47.             "Description" : "The data passed back as part of signalling the WaitCondition."
48.         }
49.     }
50. }
```

#### YAML
<a name="quickref-cloudformation-example-3.yaml"></a>

```
 1. AWSTemplateFormatVersion: '2010-09-09'
 2. Mappings:
 3.   RegionMap:
 4.     us-east-1:
 5.       AMI: ami-0123456789abcdef0
 6.     us-west-1:
 7.       AMI: ami-0987654321fedcba0
 8.     eu-west-1:
 9.       AMI: ami-0abcdef123456789a
10.     ap-northeast-1:
11.       AMI: ami-0fedcba987654321b
12.     ap-southeast-1:
13.       AMI: ami-0c1d2e3f4a5b6c7d8
14. Resources:
15.   Ec2Instance:
16.     Type: AWS::EC2::Instance
17.     Properties:
18.       UserData:
19.         Fn::Base64: !Ref myWaitHandle
20.       ImageId:
21.         Fn::FindInMap:
22.         - RegionMap
23.         - Ref: AWS::Region
24.         - AMI
25.   myWaitHandle:
26.     Type: AWS::CloudFormation::WaitConditionHandle
27.     Properties: {}
28.   myWaitCondition:
29.     Type: AWS::CloudFormation::WaitCondition
30.     DependsOn: Ec2Instance
31.     Properties:
32.       Handle: !Ref myWaitHandle
33.       Timeout: '4500'
34. Outputs:
35.   ApplicationData:
36.     Value: !GetAtt myWaitCondition.Data
37.     Description: The data passed back as part of signalling the WaitCondition.
```

### cfn-signal 헬퍼 스크립트를 사용하여 대기 조건에 신호 전송
<a name="scenario-waitcondition-cfn-signal"></a>

이 예제는 대기 조건에 성공 신호를 전송하는 `cfn-signal` 명령줄을 보여줍니다. EC2 인스턴스의 `UserData` 속성에서 명령줄을 정의해야 합니다.

#### JSON
<a name="w2aac11c41c23b7b4b4"></a>

```
"UserData": {
  "Fn::Base64": {
    "Fn::Join": [
      "", 
      [
         "#!/bin/bash -xe\n",
         "/opt/aws/bin/cfn-signal --exit-code 0 '", 
         {
           "Ref": "myWaitHandle"
         },
         "'\n"
      ]   
    ]
  }
}
```

#### YAML
<a name="w2aac11c41c23b7b4b6"></a>

```
UserData:
  Fn::Base64: !Sub |
    #!/bin/bash -xe
    /opt/aws/bin/cfn-signal --exit-code 0 '${myWaitHandle}'
```

### Curl을 사용하여 대기 조건에 신호 전송
<a name="scenario-waitcondition-curl"></a>

다음 예제에서는 대기 조건에 성공 신호를 전송하는 Curl 명령줄을 보여 줍니다.

```
1. curl -T /tmp/a "https://cloudformation-waitcondition-test.s3.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-1%3A034017226601%3Astack%2Fstack-gosar-20110427004224-test-stack-with-WaitCondition--VEYW%2Fe498ce60-70a1-11e0-81a7-5081d0136786%2FmyWaitConditionHandle?Expires=1303976584&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Signature=ik1twT6hpS4cgNAw7wyOoRejVoo%3D"
```

이때 file /tmp/a에는 다음과 같은 JSON 구조가 포함되어 있습니다.

```
1. {
2.   "Status" : "SUCCESS",
3.   "Reason" : "Configuration Complete",
4.   "UniqueId" : "ID1234",
5.   "Data" : "Application has completed configuration."
6. }
```

이 예제에서는 명령줄에서 JSON을 파라미터로 전송하는 경우를 제외하고는 동일한 성공 신호를 전송하는 Curl 명령줄을 표시합니다.

```
1. curl -X PUT -H 'Content-Type:' --data-binary '{"Status" : "SUCCESS","Reason" : "Configuration Complete","UniqueId" : "ID1234","Data" : "Application has completed configuration."}' "https://cloudformation-waitcondition-test.s3.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-1%3A034017226601%3Astack%2Fstack-gosar-20110427004224-test-stack-with-WaitCondition--VEYW%2Fe498ce60-70a1-11e0-81a7-5081d0136786%2FmyWaitConditionHandle?Expires=1303976584&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Signature=ik1twT6hpS4cgNAw7wyOoRejVoo%3D"
```

# Amazon CloudFront 템플릿 코드 조각
<a name="quickref-cloudfront"></a>

CloudFormation에서 이러한 샘플 템플릿 코드 조각을 Amazon CloudFront 배포 리소스에 사용합니다. 자세한 내용은 [Amazon CloudFront 리소스 유형](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/AWS_CloudFront.html)을 참조하세요.

**Topics**
+ [Amazon S3 오리진을 사용하는 Amazon CloudFront 배포 리소스](#scenario-cloudfront-s3origin)
+ [사용자 지정 오리진을 사용하는 Amazon CloudFront 배포 리소스](#scenario-cloudfront-customorigin)
+ [다중 오리진 지원으로 Amazon CloudFront 배포](#scenario-cloudfront-multiorigin)
+ [Lambda 함수를 오리진으로 사용하여 Amazon CloudFront 배포](#scenario-cloudfront-lambda-origin)
+ [다음 사항도 참조하세요.](#w2aac11c41c27c15)

## Amazon S3 오리진을 사용하는 Amazon CloudFront 배포 리소스
<a name="scenario-cloudfront-s3origin"></a>

다음 예제 템플릿에서는 [S3Origin](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-cloudfront-distribution-s3originconfig.html) 및 레거시 오리진 액세스 ID(OAI)를 사용하는 Amazon CloudFront [배포](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudfront-distribution.html)를 보여줍니다. 오리진 액세스 제어(OAC)를 대신 사용하는 방법에 대한 자세한 내용을 알아보려면 **Amazon CloudFront 개발자 안내서의 [Amazon Simple Storage Service 오리진에 대한 액세스 제한](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html)을 참조하세요.

### JSON
<a name="quickref-cloudfront-example-1.json"></a>

```
 1. {
 2.     "AWSTemplateFormatVersion" : "2010-09-09",
 3.     "Resources" : {
 4.         "myDistribution" : {
 5.             "Type" : "AWS::CloudFront::Distribution",
 6.             "Properties" : {
 7.                 "DistributionConfig" : {
 8.                     "Origins" : [ {
 9.                         "DomainName" : "amzn-s3-demo-bucket.s3.amazonaws.com",
10.                         "Id" : "myS3Origin",
11.                         "S3OriginConfig" : {
12.                             "OriginAccessIdentity" : "origin-access-identity/cloudfront/E127EXAMPLE51Z"
13.                         }
14.                     }],
15.                     "Enabled" : "true",
16.                     "Comment" : "Some comment",
17.                     "DefaultRootObject" : "index.html",
18.                     "Logging" : {
19.                         "IncludeCookies" : "false",
20.                         "Bucket" : "amzn-s3-demo-logging-bucket.s3.amazonaws.com",
21.                         "Prefix" : "myprefix"
22.                     },
23.                     "Aliases" : [ "mysite.example.com", "yoursite.example.com" ],
24.                     "DefaultCacheBehavior" : {
25.                         "AllowedMethods" : [ "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT" ],  
26.                         "TargetOriginId" : "myS3Origin",
27.                         "ForwardedValues" : {
28.                             "QueryString" : "false",
29.                             "Cookies" : { "Forward" : "none" }
30.                         },
31.                         "TrustedSigners" : [ "1234567890EX", "1234567891EX" ],
32.                         "ViewerProtocolPolicy" : "allow-all"
33.                     },
34.                    "PriceClass" : "PriceClass_200",
35.                    "Restrictions" : {
36.                        "GeoRestriction" : {
37.                            "RestrictionType" : "whitelist",
38.                            "Locations" : [ "AQ", "CV" ]
39.                        }
40.                    },
41.                    "ViewerCertificate" : { "CloudFrontDefaultCertificate" : "true" }  
42.                 }
43.             }
44.         }
45.     }
46. }
```

### YAML
<a name="quickref-cloudfront-example-1.yaml"></a>

```
 1. AWSTemplateFormatVersion: '2010-09-09'
 2. Resources:
 3.   myDistribution:
 4.     Type: AWS::CloudFront::Distribution
 5.     Properties:
 6.       DistributionConfig:
 7.         Origins:
 8.         - DomainName: amzn-s3-demo-bucket.s3.amazonaws.com
 9.           Id: myS3Origin
10.           S3OriginConfig:
11.             OriginAccessIdentity: origin-access-identity/cloudfront/E127EXAMPLE51Z
12.         Enabled: 'true'
13.         Comment: Some comment
14.         DefaultRootObject: index.html
15.         Logging:
16.           IncludeCookies: 'false'
17.           Bucket: amzn-s3-demo-logging-bucket.s3.amazonaws.com
18.           Prefix: myprefix
19.         Aliases:
20.         - mysite.example.com
21.         - yoursite.example.com
22.         DefaultCacheBehavior:
23.           AllowedMethods:
24.           - DELETE
25.           - GET
26.           - HEAD
27.           - OPTIONS
28.           - PATCH
29.           - POST
30.           - PUT
31.           TargetOriginId: myS3Origin
32.           ForwardedValues:
33.             QueryString: 'false'
34.             Cookies:
35.               Forward: none
36.           TrustedSigners:
37.           - 1234567890EX
38.           - 1234567891EX
39.           ViewerProtocolPolicy: allow-all
40.         PriceClass: PriceClass_200
41.         Restrictions:
42.           GeoRestriction:
43.             RestrictionType: whitelist
44.             Locations:
45.             - AQ
46.             - CV
47.         ViewerCertificate:
48.           CloudFrontDefaultCertificate: 'true'
```

## 사용자 지정 오리진을 사용하는 Amazon CloudFront 배포 리소스
<a name="scenario-cloudfront-customorigin"></a>

다음 예제 템플릿에서는 [CustomOrigin](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-cloudfront-distribution-customoriginconfig.html)을 사용하는 Amazon CloudFront [배포](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudfront-distribution.html)를 보여줍니다.

### JSON
<a name="quickref-cloudfront-example-2.json"></a>

```
 1. {
 2.     "AWSTemplateFormatVersion" : "2010-09-09",
 3.     "Resources" : {
 4.         "myDistribution" : {
 5.             "Type" : "AWS::CloudFront::Distribution",
 6.             "Properties" : {
 7.                 "DistributionConfig" : {
 8.                     "Origins" : [ {
 9.                             "DomainName" : "www.example.com",
10.                             "Id" : "myCustomOrigin",
11.                             "CustomOriginConfig" : {
12.                                 "HTTPPort" : "80",
13.                                 "HTTPSPort" : "443",
14.                                 "OriginProtocolPolicy" : "http-only"
15.                             }
16.                     } ],
17.                     "Enabled" : "true",
18.                     "Comment" : "Somecomment",
19.                     "DefaultRootObject" : "index.html",
20.                     "Logging" : {
21.                         "IncludeCookies" : "true",
22.                         "Bucket" : "amzn-s3-demo-logging-bucket.s3.amazonaws.com",
23.                         "Prefix": "myprefix"
24.                     },
25.                     "Aliases" : [
26.                         "mysite.example.com",
27.                         "*.yoursite.example.com"
28.                     ],
29.                     "DefaultCacheBehavior" : {
30.                         "TargetOriginId" : "myCustomOrigin",
31.                         "SmoothStreaming" : "false",  
32.                         "ForwardedValues" : {
33.                             "QueryString" : "false",
34.                             "Cookies" : { "Forward" : "all" }
35.                         },
36.                         "TrustedSigners" : [
37.                             "1234567890EX",
38.                             "1234567891EX"
39.                         ],
40.                         "ViewerProtocolPolicy" : "allow-all"
41.                     },
42.                     "CustomErrorResponses" : [ {
43.                         "ErrorCode" : "404",
44.                         "ResponsePagePath" : "/error-pages/404.html",
45.                         "ResponseCode" : "200",
46.                         "ErrorCachingMinTTL" : "30"
47.                     } ],
48.                    "PriceClass" : "PriceClass_200",
49.                    "Restrictions" : {
50.                        "GeoRestriction" : {
51.                            "RestrictionType" : "whitelist",
52.                            "Locations" : [ "AQ", "CV" ]
53.                        }
54.                    },
55.                    "ViewerCertificate": { "CloudFrontDefaultCertificate" : "true" }
56.                 }
57.             }
58.         }
59.     }
60. }
```

### YAML
<a name="quickref-cloudfront-example-2.yaml"></a>

```
 1. AWSTemplateFormatVersion: '2010-09-09'
 2. Resources:
 3.   myDistribution:
 4.     Type: AWS::CloudFront::Distribution
 5.     Properties:
 6.       DistributionConfig:
 7.         Origins:
 8.         - DomainName: www.example.com
 9.           Id: myCustomOrigin
10.           CustomOriginConfig:
11.             HTTPPort: '80'
12.             HTTPSPort: '443'
13.             OriginProtocolPolicy: http-only
14.         Enabled: 'true'
15.         Comment: Somecomment
16.         DefaultRootObject: index.html
17.         Logging:
18.           IncludeCookies: 'true'
19.           Bucket: amzn-s3-demo-logging-bucket.s3.amazonaws.com
20.           Prefix: myprefix
21.         Aliases:
22.         - mysite.example.com
23.         - "*.yoursite.example.com"
24.         DefaultCacheBehavior:
25.           TargetOriginId: myCustomOrigin
26.           SmoothStreaming: 'false'
27.           ForwardedValues:
28.             QueryString: 'false'
29.             Cookies:
30.               Forward: all
31.           TrustedSigners:
32.           - 1234567890EX
33.           - 1234567891EX
34.           ViewerProtocolPolicy: allow-all
35.         CustomErrorResponses:
36.         - ErrorCode: '404'
37.           ResponsePagePath: "/error-pages/404.html"
38.           ResponseCode: '200'
39.           ErrorCachingMinTTL: '30'
40.         PriceClass: PriceClass_200
41.         Restrictions:
42.           GeoRestriction:
43.             RestrictionType: whitelist
44.             Locations:
45.             - AQ
46.             - CV
47.         ViewerCertificate:
48.           CloudFrontDefaultCertificate: 'true'
```

## 다중 오리진 지원으로 Amazon CloudFront 배포
<a name="scenario-cloudfront-multiorigin"></a>

다음 예제 템플릿에서는 다중 오리진 지원을 사용하는 CloudFront [배포](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudfront-distribution.html)를 선언하는 방법을 보여줍니다. [DistributionConfig](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-cloudfront-distribution-distributionconfig.html)에서 오리진 목록이 제공되며 [DefaultCacheBehavior](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-cloudfront-distribution-defaultcachebehavior.html)가 설정됩니다.

### JSON
<a name="quickref-cloudfront-example-3.json"></a>

```
{
    "AWSTemplateFormatVersion" : "2010-09-09",
    "Resources" : {
        "myDistribution" : {
            "Type" : "AWS::CloudFront::Distribution",
            "Properties" : {
                "DistributionConfig" : {
                    "Origins" : [ {
                        "Id" : "myS3Origin",
                        "DomainName" : "amzn-s3-demo-bucket.s3.amazonaws.com",
                        "S3OriginConfig" : {
                            "OriginAccessIdentity" : "origin-access-identity/cloudfront/E127EXAMPLE51Z"
                        }
                     }, 
                     {
                         "Id" : "myCustomOrigin",
                         "DomainName" : "www.example.com",
                         "CustomOriginConfig" : {
                             "HTTPPort" : "80",
                             "HTTPSPort" : "443",
                             "OriginProtocolPolicy" : "http-only"
                         }
                     }
                   ],
                   "Enabled" : "true",
                   "Comment" : "Some comment",
                   "DefaultRootObject" : "index.html", 
                   "Logging" : {
                       "IncludeCookies" : "true",
                       "Bucket" : "amzn-s3-demo-logging-bucket.s3.amazonaws.com",
                       "Prefix" : "myprefix"
                   },            
                   "Aliases" : [ "mysite.example.com", "yoursite.example.com" ],
                   "DefaultCacheBehavior" : {
                       "TargetOriginId" : "myS3Origin",
                       "ForwardedValues" : {
                           "QueryString" : "false",
                           "Cookies" : { "Forward" : "all" }
                        },
                       "TrustedSigners" : [ "1234567890EX", "1234567891EX"  ],
                       "ViewerProtocolPolicy" : "allow-all",
                       "MinTTL" : "100",
                       "SmoothStreaming" : "true"
                   },
                   "CacheBehaviors" : [ {
                            "AllowedMethods" : [ "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT" ],  
                            "TargetOriginId" : "myS3Origin",
                            "ForwardedValues" : {
                                "QueryString" : "true",
                                "Cookies" : { "Forward" : "none" }
                            },
                            "TrustedSigners" : [ "1234567890EX", "1234567891EX" ],
                            "ViewerProtocolPolicy" : "allow-all",
                            "MinTTL" : "50",
                            "PathPattern" : "images1/*.jpg"
                        }, 
                        {
                            "AllowedMethods" : [ "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT" ],  
                            "TargetOriginId" : "myCustomOrigin",
                            "ForwardedValues" : {
                                "QueryString" : "true",
                                "Cookies" : { "Forward" : "none" }
                            },
                            "TrustedSigners" : [ "1234567890EX", "1234567891EX"  ],
                            "ViewerProtocolPolicy" : "allow-all",
                            "MinTTL" : "50",
                            "PathPattern" : "images2/*.jpg"
                        }
                   ],
                   "CustomErrorResponses" : [ {
                       "ErrorCode" : "404",
                       "ResponsePagePath" : "/error-pages/404.html",
                       "ResponseCode" : "200",
                       "ErrorCachingMinTTL" : "30"
                   } ],
                   "PriceClass" : "PriceClass_All",
                   "ViewerCertificate" : { "CloudFrontDefaultCertificate" : "true" }
                }
            }
        }
    }
}
```

### YAML
<a name="quickref-cloudfront-example-3.yaml"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  myDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
        - Id: myS3Origin
          DomainName: amzn-s3-demo-bucket.s3.amazonaws.com
          S3OriginConfig:
            OriginAccessIdentity: origin-access-identity/cloudfront/E127EXAMPLE51Z
        - Id: myCustomOrigin
          DomainName: www.example.com
          CustomOriginConfig:
            HTTPPort: '80'
            HTTPSPort: '443'
            OriginProtocolPolicy: http-only
        Enabled: 'true'
        Comment: Some comment
        DefaultRootObject: index.html
        Logging:
          IncludeCookies: 'true'
          Bucket: amzn-s3-demo-logging-bucket.s3.amazonaws.com
          Prefix: myprefix
        Aliases:
        - mysite.example.com
        - yoursite.example.com
        DefaultCacheBehavior:
          TargetOriginId: myS3Origin
          ForwardedValues:
            QueryString: 'false'
            Cookies:
              Forward: all
          TrustedSigners:
          - 1234567890EX
          - 1234567891EX
          ViewerProtocolPolicy: allow-all
          MinTTL: '100'
          SmoothStreaming: 'true'
        CacheBehaviors:
        - AllowedMethods:
          - DELETE
          - GET
          - HEAD
          - OPTIONS
          - PATCH
          - POST
          - PUT
          TargetOriginId: myS3Origin
          ForwardedValues:
            QueryString: 'true'
            Cookies:
              Forward: none
          TrustedSigners:
          - 1234567890EX
          - 1234567891EX
          ViewerProtocolPolicy: allow-all
          MinTTL: '50'
          PathPattern: images1/*.jpg
        - AllowedMethods:
          - DELETE
          - GET
          - HEAD
          - OPTIONS
          - PATCH
          - POST
          - PUT
          TargetOriginId: myCustomOrigin
          ForwardedValues:
            QueryString: 'true'
            Cookies:
              Forward: none
          TrustedSigners:
          - 1234567890EX
          - 1234567891EX
          ViewerProtocolPolicy: allow-all
          MinTTL: '50'
          PathPattern: images2/*.jpg
        CustomErrorResponses:
        - ErrorCode: '404'
          ResponsePagePath: "/error-pages/404.html"
          ResponseCode: '200'
          ErrorCachingMinTTL: '30'
        PriceClass: PriceClass_All
        ViewerCertificate:
          CloudFrontDefaultCertificate: 'true'
```

## Lambda 함수를 오리진으로 사용하여 Amazon CloudFront 배포
<a name="scenario-cloudfront-lambda-origin"></a>

다음 예에서는 지정된 Lambda 함수 URL(파라미터로 제공됨)의 프런트가 되는 CloudFront 배포를 생성하여, HTTPS 전용 액세스, 캐싱, 압축 및 글로벌 전송을 활성화합니다. Lambda URL을 사용자 지정 HTTPS 오리진으로 구성하고 표준 AWS 캐싱 정책을 적용합니다. 이 배포는 HTTP/2 및 IPv6을 통해 최적화된 성능을 제공하며, CloudFront 도메인 이름을 출력하므로 사용자가 안전한 CDN 지원 엔드포인트를 통해 Lambda 함수에 액세스할 수 있습니다. 자세한 내용은 AWS 블로그에서 [Using Amazon CloudFront with AWS Lambda as origin to accelerate your web applications](https://aws.amazon.com/blogs/networking-and-content-delivery/using-amazon-cloudfront-with-aws-lambda-as-origin-to-accelerate-your-web-applications/)를 참조하세요.

### JSON
<a name="quickref-cloudfront-example-lambda-origin.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "LambdaEndpoint": {
            "Type": "String",
            "Description": "The Lambda function URL endpoint without the 'https://'"
        }
    },
    "Resources": {
        "MyDistribution": {
            "Type": "AWS::CloudFront::Distribution",
            "Properties": {
                "DistributionConfig": {
                    "PriceClass": "PriceClass_All",
                    "HttpVersion": "http2",
                    "IPV6Enabled": true,
                    "Origins": [
                        {
                            "DomainName": {
                                "Ref": "LambdaEndpoint"
                            },
                            "Id": "LambdaOrigin",
                            "CustomOriginConfig": {
                                "HTTPSPort": 443,
                                "OriginProtocolPolicy": "https-only"
                            }
                        }
                    ],
                    "Enabled": "true",
                    "DefaultCacheBehavior": {
                        "TargetOriginId": "LambdaOrigin",
                        "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6",
                        "ViewerProtocolPolicy": "redirect-to-https",
                        "SmoothStreaming": "false",
                        "Compress": "true"
                    }
                }
            }
        }
    },
    "Outputs": {
        "CloudFrontDomain": {
            "Description": "CloudFront default domain name configured",
            "Value": {
                "Fn::Sub": "https://${MyDistribution.DomainName}/"
            }
        }
    }
}
```

### YAML
<a name="quickref-cloudfront-example-lambda-origin.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  LambdaEndpoint:
    Type: String
    Description: The Lambda function URL endpoint without the 'https://'
Resources:
  MyDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        PriceClass: PriceClass_All
        HttpVersion: http2
        IPV6Enabled: true
        Origins:
        - DomainName: !Ref LambdaEndpoint
          Id: LambdaOrigin
          CustomOriginConfig:
            HTTPSPort: 443
            OriginProtocolPolicy: https-only
        Enabled: 'true'
        DefaultCacheBehavior:
          TargetOriginId: LambdaOrigin
          CachePolicyId: '658327ea-f89d-4fab-a63d-7e88639e58f6'
          ViewerProtocolPolicy: redirect-to-https
          SmoothStreaming: 'false'
          Compress: 'true'
Outputs:
  CloudFrontDomain:
    Description: CloudFront default domain name configured
    Value: !Sub https://${MyDistribution.DomainName}/
```

## 다음 사항도 참조하세요.
<a name="w2aac11c41c27c15"></a>

Route 53 레코드에 사용자 지정 별칭을 추가하여 CloudFront 배포에 익숙한 이름을 지정하는 예는 [CloudFront 배포에 대한 별칭 리소스 레코드 세트](quickref-route53.md#scenario-user-friendly-url-for-cloudfront-distribution) 섹션을 참조하세요.

# Amazon CloudWatch 템플릿 코드 조각
<a name="quickref-cloudwatch"></a>

CloudFormation에서 Amazon CloudWatch 리소스를 설명하는 데 도움이 되는 샘플 템플릿 스니펫을 사용합니다. 자세한 내용은 [Amazon CloudWatch 리소스 유형](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/AWS_CloudWatch.html)을 참조하세요.

**Topics**
+ [결제 경보](#cloudwatch-sample-billing-alarm)
+ [CPU 사용률 경보](#cloudwatch-sample-cpu-utilization-alarm)
+ [Amazon Elastic Compute Cloud 인스턴스 복구](#cloudwatch-sample-recover-instance)
+ [기본 대시보드 생성](#cloudwatch-sample-dashboard-basic)
+ [단계별 위젯이 있는 대시보드 생성](#cloudwatch-sample-dashboard-sidebyside)

## 결제 경보
<a name="cloudwatch-sample-billing-alarm"></a>

다음 샘플에서 Amazon CloudWatch는 AWS 계정에 대한 요금이 경보 임계값을 초과할 경우 이메일 알림을 전송합니다. 사용량 알림을 수신하려면 결제 알림을 활성화하십시오. 자세한 내용은 **Amazon CloudWatch 사용 설명서의 [청구 경보를 생성하여 예상 AWS 요금 모니터링](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html)을 참조하세요.

### JSON
<a name="quickref-cloudwatch-example-1.json"></a>

```
"SpendingAlarm": {
  "Type": "AWS::CloudWatch::Alarm",
  "Properties": {
    "AlarmDescription": { "Fn::Join": ["", [
      "Alarm if AWS spending is over $",
      { "Ref": "AlarmThreshold" }
    ]]},
    "Namespace": "AWS/Billing",
    "MetricName": "EstimatedCharges",
    "Dimensions": [{
      "Name": "Currency",
      "Value" : "USD"
    }],
    "Statistic": "Maximum",
    "Period": "21600",
    "EvaluationPeriods": "1",
    "Threshold": { "Ref": "AlarmThreshold" },
    "ComparisonOperator": "GreaterThanThreshold",
    "AlarmActions": [{
      "Ref": "BillingAlarmNotification"
    }],
    "InsufficientDataActions": [{
      "Ref": "BillingAlarmNotification"
    }]
  }
}
```

### YAML
<a name="quickref-cloudwatch-example-1.yaml"></a>

```
SpendingAlarm:
  Type: AWS::CloudWatch::Alarm
  Properties:
    AlarmDescription: 
      'Fn::Join':
        - ''
        - - Alarm if AWS spending is over $
          - !Ref: AlarmThreshold
    Namespace: AWS/Billing
    MetricName: EstimatedCharges
    Dimensions:
    - Name: Currency
      Value: USD
    Statistic: Maximum
    Period: '21600'
    EvaluationPeriods: '1'
    Threshold:
      !Ref: "AlarmThreshold"
    ComparisonOperator: GreaterThanThreshold
    AlarmActions:
    - !Ref: "BillingAlarmNotification"
    InsufficientDataActions:
    - !Ref: "BillingAlarmNotification"
```

## CPU 사용률 경보
<a name="cloudwatch-sample-cpu-utilization-alarm"></a>

다음 샘플 코드 조각은 Amazon EC2 인스턴스의 평균 CPU 사용률이 세 평가 기간 동안 60초 이상 90%를 초과할 경우 알림을 전송하는 경보를 생성합니다.

### JSON
<a name="quickref-cloudwatch-example-2.json"></a>

```
 1. "CPUAlarm" : {
 2.   "Type" : "AWS::CloudWatch::Alarm",
 3.   "Properties" : {
 4.     "AlarmDescription" : "CPU alarm for my instance",
 5.     "AlarmActions" : [ { "Ref" : "logical name of an AWS::SNS::Topic resource" } ],
 6.     "MetricName" : "CPUUtilization",
 7.     "Namespace" : "AWS/EC2",
 8.     "Statistic" : "Average",
 9.     "Period" : "60",
10.     "EvaluationPeriods" : "3",
11.     "Threshold" : "90",
12.     "ComparisonOperator" : "GreaterThanThreshold",
13.     "Dimensions" : [ {
14.       "Name" : "InstanceId",
15.       "Value" : { "Ref" : "logical name of an AWS::EC2::Instance resource" }
16.     } ]
17.   }
18. }
```

### YAML
<a name="quickref-cloudwatch-example-2.yaml"></a>

```
 1. CPUAlarm:
 2.   Type: AWS::CloudWatch::Alarm
 3.   Properties:
 4.     AlarmDescription: CPU alarm for my instance
 5.     AlarmActions:
 6.     - !Ref: "logical name of an AWS::SNS::Topic resource"
 7.     MetricName: CPUUtilization
 8.     Namespace: AWS/EC2
 9.     Statistic: Average
10.     Period: '60'
11.     EvaluationPeriods: '3'
12.     Threshold: '90'
13.     ComparisonOperator: GreaterThanThreshold
14.     Dimensions:
15.     - Name: InstanceId
16.       Value: !Ref: "logical name of an AWS::EC2::Instance resource"
```

## Amazon Elastic Compute Cloud 인스턴스 복구
<a name="cloudwatch-sample-recover-instance"></a>

다음 CloudWatch 경보는 15분 동안 연속해서 상태 확인에 실패할 경우 EC2 인스턴스를 복구합니다. 경보 작업에 대한 자세한 내용은 **Amazon CloudWatch 사용 설명서의 [EC2 인스턴스를 중지, 종료, 재부팅 또는 복구하는 경보 생성](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/UsingAlarmActions.html)을 참조하세요.

### JSON
<a name="quickref-cloudwatch-example-3.json"></a>

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters" : {
    "RecoveryInstance" : {
      "Description" : "The EC2 instance ID to associate this alarm with.",
      "Type" : "AWS::EC2::Instance::Id"
    }
  },
  "Resources": {
    "RecoveryTestAlarm": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "AlarmDescription": "Trigger a recovery when instance status check fails for 15 consecutive minutes.",
        "Namespace": "AWS/EC2" ,
        "MetricName": "StatusCheckFailed_System",
        "Statistic": "Minimum",
        "Period": "60",
        "EvaluationPeriods": "15",
        "ComparisonOperator": "GreaterThanThreshold",
        "Threshold": "0",
        "AlarmActions": [ {"Fn::Join" : ["", ["arn:aws:automate:", { "Ref" : "AWS::Region" }, ":ec2:recover" ]]} ],
        "Dimensions": [{"Name": "InstanceId","Value": {"Ref": "RecoveryInstance"}}]
      }
    }
  }
}
```

### YAML
<a name="quickref-cloudwatch-example-3.yaml"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  RecoveryInstance:
    Description: The EC2 instance ID to associate this alarm with.
    Type: AWS::EC2::Instance::Id
Resources:
  RecoveryTestAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: Trigger a recovery when instance status check fails for 15
        consecutive minutes.
      Namespace: AWS/EC2
      MetricName: StatusCheckFailed_System
      Statistic: Minimum
      Period: '60'
      EvaluationPeriods: '15'
      ComparisonOperator: GreaterThanThreshold
      Threshold: '0'
      AlarmActions: [ !Sub "arn:aws:automate:${AWS::Region}:ec2:recover" ]
      Dimensions:
      - Name: InstanceId
        Value: !Ref: RecoveryInstance
```

## 기본 대시보드 생성
<a name="cloudwatch-sample-dashboard-basic"></a>

다음 예에서는 CPU 사용률을 보여주는 측정치 위젯 하나와 메시지를 보여주는 텍스트 위젯 하나가 있는 간단한 CloudWatch 대시보드를 생성합니다.

### JSON
<a name="quickref-cloudwatch-sample-dashboard-basic.json"></a>

```
{
    "BasicDashboard": {
        "Type": "AWS::CloudWatch::Dashboard",
        "Properties": {
            "DashboardName": "Dashboard1",
            "DashboardBody": "{\"widgets\":[{\"type\":\"metric\",\"x\":0,\"y\":0,\"width\":12,\"height\":6,\"properties\":{\"metrics\":[[\"AWS/EC2\",\"CPUUtilization\",\"InstanceId\",\"i-012345\"]],\"period\":300,\"stat\":\"Average\",\"region\":\"us-east-1\",\"title\":\"EC2 Instance CPU\"}},{\"type\":\"text\",\"x\":0,\"y\":7,\"width\":3,\"height\":3,\"properties\":{\"markdown\":\"Hello world\"}}]}"
        }
    }
}
```

### YAML
<a name="quickref-cloudwatch-sample-dashboard-basic.yaml"></a>

```
BasicDashboard:
  Type: AWS::CloudWatch::Dashboard
  Properties:
    DashboardName: Dashboard1
    DashboardBody: '{"widgets":[{"type":"metric","x":0,"y":0,"width":12,"height":6,"properties":{"metrics":[["AWS/EC2","CPUUtilization","InstanceId","i-012345"]],"period":300,"stat":"Average","region":"us-east-1","title":"EC2 Instance CPU"}},{"type":"text","x":0,"y":7,"width":3,"height":3,"properties":{"markdown":"Hello world"}}]}'
```

## 단계별 위젯이 있는 대시보드 생성
<a name="cloudwatch-sample-dashboard-sidebyside"></a>

다음 예에서는 단계별로 표시되는 측정치 위젯 두 개가 있는 대시보드를 생성합니다.

### JSON
<a name="quickref-cloudwatch-sample-dashboard-sidebyside.json"></a>

```
{
    "DashboardSideBySide": {
        "Type": "AWS::CloudWatch::Dashboard",
        "Properties": {
            "DashboardName": "Dashboard1",
            "DashboardBody": "{\"widgets\":[{\"type\":\"metric\",\"x\":0,\"y\":0,\"width\":12,\"height\":6,\"properties\":{\"metrics\":[[\"AWS/EC2\",\"CPUUtilization\",\"InstanceId\",\"i-012345\"]],\"period\":300,\"stat\":\"Average\",\"region\":\"us-east-1\",\"title\":\"EC2 Instance CPU\"}},{\"type\":\"metric\",\"x\":12,\"y\":0,\"width\":12,\"height\":6,\"properties\":{\"metrics\":[[\"AWS/S3\",\"BucketSizeBytes\",\"BucketName\",\"amzn-s3-demo-bucket\"]],\"period\":86400,\"stat\":\"Maximum\",\"region\":\"us-east-1\",\"title\":\"amzn-s3-demo-bucket bytes\"}}]}"
        }
    }
}
```

### YAML
<a name="quickref-cloudwatch-sample-dashboard-sidebysidequickref-cloudwatch-sample-dashboard-sidebyside.yaml"></a>

```
DashboardSideBySide:
  Type: AWS::CloudWatch::Dashboard
  Properties:
    DashboardName: Dashboard1
    DashboardBody: '{"widgets":[{"type":"metric","x":0,"y":0,"width":12,"height":6,"properties":{"metrics":[["AWS/EC2","CPUUtilization","InstanceId","i-012345"]],"period":300,"stat":"Average","region":"us-east-1","title":"EC2 Instance CPU"}},{"type":"metric","x":12,"y":0,"width":12,"height":6,"properties":{"metrics":[["AWS/S3","BucketSizeBytes","BucketName","amzn-s3-demo-bucket"]],"period":86400,"stat":"Maximum","region":"us-east-1","title":"amzn-s3-demo-bucket bytes"}}]}'
```

# Amazon CloudWatch Logs 템플릿 코드 조각
<a name="quickref-cloudwatchlogs"></a>

Amazon CloudWatch Logs는 Amazon EC2 인스턴스 또는 기타 소스의 시스템, 애플리케이션 및 사용자 지정 로그 파일을 모니터링할 수 있습니다. CloudFormation을 사용하여 로그 그룹 및 지표 필터를 프로비저닝 및 관리할 수 있습니다. Amazon CloudWatch Logs에 대한 자세한 내용은 [Amazon CloudWatch Logs 사용자 설명서](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html)를 참조하세요.

**Topics**
+ [Linux 인스턴스에서 CloudWatch Logs로 로그 전송](#quickref-cloudwatchlogs-example1)
+ [Windows 인스턴스에서 CloudWatch Logs로 로그 전송](#quickref-cloudwatchlogs-example2)
+ [다음 사항도 참조하세요.](#w2aac11c41c35c11)

## Linux 인스턴스에서 CloudWatch Logs로 로그 전송
<a name="quickref-cloudwatchlogs-example1"></a>

다음 템플릿은 CloudWatch Logs 통합을 사용하여 Amazon Linux 2023에서 웹 서버를 설정하는 방법을 보여줍니다. 이 템플릿은 다음과 같은 작업을 수행합니다.
+ Apache 및 PHP를 설치합니다.
+ Apache 액세스 로그를 CloudWatch Logs로 전달하도록 CloudWatch 에이전트를 구성합니다.
+ CloudWatch 에이전트가 로그 데이터를 CloudWatch Logs로 전송할 수 있도록 IAM 역할을 설정합니다.
+ 사용자 지정 경보 및 알림을 생성하여 404 오류 또는 높은 대역폭 사용량을 모니터링합니다.

웹 서버의 로그 이벤트는 CloudWatch 경보에 대한 지표 데이터를 제공합니다. 두 지표 필터는 로그 정보가 CloudWatch 측정치로 변환되는 방식을 설명합니다. 404 측정치는 404 발생 횟수를 계산합니다. size 측정치는 요청의 크기를 추적합니다. 두 CloudWatch 경보는 2분 안에 404가 세 번 이상 발생했거나 평균 요청 크기가 10분 동안 3500KB 이상인 경우 알림을 전송합니다.

### JSON
<a name="quickref-cloudwatchlogs-example.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Sample template that sets up and configures CloudWatch Logs on Amazon Linux 2023 instance.",
    "Parameters": {
        "KeyName": {
            "Description": "Name of an existing EC2 KeyPair to enable SSH access to the instances",
            "Type": "AWS::EC2::KeyPair::KeyName",
            "ConstraintDescription": "must be the name of an existing EC2 KeyPair."
        },
        "SSHLocation": {
            "Description": "The IP address range that can be used to SSH to the EC2 instances",
            "Type": "String",
            "MinLength": "9",
            "MaxLength": "18",
            "Default": "0.0.0.0/0",
            "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
            "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
        },
        "OperatorEmail": {
            "Description": "Email address to notify when CloudWatch alarms are triggered (404 errors or high bandwidth usage)",
            "Type": "String"
        }
    },
    "Resources": {
        "LogRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "ec2.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "Path": "/",
                "Policies": [
                    {
                        "PolicyName": "LogRolePolicy",
                        "PolicyDocument": {
                            "Version": "2012-10-17",		 	 	 
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "logs:PutLogEvents",
                                        "logs:DescribeLogStreams",
                                        "logs:DescribeLogGroups",
                                        "logs:CreateLogGroup",
                                        "logs:CreateLogStream"
                                    ],
                                    "Resource": "*"
                                }
                            ]
                        }
                    }
                ]
            }
        },
        "LogRoleInstanceProfile": {
            "Type": "AWS::IAM::InstanceProfile",
            "Properties": {
                "Path": "/",
                "Roles": [{"Ref": "LogRole"}]
            }
        },
        "WebServerSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": "Enable HTTP access via port 80 and SSH access via port 22",
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 80,
                        "ToPort": 80,
                        "CidrIp": "0.0.0.0/0"
                    },
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 22,
                        "ToPort": 22,
                        "CidrIp": {"Ref": "SSHLocation"}
                    }
                ]
            }
        },
        "WebServerHost": {
            "Type": "AWS::EC2::Instance",
            "Metadata": {
                "Comment": "Install a simple PHP application on Amazon Linux 2023",
                "AWS::CloudFormation::Init": {
                    "config": {
                        "packages": {
                            "dnf": {
                                "httpd": [],
                                "php": [],
                                "php-fpm": []
                            }
                        },
                        "files": {
                            "/etc/amazon-cloudwatch-agent/amazon-cloudwatch-agent.json": {
                                "content": {
                                    "logs": {
                                        "logs_collected": {
                                            "files": {
                                                "collect_list": [{
                                                    "file_path": "/var/log/httpd/access_log",
                                                    "log_group_name": {"Ref": "WebServerLogGroup"},
                                                    "log_stream_name": "{instance_id}/apache.log",
                                                    "timestamp_format": "%d/%b/%Y:%H:%M:%S %z"
                                                }]
                                            }
                                        }
                                    }
                                },
                                "mode": "000644",
                                "owner": "root",
                                "group": "root"
                            },
                            "/var/www/html/index.php": {
                                "content": "<?php\necho '<h1>AWS CloudFormation sample PHP application on Amazon Linux 2023</h1>';\n?>\n",
                                "mode": "000644",
                                "owner": "apache",
                                "group": "apache"
                            },
                            "/etc/cfn/cfn-hup.conf": {
                                "content":  {
                                    "Fn::Join": [
                                        "",
                                        [
                                            "[main]\n",
                                            "stack=",
                                            {"Ref": "AWS::StackId"},
                                            "\n",
                                            "region=",
                                            {"Ref": "AWS::Region"},
                                            "\n"
                                        ]
                                    ]
                                },
                                "mode": "000400",
                                "owner": "root",
                                "group": "root"
                            },
                            "/etc/cfn/hooks.d/cfn-auto-reloader.conf": {
                                "content": {
                                    "Fn::Join": [
                                        "",
                                        [
                                            "[cfn-auto-reloader-hook]\n",
                                            "triggers=post.update\n",
                                            "path=Resources.WebServerHost.Metadata.AWS::CloudFormation::Init\n",
                                            "action=/opt/aws/bin/cfn-init -s ",
                                            {"Ref": "AWS::StackId"},
                                            " -r WebServerHost ",
                                            " --region     ",
                                            {"Ref": "AWS::Region"},
                                            "\n",
                                            "runas=root\n"
                                        ]
                                    ]
                                }
                            }
                        },
                        "services": {
                            "systemd": {
                                "httpd": {
                                    "enabled": "true",
                                    "ensureRunning": "true"
                                },
                                "php-fpm": {
                                    "enabled": "true",
                                    "ensureRunning": "true"
                                }
                            }
                        }
                    }
                }
            },
            "CreationPolicy": {
                "ResourceSignal": {
                    "Timeout": "PT5M"
                }
            },
            "Properties": {
                "ImageId": "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64}}",
                "KeyName": {"Ref": "KeyName"},
                "InstanceType": "t3.micro",
                "SecurityGroupIds": [{"Ref": "WebServerSecurityGroup"}],
                "IamInstanceProfile": {"Ref": "LogRoleInstanceProfile"},
                "UserData": {"Fn::Base64": {"Fn::Join": [ "", [
                    "#!/bin/bash\n",
                    "dnf update -y aws-cfn-bootstrap\n",
                    "dnf install -y amazon-cloudwatch-agent\n",
                    "/opt/aws/bin/cfn-init -v --stack ", {"Ref": "AWS::StackName"}, " --resource WebServerHost --region ", {"Ref": "AWS::Region"}, "\n",
                    "\n",
                    "# Verify Apache log directory exists and create if needed\n",
                    "mkdir -p /var/log/httpd\n",
                    "\n",
                    "# Start CloudWatch agent\n",
                    "/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/etc/amazon-cloudwatch-agent/amazon-cloudwatch-agent.json -s\n",
                    "\n",
                    "# Signal success\n",
                    "/opt/aws/bin/cfn-signal -e $? --stack ", {"Ref": "AWS::StackName"}, " --resource WebServerHost --region ", {"Ref": "AWS::Region"}, "\n"
                ]]}}
            }
        },
        "WebServerLogGroup": {
            "Type": "AWS::Logs::LogGroup",
            "DeletionPolicy": "Retain",
            "UpdateReplacePolicy": "Retain",
            "Properties": {
                "RetentionInDays": 7
            }
        },
        "404MetricFilter": {
            "Type": "AWS::Logs::MetricFilter",
            "Properties": {
                "LogGroupName": {"Ref": "WebServerLogGroup"},
                "FilterPattern": "[ip, identity, user_id, timestamp, request, status_code = 404, size, ...]",
                "MetricTransformations": [
                    {
                        "MetricValue": "1",
                        "MetricNamespace": "test/404s",
                        "MetricName": "test404Count"
                    }
                ]
            }
        },
        "BytesTransferredMetricFilter": {
            "Type": "AWS::Logs::MetricFilter",
            "Properties": {
                "LogGroupName": {"Ref": "WebServerLogGroup"},
                "FilterPattern": "[ip, identity, user_id, timestamp, request, status_code, size, ...]",
                "MetricTransformations": [
                    {
                        "MetricValue": "$size",
                        "MetricNamespace": "test/BytesTransferred",
                        "MetricName": "testBytesTransferred"
                    }
                ]
            }
        },
        "404Alarm": {
            "Type": "AWS::CloudWatch::Alarm",
            "Properties": {
                "AlarmDescription": "The number of 404s is greater than 2 over 2 minutes",
                "MetricName": "test404Count",
                "Namespace": "test/404s",
                "Statistic": "Sum",
                "Period": "60",
                "EvaluationPeriods": "2",
                "Threshold": "2",
                "AlarmActions": [{"Ref": "AlarmNotificationTopic"}],
                "ComparisonOperator": "GreaterThanThreshold"
            }
        },
        "BandwidthAlarm": {
            "Type": "AWS::CloudWatch::Alarm",
            "Properties": {
                "AlarmDescription": "The average volume of traffic is greater 3500 KB over 10 minutes",
                "MetricName": "testBytesTransferred",
                "Namespace": "test/BytesTransferred",
                "Statistic": "Average",
                "Period": "300",
                "EvaluationPeriods": "2",
                "Threshold": "3500",
                "AlarmActions": [{"Ref": "AlarmNotificationTopic"}],
                "ComparisonOperator": "GreaterThanThreshold"
            }
        },
        "AlarmNotificationTopic": {
            "Type": "AWS::SNS::Topic",
            "Properties": {
                "Subscription": [{"Endpoint": {"Ref": "OperatorEmail"}, "Protocol": "email"}]
            }
        }
    },
    "Outputs": {
        "InstanceId": {
            "Description": "The instance ID of the web server",
            "Value": {"Ref": "WebServerHost"}
        },
        "WebsiteURL": {
            "Value": {"Fn::Sub": "http://${WebServerHost.PublicDnsName}"},
            "Description": "URL for the web server"
        },
        "PublicIP": {
            "Description": "Public IP address of the web server",
            "Value": {"Fn::GetAtt": ["WebServerHost","PublicIp"]
            }
        },
        "CloudWatchLogGroupName": {
            "Description": "The name of the CloudWatch log group",
            "Value": {"Ref": "WebServerLogGroup"}
        }
    }
}
```

### YAML
<a name="quickref-cloudwatchlogs-example.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Description: Sample template that sets up and configures CloudWatch Logs on Amazon Linux 2023 instance.
Parameters:
  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instances
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: must be the name of an existing EC2 KeyPair.
  SSHLocation:
    Description: The IP address range that can be used to SSH to the EC2 instances
    Type: String
    MinLength: '9'
    MaxLength: '18'
    Default: 0.0.0.0/0
    AllowedPattern: '(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})'
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
  OperatorEmail:
    Description: Email address to notify when CloudWatch alarms are triggered (404 errors or high bandwidth usage)
    Type: String
Resources:
  LogRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17		 	 	 
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: LogRolePolicy
          PolicyDocument:
            Version: 2012-10-17		 	 	 
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:PutLogEvents'
                  - 'logs:DescribeLogStreams'
                  - 'logs:DescribeLogGroups'
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                Resource: '*'
  LogRoleInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref LogRole
  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80 and SSH access via port 22
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref SSHLocation
  WebServerHost:
    Type: AWS::EC2::Instance
    Metadata:
      Comment: Install a simple PHP application on Amazon Linux 2023
      'AWS::CloudFormation::Init':
        config:
          packages:
            dnf:
              httpd: []
              php: []
              php-fpm: []
          files:
            /etc/amazon-cloudwatch-agent/amazon-cloudwatch-agent.json:
              content: !Sub |
                {
                  "logs": {
                    "logs_collected": {
                      "files": {
                        "collect_list": [
                          {
                            "file_path": "/var/log/httpd/access_log",
                            "log_group_name": "${WebServerLogGroup}",
                            "log_stream_name": "{instance_id}/apache.log",
                            "timestamp_format": "%d/%b/%Y:%H:%M:%S %z"
                          }
                        ]
                      }
                    }
                  }
                }
              mode: '000644'
              owner: root
              group: root
            /var/www/html/index.php:
              content: |
                <?php echo '<h1>AWS CloudFormation sample PHP application on Amazon Linux 2023</h1>';
                ?>
              mode: '000644'
              owner: apache
              group: apache
            /etc/cfn/cfn-hup.conf:
              content: !Sub |
                [main]
                stack=${AWS::StackId}
                region=${AWS::Region}
              mode: '000400'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:
              content: !Sub |
                [cfn-auto-reloader-hook]
                triggers=post.update
                path=Resources.WebServerHost.Metadata.AWS::CloudFormation::Init
                action=/opt/aws/bin/cfn-init -s ${AWS::StackId} -r WebServerHost --region ${AWS::Region}
                runas=root
          services:
            systemd:
              httpd:
                enabled: 'true'
                ensureRunning: 'true'
              php-fpm:
                enabled: 'true'
                ensureRunning: 'true'
    CreationPolicy:
      ResourceSignal:
        Timeout: PT5M
    Properties:
      ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64}}'
      KeyName: !Ref KeyName
      InstanceType: t3.micro
      SecurityGroupIds:
        - !Ref WebServerSecurityGroup
      IamInstanceProfile: !Ref LogRoleInstanceProfile
      UserData: !Base64
        Fn::Sub: |
          #!/bin/bash
          dnf update -y aws-cfn-bootstrap
          dnf install -y amazon-cloudwatch-agent
          /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerHost --region ${AWS::Region}
          
          # Verify Apache log directory exists and create if needed
          mkdir -p /var/log/httpd
          
          # Start CloudWatch agent
          /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/etc/amazon-cloudwatch-agent/amazon-cloudwatch-agent.json -s
          
          # Signal success
          /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerHost --region ${AWS::Region}
          echo "Done"
  WebServerLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    UpdateReplacePolicy: Retain
    Properties:
      RetentionInDays: 7
  404MetricFilter:
    Type: AWS::Logs::MetricFilter
    Properties:
      LogGroupName: !Ref WebServerLogGroup
      FilterPattern: >-
        [ip, identity, user_id, timestamp, request, status_code = 404, size, ...]
      MetricTransformations:
        - MetricValue: '1'
          MetricNamespace: test/404s
          MetricName: test404Count
  BytesTransferredMetricFilter:
    Type: AWS::Logs::MetricFilter
    Properties:
      LogGroupName: !Ref WebServerLogGroup
      FilterPattern: '[ip, identity, user_id, timestamp, request, status_code, size, ...]'
      MetricTransformations:
        - MetricValue: $size
          MetricNamespace: test/BytesTransferred
          MetricName: testBytesTransferred
  404Alarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: The number of 404s is greater than 2 over 2 minutes
      MetricName: test404Count
      Namespace: test/404s
      Statistic: Sum
      Period: '60'
      EvaluationPeriods: '2'
      Threshold: '2'
      AlarmActions:
        - !Ref AlarmNotificationTopic
      ComparisonOperator: GreaterThanThreshold
  BandwidthAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: The average volume of traffic is greater 3500 KB over 10 minutes
      MetricName: testBytesTransferred
      Namespace: test/BytesTransferred
      Statistic: Average
      Period: '300'
      EvaluationPeriods: '2'
      Threshold: '3500'
      AlarmActions:
        - !Ref AlarmNotificationTopic
      ComparisonOperator: GreaterThanThreshold
  AlarmNotificationTopic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: !Ref OperatorEmail
          Protocol: email
Outputs:
  InstanceId:
    Description: The instance ID of the web server
    Value: !Ref WebServerHost
  WebsiteURL:
    Value: !Sub 'http://${WebServerHost.PublicDnsName}'
    Description: URL for the web server
  PublicIP:
    Description: Public IP address of the web server
    Value: !GetAtt WebServerHost.PublicIp
  CloudWatchLogGroupName:
    Description: The name of the CloudWatch log group
    Value: !Ref WebServerLogGroup
```

## Windows 인스턴스에서 CloudWatch Logs로 로그 전송
<a name="quickref-cloudwatchlogs-example2"></a>

다음 템플릿은 Windows 2012R2 인스턴스에 대한 CloudWatch Logs를 구성합니다.

Windows의 CloudWatch Logs 에이전트(Windows 2012R2 및 Windows 2016 AMI의 SSM 에이전트)는 시작된 후에만 로그를 전송하므로 스타트업 전에 생성된 모든 로그는 전송되지 않습니다. 이를 해결하기 위해 템플릿은 로그를 작성하기 전에 에이전트가 시작되도록 합니다.
+ cfn-init `config`의 첫 번째 `configSets` 항목으로 에이전트 설정을 구성합니다.
+ `waitAfterCompletion`을 사용하여 에이전트를 시작하는 명령 뒤에 일시 중지를 삽입합니다.

### JSON
<a name="quickref-cloudwatchlogs-example2.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Sample template that sets up and configures CloudWatch Logs on Windows 2012R2 instance.",
    "Parameters": {
        "KeyPair": {
            "Description": "Name of an existing EC2 KeyPair to enable RDP access to the instances",
            "Type": "AWS::EC2::KeyPair::KeyName",
            "ConstraintDescription": "must be the name of an existing EC2 KeyPair."
        },
        "RDPLocation": {
            "Description": "The IP address range that can be used to RDP to the EC2 instances",
            "Type": "String",
            "MinLength": "9",
            "MaxLength": "18",
            "Default": "0.0.0.0/0",
            "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
            "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
        },
        "OperatorEmail": {
            "Description": "Email address to notify when CloudWatch alarms are triggered (404 errors)",
            "Type": "String"
        }
    },
    "Resources": {
        "WebServerSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": "Enable HTTP access via port 80 and RDP access via port 3389",
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": "80",
                        "ToPort": "80",
                        "CidrIp": "0.0.0.0/0"
                    },
                    {
                        "IpProtocol": "tcp",
                        "FromPort": "3389",
                        "ToPort": "3389",
                        "CidrIp": {"Ref": "RDPLocation"}
                    }
                ]
            }
        },
        "LogRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "ec2.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
                ],
                "Path": "/",
                "Policies": [
                    {
                        "PolicyName": "LogRolePolicy",
                        "PolicyDocument": {
                            "Version": "2012-10-17",		 	 	 
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "logs:Create*",
                                        "logs:PutLogEvents",
                                        "s3:GetObject"
                                    ],
                                    "Resource": [
                                        "arn:aws:logs:*:*:*",
                                        "arn:aws:s3:::*"
                                    ]
                                }
                            ]
                        }
                    }
                ]
            }
        },
        "LogRoleInstanceProfile": {
            "Type": "AWS::IAM::InstanceProfile",
            "Properties": {
                "Path": "/",
                "Roles": [{"Ref": "LogRole"}]
            }
        },
        "WebServerHost": {
            "Type": "AWS::EC2::Instance",
            "CreationPolicy": {
                "ResourceSignal": {
                    "Timeout": "PT15M"
                }
            },
            "Metadata": {
                "AWS::CloudFormation::Init": {
                    "configSets": {
                        "config": [
                            "00-ConfigureCWLogs",
                            "01-InstallWebServer",
                            "02-ConfigureApplication",
                            "03-Finalize"
                        ]
                    },
                    "00-ConfigureCWLogs": {
                        "files": {
                            "C:\\Program Files\\Amazon\\SSM\\Plugins\\awsCloudWatch\\AWS.EC2.Windows.CloudWatch.json": {
                                "content": {
                                    "EngineConfiguration": {
                                        "Components": [
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.EventLog.EventLogInputComponent,AWS.EC2.Windows.CloudWatch",
                                                "Id": "ApplicationEventLog",
                                                "Parameters": {
                                                    "Levels": "7",
                                                    "LogName": "Application"
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.EventLog.EventLogInputComponent,AWS.EC2.Windows.CloudWatch",
                                                "Id": "SystemEventLog",
                                                "Parameters": {
                                                    "Levels": "7",
                                                    "LogName": "System"
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.EventLog.EventLogInputComponent,AWS.EC2.Windows.CloudWatch",
                                                "Id": "SecurityEventLog",
                                                "Parameters": {
                                                    "Levels": "7",
                                                    "LogName": "Security"
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
                                                "Id": "EC2ConfigLog",
                                                "Parameters": {
                                                    "CultureName": "en-US",
                                                    "Encoding": "ASCII",
                                                    "Filter": "EC2ConfigLog.txt",
                                                    "LogDirectoryPath": "C:\\Program Files\\Amazon\\Ec2ConfigService\\Logs",
                                                    "TimeZoneKind": "UTC",
                                                    "TimestampFormat": "yyyy-MM-ddTHH:mm:ss.fffZ:"
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
                                                "Id": "CfnInitLog",
                                                "Parameters": {
                                                    "CultureName": "en-US",
                                                    "Encoding": "ASCII",
                                                    "Filter": "cfn-init.log",
                                                    "LogDirectoryPath": "C:\\cfn\\log",
                                                    "TimeZoneKind": "Local",
                                                    "TimestampFormat": "yyyy-MM-dd HH:mm:ss,fff"
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
                                                "Id": "IISLogs",
                                                "Parameters": {
                                                    "CultureName": "en-US",
                                                    "Encoding": "UTF-8",
                                                    "Filter": "",
                                                    "LineCount": "3",
                                                    "LogDirectoryPath": "C:\\inetpub\\logs\\LogFiles\\W3SVC1",
                                                    "TimeZoneKind": "UTC",
                                                    "TimestampFormat": "yyyy-MM-dd HH:mm:ss"
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.PerformanceCounterComponent.PerformanceCounterInputComponent,AWS.EC2.Windows.CloudWatch",
                                                "Id": "MemoryPerformanceCounter",
                                                "Parameters": {
                                                    "CategoryName": "Memory",
                                                    "CounterName": "Available MBytes",
                                                    "DimensionName": "",
                                                    "DimensionValue": "",
                                                    "InstanceName": "",
                                                    "MetricName": "Memory",
                                                    "Unit": "Megabytes"
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                                                "Id": "CloudWatchApplicationEventLog",
                                                "Parameters": {
                                                    "AccessKey": "",
                                                    "LogGroup": {"Ref": "LogGroup"},
                                                    "LogStream": "{instance_id}/ApplicationEventLog",
                                                    "Region": {"Ref": "AWS::Region"},
                                                    "SecretKey": ""
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                                                "Id": "CloudWatchSystemEventLog",
                                                "Parameters": {
                                                    "AccessKey": "",
                                                    "LogGroup": {"Ref": "LogGroup"},
                                                    "LogStream": "{instance_id}/SystemEventLog",
                                                    "Region": {"Ref": "AWS::Region"},
                                                    "SecretKey": ""
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                                                "Id": "CloudWatchSecurityEventLog",
                                                "Parameters": {
                                                    "AccessKey": "",
                                                    "LogGroup": {"Ref": "LogGroup"},
                                                    "LogStream": "{instance_id}/SecurityEventLog",
                                                    "Region": {"Ref": "AWS::Region"},
                                                    "SecretKey": ""
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                                                "Id": "CloudWatchEC2ConfigLog",
                                                "Parameters": {
                                                    "AccessKey": "",
                                                    "LogGroup": {"Ref": "LogGroup"},
                                                    "LogStream": "{instance_id}/EC2ConfigLog",
                                                    "Region": {"Ref": "AWS::Region"},
                                                    "SecretKey": ""
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                                                "Id": "CloudWatchCfnInitLog",
                                                "Parameters": {
                                                    "AccessKey": "",
                                                    "LogGroup": {"Ref": "LogGroup"},
                                                    "LogStream": "{instance_id}/CfnInitLog",
                                                    "Region": {"Ref": "AWS::Region"},
                                                    "SecretKey": ""
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                                                "Id": "CloudWatchIISLogs",
                                                "Parameters": {
                                                    "AccessKey": "",
                                                    "LogGroup": {"Ref": "LogGroup"},
                                                    "LogStream": "{instance_id}/IISLogs",
                                                    "Region": {"Ref": "AWS::Region"},
                                                    "SecretKey": ""
                                                }
                                            },
                                            {
                                                "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatch.CloudWatchOutputComponent,AWS.EC2.Windows.CloudWatch",
                                                "Id": "CloudWatch",
                                                "Parameters": {
                                                    "AccessKey": "",
                                                    "NameSpace": "Windows/Default",
                                                    "Region": {"Ref": "AWS::Region"},
                                                    "SecretKey": ""
                                                }
                                            }
                                        ],
                                        "Flows": {
                                            "Flows": [
                                                "ApplicationEventLog,CloudWatchApplicationEventLog",
                                                "SystemEventLog,CloudWatchSystemEventLog",
                                                "SecurityEventLog,CloudWatchSecurityEventLog",
                                                "EC2ConfigLog,CloudWatchEC2ConfigLog",
                                                "CfnInitLog,CloudWatchCfnInitLog",
                                                "IISLogs,CloudWatchIISLogs",
                                                "MemoryPerformanceCounter,CloudWatch"
                                            ]
                                        },
                                        "PollInterval": "00:00:05"
                                    },
                                    "IsEnabled": true
                                }
                            }
                        },
                        "commands": {
                            "0-enableSSM": {
                                "command": "powershell.exe -Command \"Set-Service -Name AmazonSSMAgent -StartupType Automatic\" ",
                                "waitAfterCompletion": "0"
                            },
                            "1-restartSSM": {
                                "command": "powershell.exe -Command \"Restart-Service AmazonSSMAgent \"",
                                "waitAfterCompletion": "30"
                            }
                        }
                    },
                    "01-InstallWebServer": {
                        "commands": {
                            "01_install_webserver": {
                                "command": "powershell.exe -Command \"Install-WindowsFeature Web-Server  -IncludeAllSubFeature\"",
                                "waitAfterCompletion": "0"
                            }
                        }
                    },
                    "02-ConfigureApplication": {
                        "files": {
                            "c:\\Inetpub\\wwwroot\\index.htm": {
                                "content": "<html> <head> <title>Test Application Page</title> </head> <body> <h1>Congratulations!! Your IIS server is configured.</h1> </body> </html>"
                            }
                        }
                    },
                    "03-Finalize": {
                        "commands": {
                            "00_signal_success": {
                                "command": {
                                    "Fn::Sub": "cfn-signal.exe -e 0 --resource WebServerHost --stack ${AWS::StackName} --region ${AWS::Region}"
                                },
                                "waitAfterCompletion": "0"
                            }
                        }
                    }
                }
            },
            "Properties": {
                "KeyName": {
                    "Ref": "KeyPair"
                },
                "ImageId": "{{resolve:ssm:/aws/service/ami-windows-latest/Windows_Server-2012-R2_RTM-English-64Bit-Base}}",
                "InstanceType": "t2.xlarge",
                "SecurityGroupIds": [{"Ref": "WebServerSecurityGroup"}],
                "IamInstanceProfile": {"Ref": "LogRoleInstanceProfile"},
                "UserData": {
                    "Fn::Base64": {
                        "Fn::Join": [
                            "",
                            [
                                "<script>\n",
                                "wmic product where \"description='Amazon SSM Agent' \" uninstall\n",
                                "wmic product where \"description='aws-cfn-bootstrap' \" uninstall \n",
                                "start /wait c:\\Windows\\system32\\msiexec /passive /qn /i https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-win64-latest.msi\n",
                                "powershell.exe -Command \"iwr https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/windows_amd64/AmazonSSMAgentSetup.exe  -UseBasicParsing -OutFile C:\\AmazonSSMAgentSetup.exe\"\n",
                                "start /wait C:\\AmazonSSMAgentSetup.exe /install /quiet\n",
                                "cfn-init.exe -v -c config -s ", {"Ref": "AWS::StackName"}, " --resource WebServerHost --region ", {"Ref": "AWS::Region"}, " \n",
                                "</script>\n"
                            ]
                        ]
                    }
                }
            }
        },
        "LogGroup": {
            "Type": "AWS::Logs::LogGroup",
            "Properties": {
                "RetentionInDays": 7
            }
        },
        "404MetricFilter": {
            "Type": "AWS::Logs::MetricFilter",
            "Properties": {
                "LogGroupName": {"Ref": "LogGroup"},
                "FilterPattern": "[timestamps, serverip, method, uri, query, port, dash, clientip, useragent, status_code = 404, ...]",
                "MetricTransformations": [
                    {
                        "MetricValue": "1",
                        "MetricNamespace": "test/404s",
                        "MetricName": "test404Count"
                    }
                ]
            }
        },
        "404Alarm": {
            "Type": "AWS::CloudWatch::Alarm",
            "Properties": {
                "AlarmDescription": "The number of 404s is greater than 2 over 2 minutes",
                "MetricName": "test404Count",
                "Namespace": "test/404s",
                "Statistic": "Sum",
                "Period": "60",
                "EvaluationPeriods": "2",
                "Threshold": "2",
                "AlarmActions": [{"Ref": "AlarmNotificationTopic"}],
                "ComparisonOperator": "GreaterThanThreshold"
            }
        },
        "AlarmNotificationTopic": {
            "Type": "AWS::SNS::Topic",
            "Properties": {
                "Subscription": [{"Endpoint": {"Ref": "OperatorEmail"}, "Protocol": "email"}]
            }
        }
    },
    "Outputs": {
        "InstanceId": {
            "Description": "The instance ID of the web server",
            "Value": {"Ref": "WebServerHost"}
        },
        "WebsiteURL": {
            "Value": {"Fn::Sub": "http://${WebServerHost.PublicDnsName}"},
            "Description": "URL for the web server"
        },
        "PublicIP": {
            "Description": "Public IP address of the web server",
            "Value": {"Fn::GetAtt": ["WebServerHost","PublicIp"]}
        },
        "CloudWatchLogGroupName": {
            "Description": "The name of the CloudWatch log group",
            "Value": {"Ref": "LogGroup"}
        }
    }
}
```

### YAML
<a name="quickref-cloudwatchlogs-example2.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Description: >-
  Sample template that sets up and configures CloudWatch Logs on Windows 2012R2 instance.
Parameters:
  KeyPair:
    Description: Name of an existing EC2 KeyPair to enable RDP access to the instances
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: must be the name of an existing EC2 KeyPair.
  RDPLocation:
    Description: The IP address range that can be used to RDP to the EC2 instances
    Type: String
    MinLength: '9'
    MaxLength: '18'
    Default: 0.0.0.0/0
    AllowedPattern: '(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})'
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
  OperatorEmail:
    Description: Email address to notify when CloudWatch alarms are triggered (404 errors)
    Type: String
Resources:
  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80 and RDP access via port 3389
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: '3389'
          ToPort: '3389'
          CidrIp: !Ref RDPLocation
  LogRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17		 	 	 
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore'
      Path: /
      Policies:
        - PolicyName: LogRolePolicy
          PolicyDocument:
            Version: 2012-10-17		 	 	 
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:Create*'
                  - 'logs:PutLogEvents'
                  - 's3:GetObject'
                Resource:
                  - 'arn:aws:logs:*:*:*'
                  - 'arn:aws:s3:::*'
  LogRoleInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref LogRole
  WebServerHost:
    Type: AWS::EC2::Instance
    CreationPolicy:
      ResourceSignal:
        Timeout: PT15M
    Metadata:
      'AWS::CloudFormation::Init':
        configSets:
          config:
            - 00-ConfigureCWLogs
            - 01-InstallWebServer
            - 02-ConfigureApplication
            - 03-Finalize
        00-ConfigureCWLogs:
          files:
            'C:\Program Files\Amazon\SSM\Plugins\awsCloudWatch\AWS.EC2.Windows.CloudWatch.json':
              content: !Sub |
                {
                  "EngineConfiguration": {
                      "Components": [
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.EventLog.EventLogInputComponent,AWS.EC2.Windows.CloudWatch",
                              "Id": "ApplicationEventLog",
                              "Parameters": {
                                  "Levels": "7",
                                  "LogName": "Application"
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.EventLog.EventLogInputComponent,AWS.EC2.Windows.CloudWatch",
                              "Id": "SystemEventLog",
                              "Parameters": {
                                  "Levels": "7",
                                  "LogName": "System"
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.EventLog.EventLogInputComponent,AWS.EC2.Windows.CloudWatch",
                              "Id": "SecurityEventLog",
                              "Parameters": {
                                  "Levels": "7",
                                  "LogName": "Security"
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
                              "Id": "EC2ConfigLog",
                              "Parameters": {
                                  "CultureName": "en-US",
                                  "Encoding": "ASCII",
                                  "Filter": "EC2ConfigLog.txt",
                                  "LogDirectoryPath": "C:\\Program Files\\Amazon\\Ec2ConfigService\\Logs",
                                  "TimeZoneKind": "UTC",
                                  "TimestampFormat": "yyyy-MM-ddTHH:mm:ss.fffZ:"
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
                              "Id": "CfnInitLog",
                              "Parameters": {
                                  "CultureName": "en-US",
                                  "Encoding": "ASCII",
                                  "Filter": "cfn-init.log",
                                  "LogDirectoryPath": "C:\\cfn\\log",
                                  "TimeZoneKind": "Local",
                                  "TimestampFormat": "yyyy-MM-dd HH:mm:ss,fff"
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
                              "Id": "IISLogs",
                              "Parameters": {
                                  "CultureName": "en-US",
                                  "Encoding": "UTF-8",
                                  "Filter": "",
                                  "LineCount": "3",
                                  "LogDirectoryPath": "C:\\inetpub\\logs\\LogFiles\\W3SVC1",
                                  "TimeZoneKind": "UTC",
                                  "TimestampFormat": "yyyy-MM-dd HH:mm:ss"
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.PerformanceCounterComponent.PerformanceCounterInputComponent,AWS.EC2.Windows.CloudWatch",
                              "Id": "MemoryPerformanceCounter",
                              "Parameters": {
                                  "CategoryName": "Memory",
                                  "CounterName": "Available MBytes",
                                  "DimensionName": "",
                                  "DimensionValue": "",
                                  "InstanceName": "",
                                  "MetricName": "Memory",
                                  "Unit": "Megabytes"
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                              "Id": "CloudWatchApplicationEventLog",
                              "Parameters": {
                                  "AccessKey": "",
                                  "LogGroup": "${LogGroup}",
                                  "LogStream": "{instance_id}/ApplicationEventLog",
                                  "Region": "${AWS::Region}",
                                  "SecretKey": ""
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                              "Id": "CloudWatchSystemEventLog",
                              "Parameters": {
                                  "AccessKey": "",
                                  "LogGroup": "${LogGroup}",
                                  "LogStream": "{instance_id}/SystemEventLog",
                                  "Region": "${AWS::Region}",
                                  "SecretKey": ""
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                              "Id": "CloudWatchSecurityEventLog",
                              "Parameters": {
                                  "AccessKey": "",
                                  "LogGroup": "${LogGroup}",
                                  "LogStream": "{instance_id}/SecurityEventLog",
                                  "Region": "${AWS::Region}",
                                  "SecretKey": ""
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                              "Id": "CloudWatchEC2ConfigLog",
                              "Parameters": {
                                  "AccessKey": "",
                                  "LogGroup": "${LogGroup}",
                                  "LogStream": "{instance_id}/EC2ConfigLog",
                                  "Region": "${AWS::Region}",
                                  "SecretKey": ""
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                              "Id": "CloudWatchCfnInitLog",
                              "Parameters": {
                                  "AccessKey": "",
                                  "LogGroup": "${LogGroup}",
                                  "LogStream": "{instance_id}/CfnInitLog",
                                  "Region": "${AWS::Region}",
                                  "SecretKey": ""
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                              "Id": "CloudWatchIISLogs",
                              "Parameters": {
                                  "AccessKey": "",
                                  "LogGroup": "${LogGroup}",
                                  "LogStream": "{instance_id}/IISLogs",
                                  "Region": "${AWS::Region}",
                                  "SecretKey": ""
                              }
                          },
                          {
                              "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatch.CloudWatchOutputComponent,AWS.EC2.Windows.CloudWatch",
                              "Id": "CloudWatch",
                              "Parameters": {
                                  "AccessKey": "",
                                  "NameSpace": "Windows/Default",
                                  "Region": "${AWS::Region}",
                                  "SecretKey": ""
                              }
                          }
                      ],
                      "Flows": {
                          "Flows": [
                              "ApplicationEventLog,CloudWatchApplicationEventLog",
                              "SystemEventLog,CloudWatchSystemEventLog",
                              "SecurityEventLog,CloudWatchSecurityEventLog",
                              "EC2ConfigLog,CloudWatchEC2ConfigLog",
                              "CfnInitLog,CloudWatchCfnInitLog",
                              "IISLogs,CloudWatchIISLogs",
                              "MemoryPerformanceCounter,CloudWatch"
                          ]
                      },
                      "PollInterval": "00:00:05"
                  },
                  "IsEnabled": true
                }
          commands:
            0-enableSSM:
              command: >-
                powershell.exe -Command "Set-Service -Name AmazonSSMAgent
                -StartupType Automatic" 
              waitAfterCompletion: '0'
            1-restartSSM:
              command: powershell.exe -Command "Restart-Service AmazonSSMAgent "
              waitAfterCompletion: '30'
        01-InstallWebServer:
          commands:
            01_install_webserver:
              command: >-
                powershell.exe -Command "Install-WindowsFeature Web-Server 
                -IncludeAllSubFeature"
              waitAfterCompletion: '0'
        02-ConfigureApplication:
          files:
            'c:\Inetpub\wwwroot\index.htm':
              content: >-
                <html> <head> <title>Test Application Page</title> </head>
                <body> <h1>Congratulations !! Your IIS server is
                configured.</h1> </body> </html>
        03-Finalize:
          commands:
            00_signal_success:
              command: !Sub >-
                cfn-signal.exe -e 0 --resource WebServerHost --stack
                ${AWS::StackName} --region ${AWS::Region}
              waitAfterCompletion: '0'
    Properties:
      KeyName: !Ref KeyPair
      ImageId: "{{resolve:ssm:/aws/service/ami-windows-latest/Windows_Server-2012-R2_RTM-English-64Bit-Base}}"
      InstanceType: t2.xlarge
      SecurityGroupIds:
        - !Ref WebServerSecurityGroup
      IamInstanceProfile: !Ref LogRoleInstanceProfile
      UserData: !Base64 
        'Fn::Sub': >
          <script>

          wmic product where "description='Amazon SSM Agent' " uninstall

          wmic product where "description='aws-cfn-bootstrap' " uninstall 

          start /wait c:\\Windows\\system32\\msiexec /passive /qn /i
          https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-win64-latest.msi

          powershell.exe -Command "iwr
          https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/windows_amd64/AmazonSSMAgentSetup.exe 
          -UseBasicParsing -OutFile C:\\AmazonSSMAgentSetup.exe"

          start /wait C:\\AmazonSSMAgentSetup.exe /install /quiet

          cfn-init.exe -v -c config -s ${AWS::StackName} --resource
          WebServerHost --region ${AWS::Region} 

          </script>
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      RetentionInDays: 7
  404MetricFilter:
    Type: AWS::Logs::MetricFilter
    Properties:
      LogGroupName: !Ref LogGroup
      FilterPattern: >-
        [timestamps, serverip, method, uri, query, port, dash, clientip,
        useragent, status_code = 404, ...]
      MetricTransformations:
        - MetricValue: '1'
          MetricNamespace: test/404s
          MetricName: test404Count
  404Alarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription: The number of 404s is greater than 2 over 2 minutes
      MetricName: test404Count
      Namespace: test/404s
      Statistic: Sum
      Period: '60'
      EvaluationPeriods: '2'
      Threshold: '2'
      AlarmActions:
        - !Ref AlarmNotificationTopic
      ComparisonOperator: GreaterThanThreshold
  AlarmNotificationTopic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: !Ref OperatorEmail
          Protocol: email
Outputs:
  InstanceId:
    Description: The instance ID of the web server
    Value: !Ref WebServerHost
  WebsiteURL:
    Value: !Sub 'http://${WebServerHost.PublicDnsName}'
    Description: URL for the web server
  PublicIP:
    Description: Public IP address of the web server
    Value: !GetAtt 
      - WebServerHost
      - PublicIp
  CloudWatchLogGroupName:
    Description: The name of the CloudWatch log group
    Value: !Ref LogGroup
```

## 다음 사항도 참조하세요.
<a name="w2aac11c41c35c11"></a>

CloudWatch Logs 리소스에 대한 자세한 내용을 알아보려면 [AWS::Logs::LogGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-logs-loggroup.html) 또는 [AWS::Logs::MetricFilter](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-logs-metricfilter.html)를 참조하세요.

# Amazon DynamoDB 템플릿 코드 조각
<a name="quickref-dynamodb"></a>

**Topics**
+ [Amazon DynamoDB 테이블을 통한 Application Auto Scaling](#quickref-dynamodb-application-autoscaling)
+ [다음 사항도 참조하세요.](#w2aac11c41c39b7)

## Amazon DynamoDB 테이블을 통한 Application Auto Scaling
<a name="quickref-dynamodb-application-autoscaling"></a>

이 예에서는 `AWS::DynamoDB::Table` 리소스에 대해 Application Auto Scaling을 설정합니다. 이 템플릿은 테이블에 대한 `TargetTrackingScaling` 처리량을 확장하는 `WriteCapacityUnits` 조정 정책을 정의합니다.

### JSON
<a name="quickref-dynamodb-example.json"></a>

```
{
    "Resources": {
        "DDBTable": {
            "Type": "AWS::DynamoDB::Table",
            "Properties": {
                "AttributeDefinitions": [
                    {
                        "AttributeName": "ArtistId",
                        "AttributeType": "S"
                    },
                    {
                        "AttributeName": "Concert",
                        "AttributeType": "S"
                    },
                    {
                        "AttributeName": "TicketSales",
                        "AttributeType": "S"
                    }
                ],
                "KeySchema": [
                    {
                        "AttributeName": "ArtistId",
                        "KeyType": "HASH"
                    },
                    {
                        "AttributeName": "Concert",
                        "KeyType": "RANGE"
                    }
                ],
                "GlobalSecondaryIndexes": [
                    {
                        "IndexName": "GSI",
                        "KeySchema": [
                            {
                                "AttributeName": "TicketSales",
                                "KeyType": "HASH"
                            }
                        ],
                        "Projection": {
                            "ProjectionType": "KEYS_ONLY"
                        },
                        "ProvisionedThroughput": {
                            "ReadCapacityUnits": 5,
                            "WriteCapacityUnits": 5
                        }
                    }
                ],
                "ProvisionedThroughput": {
                    "ReadCapacityUnits": 5,
                    "WriteCapacityUnits": 5
                }
            }
        },
        "WriteCapacityScalableTarget": {
            "Type": "AWS::ApplicationAutoScaling::ScalableTarget",
            "Properties": {
                "MaxCapacity": 15,
                "MinCapacity": 5,
                "ResourceId": {
                    "Fn::Join": [
                        "/",
                        [
                            "table",
                            {
                                "Ref": "DDBTable"
                            }
                        ]
                    ]
                },
                "RoleARN" : { "Fn::Sub" : "arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable" },
                "ScalableDimension": "dynamodb:table:WriteCapacityUnits",
                "ServiceNamespace": "dynamodb"
            }
        },
        "WriteScalingPolicy": {
            "Type": "AWS::ApplicationAutoScaling::ScalingPolicy",
            "Properties": {
                "PolicyName": "WriteAutoScalingPolicy",
                "PolicyType": "TargetTrackingScaling",
                "ScalingTargetId": {
                    "Ref": "WriteCapacityScalableTarget"
                },
                "TargetTrackingScalingPolicyConfiguration": {
                    "TargetValue": 50,
                    "ScaleInCooldown": 60,
                    "ScaleOutCooldown": 60,
                    "PredefinedMetricSpecification": {
                        "PredefinedMetricType": "DynamoDBWriteCapacityUtilization"
                    }
                }
            }
        }
    }
}
```

### YAML
<a name="quickref-dynamodb-example.yaml"></a>

```
Resources:
  DDBTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: "ArtistId"
          AttributeType: "S"
        - AttributeName: "Concert"
          AttributeType: "S"
        - AttributeName: "TicketSales"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "ArtistId"
          KeyType: "HASH"
        - AttributeName: "Concert"
          KeyType: "RANGE"
      GlobalSecondaryIndexes:
        - IndexName: "GSI"
          KeySchema:
            - AttributeName: "TicketSales"
              KeyType: "HASH"
          Projection:
            ProjectionType: "KEYS_ONLY"
          ProvisionedThroughput:
            ReadCapacityUnits: 5
            WriteCapacityUnits: 5
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
  WriteCapacityScalableTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MaxCapacity: 15
      MinCapacity: 5
      ResourceId: !Join
        - /
        - - table
          - !Ref DDBTable
      RoleARN:
        Fn::Sub: 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable'
      ScalableDimension: dynamodb:table:WriteCapacityUnits
      ServiceNamespace: dynamodb
  WriteScalingPolicy:
    Type: AWS::ApplicationAutoScaling::ScalingPolicy
    Properties:
      PolicyName: WriteAutoScalingPolicy
      PolicyType: TargetTrackingScaling
      ScalingTargetId: !Ref WriteCapacityScalableTarget
      TargetTrackingScalingPolicyConfiguration:
        TargetValue: 50.0
        ScaleInCooldown: 60
        ScaleOutCooldown: 60
        PredefinedMetricSpecification:
          PredefinedMetricType: DynamoDBWriteCapacityUtilization
```

## 다음 사항도 참조하세요.
<a name="w2aac11c41c39b7"></a>

자세한 내용은 AWS 데이터베이스 블로그의 [CloudFormation을 사용하여 DynamoDB 테이블 및 인덱스에 대한 Auto Scaling을 구성하는 방법](https://aws.amazon.com/blogs/database/how-to-use-aws-cloudformation-to-configure-auto-scaling-for-amazon-dynamodb-tables-and-indexes/) 게시물을 참조하세요.

DynamoDB 리소스에 대한 자세한 내용은 [AWS::DynamoDB::Table](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-dynamodb-table.html)을 참조하십시오.

# Amazon EC2 CloudFormation 템플릿 코드 조각
<a name="quickref-ec2"></a>

Amazon EC2는 AWS 클라우드에서 확장 가능한 컴퓨팅 용량을 제공합니다. Amazon EC2를 사용하여 원하는 수의 가상 서버를 빌드하고 보안 및 네트워킹을 구성하며 스토리지를 관리할 수 있습니다. 인스턴스라고 하는 이러한 가상 서버는 다양한 운영 체제와 애플리케이션을 실행할 수 있으며 특정 요구 사항에 맞게 사용자 지정할 수 있습니다. Amazon EC2를 사용하면 손쉽게 규모를 확장 또는 축소하여 요구 사항 변경이나 사용량 급증에 대처할 수 있습니다.

CloudFormation 템플릿을 사용하여 Amazon EC2 인스턴스를 인프라의 일부로 정의하고 프로비저닝할 수 있습니다. 템플릿을 사용하면 반복 가능하고 일관된 방식으로 Amazon EC2 리소스 배포를 쉽게 관리하고 자동화할 수 있습니다.

다음 예제 템플릿 코드 조각은 Amazon EC2용 CloudFormation 리소스 또는 구성 요소를 설명합니다. 이러한 코드 조각은 템플릿에 통합되도록 설계되었으며 독립적으로 실행되도록 설계되지 않았습니다.

**Topics**
+ [EC2 인스턴스 구성](quickref-ec2-instance-config.md)
+ [시작 템플릿 생성](quickref-ec2-launch-templates.md)
+ [보안 그룹 관리](quickref-ec2-sg.md)
+ [탄력적 IP 할당](quickref-ec2-elastic-ip.md)
+ [VPC 리소스 구성](quickref-ec2-vpc.md)

# CloudFormation을 사용하여 Amazon EC2 인스턴스 구성
<a name="quickref-ec2-instance-config"></a>

다음 코드 조각은 CloudFormation을 사용하여 Amazon EC2 인스턴스를 구성하는 방법을 보여줍니다.

**Topics**
+ [일반적인 Amazon EC2 구성](#quickref-ec2-instance-config-general)
+ [인스턴스의 블록 디바이스 매핑 지정](#scenario-ec2-bdm)

## 일반적인 Amazon EC2 구성
<a name="quickref-ec2-instance-config-general"></a>

다음 코드 조각은 CloudFormation을 사용하는 Amazon EC2 인스턴스의 일반적인 구성을 보여줍니다.

**Topics**
+ [지정된 가용 영역에서 Amazon EC2 인스턴스 생성](#scenario-ec2-instance)
+ [EBS 볼륨 및 사용자 데이터를 사용하여 태그가 지정된 Amazon EC2 인스턴스 구성](#scenario-ec2-instance-with-vol-and-tags)
+ [Amazon EC2 인스턴스 시작을 위한 사용자 데이터에 DynamoDB 테이블 이름 정의](#scenario-ec2-with-sdb-domain)
+ [`DeletionPolicy`을(를) 사용하여 Amazon EBS 볼륨 생성](#scenario-ec2-volume)

### 지정된 가용 영역에서 Amazon EC2 인스턴스 생성
<a name="scenario-ec2-instance"></a>

다음 코드 조각은 [AWS::EC2::Instance](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html) 리소스를 사용하여 지정된 가용 영역에서 Amazon EC2 인스턴스를 생성합니다. 가용 영역의 코드는 리전 코드와 문자 식별자를 조합한 것입니다. 단일 가용 영역에서 인스턴스를 시작할 수 있습니다.

#### JSON
<a name="quickref-ec2-example-6.json"></a>

```
1. "Ec2Instance": {
2.     "Type": "AWS::EC2::Instance",
3.     "Properties": {
4.         "AvailabilityZone": "aa-example-1a",
5.         "ImageId": "ami-1234567890abcdef0"
6.     }
7. }
```

#### YAML
<a name="quickref-ec2-example-6.yaml"></a>

```
1. Ec2Instance:
2.   Type: AWS::EC2::Instance
3.   Properties:
4.     AvailabilityZone: aa-example-1a
5.     ImageId: ami-1234567890abcdef0
```

### EBS 볼륨 및 사용자 데이터를 사용하여 태그가 지정된 Amazon EC2 인스턴스 구성
<a name="scenario-ec2-instance-with-vol-and-tags"></a>

다음 코드 조각은 태그, EBS 볼륨 및 사용자 데이터를 사용하여 Amazon EC2 인스턴스를 생성합니다. [AWS::EC2::Instance](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html) 리소스를 사용합니다. 동일한 템플릿에서 [AWS::EC2::SecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) 리소스, [AWS::SNS::Topic](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-topic.html) 리소스 및 [AWS::EC2::Volume](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-volume.html) 리소스를 정의해야 합니다. `KeyName`은(는) 템플릿의 `Parameters` 섹션에서 정의해야 합니다.

태그를 사용하면 용도, 소유자 또는 환경 등 원하는 기준에 따라 AWS 리소스를 분류할 수 있습니다. 사용자 데이터를 사용하면 시작 중에 인스턴스에 사용자 지정 스크립트 또는 데이터를 프로비저닝할 수 있습니다. 이 데이터는 초기화 중에 인스턴스에 대한 작업 자동화, 소프트웨어 구성, 패키지 설치 및 기타 작업을 용이하게 합니다.

리소스 태그 지정에 대한 자세한 내용은 *Amazon EC2 사용 설명서*의 [Amazon EC2 리소스 태깅](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html)을 참조하세요.

사용자 데이터에 대한 자세한 내용은 *Amazon EC2 사용 설명서*의 [인스턴스 메타데이터를 사용하여 EC2 인스턴스를 관리합니다](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)를 참조하세요.

#### JSON
<a name="quickref-ec2-example-7.json"></a>

```
 1. "Ec2Instance": {
 2.   "Type": "AWS::EC2::Instance",
 3.   "Properties": {
 4.     "KeyName": { "Ref": "KeyName" },
 5.     "SecurityGroups": [ { "Ref": "Ec2SecurityGroup" } ],
 6.     "UserData": {
 7.       "Fn::Base64": {
 8.         "Fn::Join": [ ":", [
 9.             "PORT=80",
10.             "TOPIC=",
11.             { "Ref": "MySNSTopic" }
12.           ]
13.         ]
14.       }
15.     },
16.     "InstanceType": "aa.size",
17.     "AvailabilityZone": "aa-example-1a",
18.     "ImageId": "ami-1234567890abcdef0",
19.     "Volumes": [
20.       {
21.         "VolumeId": { "Ref": "MyVolumeResource" },
22.         "Device": "/dev/sdk"
23.       }
24.     ],
25.     "Tags": [ { "Key": "Name", "Value": "MyTag" } ]
26.   }
27. }
```

#### YAML
<a name="quickref-ec2-example-7.yaml"></a>

```
 1. Ec2Instance:
 2.   Type: AWS::EC2::Instance
 3.   Properties:
 4.     KeyName: !Ref KeyName
 5.     SecurityGroups:
 6.       - !Ref Ec2SecurityGroup
 7.     UserData:
 8.       Fn::Base64:
 9.         Fn::Join:
10.           - ":"
11.           - - "PORT=80"
12.             - "TOPIC="
13.             - !Ref MySNSTopic
14.     InstanceType: aa.size
15.     AvailabilityZone: aa-example-1a
16.     ImageId: ami-1234567890abcdef0
17.     Volumes:
18.       - VolumeId: !Ref MyVolumeResource
19.         Device: "/dev/sdk"
20.     Tags:
21.       - Key: Name
22.         Value: MyTag
```

### Amazon EC2 인스턴스 시작을 위한 사용자 데이터에 DynamoDB 테이블 이름 정의
<a name="scenario-ec2-with-sdb-domain"></a>

다음 코드 조각은 Amazon EC2 인스턴스를 생성하고 시작 시 인스턴스에 전달할 DynamoDB 테이블 이름을 사용자 데이터에 정의합니다. [AWS::EC2::Instance](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html) 리소스를 사용합니다. 사용자 데이터에 파라미터 또는 동적 값을 정의하여 시작 시 EC2 인스턴스를 전달할 수 있습니다.

사용자 데이터에 대한 자세한 내용은 *Amazon EC2 사용 설명서*의 [인스턴스 메타데이터를 사용하여 EC2 인스턴스를 관리합니다](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)를 참조하세요.

#### JSON
<a name="quickref-ec2-example-8.json"></a>

```
 1. "Ec2Instance": {
 2.     "Type": "AWS::EC2::Instance",
 3.     "Properties": {
 4.         "UserData": {
 5.             "Fn::Base64": {
 6.                 "Fn::Join": [
 7.                     "",
 8.                     [
 9.                         "TableName=",
10.                         {
11.                             "Ref": "DynamoDBTableName"
12.                         }
13.                     ]
14.                 ]
15.             }
16.         },
17.         "AvailabilityZone": "aa-example-1a",
18.         "ImageId": "ami-1234567890abcdef0"
19.     }
20. }
```

#### YAML
<a name="quickref-ec2-example-8.yaml"></a>

```
 1. Ec2Instance:
 2.   Type: AWS::EC2::Instance
 3.   Properties:
 4.     UserData:
 5.       Fn::Base64:
 6.         Fn::Join:
 7.           - ''
 8.           - - 'TableName='
 9.             - Ref: DynamoDBTableName
10.     AvailabilityZone: aa-example-1a
11.     ImageId: ami-1234567890abcdef0
```

### `DeletionPolicy`을(를) 사용하여 Amazon EBS 볼륨 생성
<a name="scenario-ec2-volume"></a>

다음 코드 조각은 Amazon EC2 [AWS::EC2::Volume](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-volume.html) 리소스를 사용하여 Amazon EBS 볼륨을 생성합니다. `Size` 또는 `SnapshotID` 속성을 사용하여 볼륨을 정의할 수 있지만 둘 다 사용할 수는 없습니다. 스택을 삭제할 때 볼륨의 스냅샷을 생성하도록 `DeletionPolicy` 속성이 설정됩니다.

`DeletionPolicy` 속성에 대한 자세한 내용은 [DeletionPolicy 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-deletionpolicy.html)을 참조하세요.

Amazon EBS 볼륨 생성에 대한 자세한 내용은 [Amazon EBS 볼륨 생성](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-creating-volume.html)을 참조하세요.

#### JSON
<a name="quickref-ec2-example-13.json"></a>

이 코드 조각은 지정된 **크기**로 Amazon EBS 볼륨을 생성합니다. 크기는 10으로 설정되어 있지만 필요에 따라 조정할 수 있습니다. [AWS::EC2::Volume](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-volume.html) 리소스를 사용하면 크기 또는 스냅샷 ID를 지정할 수 있지만 둘 다 지정할 수는 없습니다.

```
 1. "MyEBSVolume": {
 2.     "Type": "AWS::EC2::Volume",
 3.     "Properties": {
 4.         "Size": "10",
 5.         "AvailabilityZone": {
 6.             "Ref": "AvailabilityZone"
 7.         }
 8.     },
 9.     "DeletionPolicy": "Snapshot"
10. }
```

이 코드 조각은 제공된 **스냅샷 ID**를 사용하여 Amazon EBS 볼륨을 생성합니다. [AWS::EC2::Volume](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-volume.html) 리소스를 사용하면 크기 또는 스냅샷 ID를 지정할 수 있지만 둘 다 지정할 수는 없습니다.

```
 1. "MyEBSVolume": {
 2.     "Type": "AWS::EC2::Volume",
 3.     "Properties": {
 4.         "SnapshotId" : "snap-1234567890abcdef0",
 5.         "AvailabilityZone": {
 6.             "Ref": "AvailabilityZone"
 7.         }
 8.     },
 9.     "DeletionPolicy": "Snapshot"
10. }
```

#### YAML
<a name="quickref-ec2-example-13.yaml"></a>

이 코드 조각은 지정된 **크기**로 Amazon EBS 볼륨을 생성합니다. 크기는 10으로 설정되어 있지만 필요에 따라 조정할 수 있습니다. [AWS::EC2::Volume](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-volume.html) 리소스를 사용하면 크기 또는 스냅샷 ID를 지정할 수 있지만 둘 다 지정할 수는 없습니다.

```
1. MyEBSVolume:
2.   Type: AWS::EC2::Volume
3.   Properties:
4.     Size: 10
5.     AvailabilityZone:
6.       Ref: AvailabilityZone
7.   DeletionPolicy: Snapshot
```

이 코드 조각은 제공된 **스냅샷 ID**를 사용하여 Amazon EBS 볼륨을 생성합니다. [AWS::EC2::Volume](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-volume.html) 리소스를 사용하면 크기 또는 스냅샷 ID를 지정할 수 있지만 둘 다 지정할 수는 없습니다.

```
1. MyEBSVolume:
2.   Type: AWS::EC2::Volume
3.   Properties:
4.     SnapshotId: snap-1234567890abcdef0
5.     AvailabilityZone:
6.       Ref: AvailabilityZone
7.   DeletionPolicy: Snapshot
```

## 인스턴스의 블록 디바이스 매핑 지정
<a name="scenario-ec2-bdm"></a>

블록 디바이스 매핑은 인스턴스에 연결할 블록 디바이스(인스턴스 스토어 볼륨 및 EBS 볼륨 포함)를 정의합니다. AMI를 생성할 때 블록 디바이스 매핑을 지정하면 AMI에서 실행되는 모든 인스턴스가 해당 매핑을 사용할 수 있습니다. 또는 인스턴스를 실행할 때 블록 디바이스 매핑을 지정하여 해당 매핑이 인스턴스가 실행된 AMI에서 지정된 매핑을 재정의하도록 할 수 있습니다.

다음 템플릿 코드 조각을 사용하면 [AWS::EC2::Instance](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html) 리소스의 `BlockDeviceMappings` 속성을 사용하여 EBS 또는 인스턴스 스토어 볼륨의 블록 디바이스 매핑을 지정할 수 있습니다.

블록 디바이스 매핑에 대한 자세한 내용은 *Amazon EC2 사용 설명서*의 [Amazon EC2 인스턴스의 볼륨에 대한 블록 디바이스 매핑](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html)을 참조하세요.

**Topics**
+ [두 EBS 볼륨의 블록 디바이스 매핑 지정](#w2aac11c41c43c13b9c11)
+ [인스턴스 스토어 볼륨의 인스턴스 블록 디바이스 매핑 지정](#w2aac11c41c43c13b9c13)

### 두 EBS 볼륨의 블록 디바이스 매핑 지정
<a name="w2aac11c41c43c13b9c11"></a>

#### JSON
<a name="quickref-ec2-example-1.json"></a>

```
"Ec2Instance": {
    "Type": "AWS::EC2::Instance",
    "Properties": {
      "ImageId": "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}",
      "KeyName": { "Ref": "KeyName" },
      "InstanceType": { "Ref": "InstanceType" },
      "SecurityGroups": [{ "Ref": "Ec2SecurityGroup" }],
      "BlockDeviceMappings": [
        {
          "DeviceName": "/dev/sda1",
          "Ebs": { "VolumeSize": "50" }
        },
        {
          "DeviceName": "/dev/sdm",
          "Ebs": { "VolumeSize": "100" }
        }
      ]
    }
  }
}
```

#### YAML
<a name="quickref-ec2-example-1.yaml"></a>

```
EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      KeyName: !Ref KeyName
      InstanceType: !Ref InstanceType
      SecurityGroups:
        - !Ref Ec2SecurityGroup
      BlockDeviceMappings:
        -
          DeviceName: /dev/sda1
          Ebs:
            VolumeSize: 50
        -
          DeviceName: /dev/sdm
          Ebs:
            VolumeSize: 100
```

### 인스턴스 스토어 볼륨의 인스턴스 블록 디바이스 매핑 지정
<a name="w2aac11c41c43c13b9c13"></a>

#### JSON
<a name="quickref-ec2-example-2.json"></a>

```
"Ec2Instance" : {
  "Type" : "AWS::EC2::Instance", 
  "Properties" : {
    "ImageId" : "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}",
    "KeyName" : { "Ref" : "KeyName" },
    "InstanceType": { "Ref": "InstanceType" },
    "SecurityGroups" : [{ "Ref" : "Ec2SecurityGroup" }],
    "BlockDeviceMappings" : [
      {
        "DeviceName"  : "/dev/sdc",
        "VirtualName" : "ephemeral0"
      }
    ]
  }
}
```

#### YAML
<a name="quickref-ec2-example-2.yaml"></a>

```
EC2Instance:
  Type: AWS::EC2::Instance
  Properties:
    ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
    KeyName: !Ref KeyName
    InstanceType: !Ref InstanceType
    SecurityGroups:
      - !Ref Ec2SecurityGroup
    BlockDeviceMappings:
      - DeviceName: /dev/sdc
        VirtualName: ephemeral0
```

# CloudFormation을 사용하여 시작 템플릿 생성
<a name="quickref-ec2-launch-templates"></a>

이 섹션에서는 CloudFormation을 사용하여 Amazon EC2 시작 템플릿을 생성하는 예를 제공합니다. 시작 템플릿을 사용하면 AWS 내에서 Amazon EC2 인스턴스를 구성하고 프로비저닝하기 위한 템플릿을 생성할 수 있습니다. 시작 템플릿을 사용하면 인스턴스를 시작할 때마다 지정할 필요가 없도록 시작 파라미터를 저장할 수 있습니다. 더 많은 예는 `AWS::EC2::LaunchTemplate` 리소스의 [예](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html#aws-resource-ec2-launchtemplate--examples) 섹션을 참조하세요.

시작 템플릿에 대한 자세한 내용은 *Amazon EC2 사용 설명서*의 [Amazon EC2 시작 템플릿에 인스턴스 시작 파라미터 저장](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-launch-templates.html)을 참조하세요.

Auto Scaling 그룹에 사용할 시작 템플릿을 생성하는 방법에 대한 자세한 내용은 *Amazon EC2 Auto Scaling 사용 설명서*의 [Auto Scaling 시작 템플릿](https://docs.aws.amazon.com/autoscaling/ec2/userguide/launch-templates.html)을 참조하세요.

**Topics**
+ [보안 그룹, 태그, 사용자 데이터와 IAM 역할을 지정하는 시작 템플릿 생성](#scenario-as-launch-template)

## 보안 그룹, 태그, 사용자 데이터와 IAM 역할을 지정하는 시작 템플릿 생성
<a name="scenario-as-launch-template"></a>

이 코드 조각은 인스턴스를 시작하기 위한 구성 정보를 포함하는 [AWS::EC2::LaunchTemplate](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html) 리소스를 보여줍니다. `ImageId`, `InstanceType`, `SecurityGroups`, `UserData` 및 `TagSpecifications` 속성의 값을 지정합니다. `SecurityGroups` 속성은 기존 EC2 보안 그룹과 새 보안 그룹을 지정합니다. `Ref` 함수는 스택 템플릿의 다른 곳에 선언된 [AWS::EC2::SecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) 리소스 `myNewEC2SecurityGroup`의 ID를 가져옵니다.

시작 템플릿에는 사용자 정의 사용자 데이터에 대한 부분이 포함되어 있습니다. 이 섹션에서 인스턴스가 시작될 때 실행되는 구성 태스크 및 스크립트를 전달할 수 있습니다. 이 예제에서 사용자 데이터는 AWS Systems Manager Agent를 설치하고 시작합니다.

시작 템플릿에는 인스턴스에서 실행되는 애플리케이션이 사용자를 대신하여 작업을 수행할 수 있도록 하는 IAM 역할도 포함되어 있습니다. 이 예제는 `IamInstanceProfile` 속성을 사용하여 IAM 역할을 지정하는 시작 템플릿에 대한 [AWS::IAM::Role](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-role.html) 리소스를 보여줍니다. `Ref` 함수는 [AWS::IAM::InstanceProfile](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-instanceprofile.html) 리소스 `myInstanceProfile`의 이름을 가져옵니다. IAM 역할의 권한을 구성하려면 `ManagedPolicyArns` 속성 값을 지정합니다.

### JSON
<a name="quickref-launch-template-example-1.json"></a>

```
 1. {
 2.   "Resources":{
 3.     "myLaunchTemplate":{
 4.       "Type":"AWS::EC2::LaunchTemplate",
 5.       "Properties":{
 6.         "LaunchTemplateName":{ "Fn::Sub": "${AWS::StackName}-launch-template" },
 7.         "LaunchTemplateData":{
 8.           "ImageId":"ami-02354e95b3example",
 9.           "InstanceType":"t3.micro",
10.           "IamInstanceProfile":{
11.             "Name":{
12.               "Ref":"myInstanceProfile"
13.             }
14.           },
15.           "SecurityGroupIds":[
16.             {
17.               "Ref":"myNewEC2SecurityGroup"
18.             },
19.             "sg-083cd3bfb8example"
20.           ],
21.           "UserData":{
22.             "Fn::Base64":{
23.               "Fn::Join": [
24.                 "", [
25.                   "#!/bin/bash\n",
26.                   "cd /tmp\n",
27.                   "yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm\n",
28.                   "systemctl enable amazon-ssm-agent\n",
29.                   "systemctl start amazon-ssm-agent\n"
30.                 ]
31.               ]
32.             }
33.           },
34.           "TagSpecifications":[
35.             {
36.               "ResourceType":"instance",
37.               "Tags":[
38.                 {
39.                   "Key":"environment",
40.                   "Value":"development"
41.                 }
42.               ]
43.             },
44.             {
45.               "ResourceType":"volume",
46.               "Tags":[
47.                 {
48.                   "Key":"environment",
49.                   "Value":"development"
50.                 }
51.               ]
52.             }
53.           ]
54.         }
55.       }
56.     },
57.     "myInstanceRole":{
58.       "Type":"AWS::IAM::Role",
59.       "Properties":{
60.         "RoleName":"InstanceRole",
61.         "AssumeRolePolicyDocument":{
62.           "Version": "2012-10-17",		 	 	 
63.           "Statement":[
64.             {
65.               "Effect":"Allow",
66.               "Principal":{
67.                 "Service":[
68.                   "ec2.amazonaws.com"
69.                 ]
70.               },
71.               "Action":[
72.                 "sts:AssumeRole"
73.               ]
74.             }
75.           ]
76.         },
77.         "ManagedPolicyArns":[
78.           "arn:aws:iam::aws:policy/myCustomerManagedPolicy"
79.         ]
80.       }
81.     },
82.     "myInstanceProfile":{
83.       "Type":"AWS::IAM::InstanceProfile",
84.       "Properties":{
85.         "Path":"/",
86.         "Roles":[
87.           {
88.             "Ref":"myInstanceRole"
89.           }
90.         ]
91.       }
92.     }
93.   }
94. }
```

### YAML
<a name="quickref-launch-template-example-1.yaml"></a>

```
 1. ---
 2. Resources:
 3.   myLaunchTemplate:
 4.     Type: AWS::EC2::LaunchTemplate
 5.     Properties:
 6.       LaunchTemplateName: !Sub ${AWS::StackName}-launch-template
 7.       LaunchTemplateData:
 8.         ImageId: ami-02354e95b3example
 9.         InstanceType: t3.micro
10.         IamInstanceProfile:
11.           Name: !Ref myInstanceProfile
12.         SecurityGroupIds:
13.         - !Ref myNewEC2SecurityGroup
14.         - sg-083cd3bfb8example
15.         UserData:
16.           Fn::Base64: !Sub |
17.             #!/bin/bash
18.             cd /tmp
19.             yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
20.             systemctl enable amazon-ssm-agent
21.             systemctl start amazon-ssm-agent
22.         TagSpecifications:
23.         - ResourceType: instance
24.           Tags:
25.           - Key: environment
26.             Value: development
27.         - ResourceType: volume
28.           Tags:
29.           - Key: environment
30.             Value: development
31.   myInstanceRole:
32.     Type: AWS::IAM::Role
33.     Properties:
34.       RoleName: InstanceRole
35.       AssumeRolePolicyDocument:
36.         Version: '2012-10-17'
37.         Statement:
38.         - Effect: 'Allow'
39.           Principal:
40.             Service:
41.             - 'ec2.amazonaws.com'
42.           Action:
43.           - 'sts:AssumeRole'
44.       ManagedPolicyArns:
45.         - 'arn:aws:iam::aws:policy/myCustomerManagedPolicy'
46.   myInstanceProfile:
47.     Type: AWS::IAM::InstanceProfile
48.     Properties:
49.       Path: '/'
50.       Roles:
51.       - !Ref myInstanceRole
```

# CloudFormation을 사용하여 보안 그룹 관리
<a name="quickref-ec2-sg"></a>

다음 코드 조각은 CloudFormation을 사용하여 보안 그룹과 Amazon EC2 인스턴스를 관리하여 AWS 리소스에 대한 액세스를 제어하는 방법을 보여줍니다.

**Topics**
+ [보안 그룹과 Amazon EC2 인스턴스 연결](#quickref-ec2-instances-associate-security-group)
+ [인그레스 규칙이 있는 보안 그룹 생성](#quickref-ec2-instances-ingress)
+ [보안 그룹 인그레스 규칙이 있는 Elastic Load Balancer 생성](#scenario-ec2-security-group-elbingress)

## 보안 그룹과 Amazon EC2 인스턴스 연결
<a name="quickref-ec2-instances-associate-security-group"></a>

다음 예제 코드 조각은 CloudFormation을 사용하여 Amazon EC2 인스턴스를 기본 Amazon VPC 보안 그룹과 연결하는 방법을 보여줍니다.

**Topics**
+ [기본 VPC 보안 그룹과 Amazon EC2 인스턴스 연결](#using-cfn-getatt-default-values)
+ [연결된 볼륨 및 보안 그룹을 포함하는 Amazon EC2 인스턴스를 생성합니다.](#scenario-ec2-volumeattachment)

### 기본 VPC 보안 그룹과 Amazon EC2 인스턴스 연결
<a name="using-cfn-getatt-default-values"></a>

다음 코드 조각은 Amazon VPC, VPC 내의 서브넷, Amazon EC2 인스턴스를 생성합니다. VPC는 [AWS::EC2::VPC](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-vpc.html) 리소스를 사용하여 생성됩니다. VPC의 IP 주소 범위는 더 큰 템플릿에서 정의되며 `MyVPCCIDRRange` 파라미터에 의해 참조됩니다.

서브넷은 [AWS::EC2:: Subnet](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-subnet.html) 리소스를 사용하여 VPC 내에 생성됩니다. 서브넷은 `MyVPC`(으)로 참조되는 VPC와 연결됩니다.

EC2 인스턴스는 [AWS::EC2::Instance](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html) 리소스를 사용하여 VPC와 서브넷 내에서 시작됩니다. 이 리소스는 인스턴스를 시작하는 데 사용할 Amazon Machine Image(AMI), 인스턴스를 실행할 서브넷, 인스턴스와 연결할 보안 그룹을 지정합니다. `ImageId`는 Systems Manager 파라미터를 사용하여 최신 Amazon Linux 2 AMI를 동적으로 검색합니다.

보안 그룹 ID는 `MyVPC` 리소스에서 기본 보안 그룹을 검색하는 `Fn::GetAtt` 함수를 사용하여 가져옵니다.

인스턴스는 코드 조각에 정의된 `MySubnet` 리소스 내에 배치됩니다.

CloudFormation을 사용하여 VPC를 생성하는 경우 AWS는 VPC 내에 기본 보안 그룹을 포함한 기본 리소스를 자동으로 생성합니다. 하지만 CloudFormation 템플릿 내에 VPC를 정의하면 템플릿을 생성할 때 이러한 기본 리소스의 ID에 액세스하지 못할 수 있습니다. 템플릿에 지정된 기본 리소스에 액세스하고 사용하려면 `Fn::GetAtt`와(과) 같은 내장 함수를 사용할 수 있습니다. 이 함수를 사용하면 CloudFormation에서 자동으로 생성한 기본 리소스를 사용하여 작업할 수 있습니다.

#### JSON
<a name="quickref-ec2-example-15.json"></a>

```
"MyVPC": {
    "Type": "AWS::EC2::VPC",
    "Properties": {
        "CidrBlock": {
            "Ref": "MyVPCCIDRRange"
        },
        "EnableDnsSupport": false,
        "EnableDnsHostnames": false,
        "InstanceTenancy": "default"
    }
},
"MySubnet": {
    "Type": "AWS::EC2::Subnet",
    "Properties": {
        "CidrBlock": {
            "Ref": "MyVPCCIDRRange"
        },
        "VpcId": {
            "Ref": "MyVPC"
        }
    }
},
"MyInstance": {
    "Type": "AWS::EC2::Instance",
    "Properties": {
        "ImageId": "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}",
        "SecurityGroupIds": [
            {
                "Fn::GetAtt": [
                    "MyVPC",
                    "DefaultSecurityGroup"
                ]
            }
        ],
        "SubnetId": {
            "Ref": "MySubnet"
        }
    }
}
```

#### YAML
<a name="quickref-ec2-example-15.yaml"></a>

```
MyVPC:
  Type: AWS::EC2::VPC
  Properties:
    CidrBlock:
      Ref: MyVPCCIDRRange
    EnableDnsSupport: false
    EnableDnsHostnames: false
    InstanceTenancy: default
MySubnet:
  Type: AWS::EC2::Subnet
  Properties:
    CidrBlock:
      Ref: MyVPCCIDRRange
    VpcId:
      Ref: MyVPC
MyInstance:
  Type: AWS::EC2::Instance
  Properties:
    ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
    SecurityGroupIds:
      - Fn::GetAtt:
          - MyVPC
          - DefaultSecurityGroup
    SubnetId:
      Ref: MySubnet
```

### 연결된 볼륨 및 보안 그룹을 포함하는 Amazon EC2 인스턴스를 생성합니다.
<a name="scenario-ec2-volumeattachment"></a>

다음 코드 조각은 지정된 AMI에서 시작되는 [AWS::EC2::Instance](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html) 리소스를 사용하여 Amazon EC2 인스턴스를 생성합니다. 인스턴스는 [AWS::EC2::SecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) 리소스를 사용하여 지정된 IP 주소로부터 포트 22로 들어오는 SSH 트래픽을 허용하는 보안 그룹과 연결됩니다. [AWS::EC2::Volume](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-volume.html) 리소스를 사용하여 100GB Amazon EBS 볼륨을 생성합니다. 볼륨은 `GetAtt` 함수에 지정된 대로 인스턴스와 동일한 가용 영역에 생성되며 `/dev/sdh` 디바이스의 인스턴스에 마운트됩니다.

Amazon EBS 볼륨 생성에 대한 자세한 내용은 [Amazon EBS 볼륨 생성](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-creating-volume.html)을 참조하세요.

#### JSON
<a name="quickref-ec2-example-14.json"></a>

```
 1. "Ec2Instance": {
 2.     "Type": "AWS::EC2::Instance",
 3.     "Properties": {
 4.         "SecurityGroups": [
 5.             {
 6.                 "Ref": "InstanceSecurityGroup"
 7.             }
 8.         ],
 9.         "ImageId": "ami-1234567890abcdef0"
10.     }
11. },
12. "InstanceSecurityGroup": {
13.     "Type": "AWS::EC2::SecurityGroup",
14.     "Properties": {
15.         "GroupDescription": "Enable SSH access via port 22",
16.         "SecurityGroupIngress": [
17.             {
18.                 "IpProtocol": "tcp",
19.                 "FromPort": "22",
20.                 "ToPort": "22",
21.                 "CidrIp": "192.0.2.0/24"
22.             }
23.         ]
24.     }
25. },
26. "NewVolume": {
27.     "Type": "AWS::EC2::Volume",
28.     "Properties": {
29.         "Size": "100",
30.         "AvailabilityZone": {
31.             "Fn::GetAtt": [
32.                 "Ec2Instance",
33.                 "AvailabilityZone"
34.             ]
35.         }
36.     }
37. },
38. "MountPoint": {
39.     "Type": "AWS::EC2::VolumeAttachment",
40.     "Properties": {
41.         "InstanceId": {
42.             "Ref": "Ec2Instance"
43.         },
44.         "VolumeId": {
45.             "Ref": "NewVolume"
46.         },
47.         "Device": "/dev/sdh"
48.     }
49. }
```

#### YAML
<a name="quickref-ec2-example-14.yaml"></a>

```
 1. Ec2Instance:
 2.   Type: AWS::EC2::Instance
 3.   Properties:
 4.     SecurityGroups:
 5.       - !Ref InstanceSecurityGroup
 6.     ImageId: ami-1234567890abcdef0
 7. InstanceSecurityGroup:
 8.   Type: AWS::EC2::SecurityGroup
 9.   Properties:
10.     GroupDescription: Enable SSH access via port 22
11.     SecurityGroupIngress:
12.       - IpProtocol: tcp
13.         FromPort: 22
14.         ToPort: 22
15.         CidrIp: 192.0.2.0/24
16. NewVolume:
17.   Type: AWS::EC2::Volume
18.   Properties:
19.     Size: 100
20.     AvailabilityZone: !GetAtt [Ec2Instance, AvailabilityZone]
21. MountPoint:
22.   Type: AWS::EC2::VolumeAttachment
23.   Properties:
24.     InstanceId: !Ref Ec2Instance
25.     VolumeId: !Ref NewVolume
26.     Device: /dev/sdh
```

## 인그레스 규칙이 있는 보안 그룹 생성
<a name="quickref-ec2-instances-ingress"></a>

다음 코드 조각 예제는 CloudFormation을 사용하여 특정 인그레스 규칙이 있는 보안 그룹을 구성하는 방법을 보여줍니다.

**Topics**
+ [SSH 및 HTTP 액세스를 위한 인그레스 규칙이 있는 보안 그룹 생성](#scenario-ec2-security-group-rule)
+ [지정된 CIDR 범위에서의 HTTP 및 SSH 액세스에 대한 인그레스 규칙이 있는 보안 그룹 생성](#scenario-ec2-security-group-two-ports)
+ [인그레스 규칙이 있는 교차 참조 보안 그룹 생성](#scenario-ec2-security-group-ingress)

### SSH 및 HTTP 액세스를 위한 인그레스 규칙이 있는 보안 그룹 생성
<a name="scenario-ec2-security-group-rule"></a>

다음 코드 조각은 [AWS::EC2::SecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) 리소스를 사용하는 두 가지 보안 그룹 인그레스 규칙을 설명합니다. 첫 번째 인그레스 규칙은 계정 번호가 `1111-2222-3333`인 AWS 계정이 소유한 `MyAdminSecurityGroup`이라는 기존 보안 그룹에서의 SSH(포트 22) 액세스를 허용합니다. 두 번째 인그레스 규칙은 동일한 템플릿에서 생성된 `MySecurityGroupCreatedInCFN`이라는 다른 보안 그룹에서의 HTTP(포트 80) 액세스를 허용합니다. `Ref` 함수는 동일한 템플릿에 생성된 보안 그룹의 논리명을 참조하는 데 사용됩니다.

첫 번째 인그레스 규칙에서는 `SourceSecurityGroupName` 및 `SourceSecurityGroupOwnerId` 속성 모두에 값을 추가해야 합니다. 두 번째 인그레스 규칙에서 `MySecurityGroupCreatedInCFNTemplate`은(는) 동일한 템플릿에 생성된 다른 보안 그룹을 참조합니다. 논리명 `MySecurityGroupCreatedInCFNTemplate`이(가) 더 큰 템플릿에서 지정한 보안 그룹 리소스의 실제 논리명과 일치하는지 확인합니다.

보안 그룹에 대한 자세한 내용은 *Amazon EC2 사용 설명서*의 [Amazon EC2 인스턴스에 대한 Amazon EC2 보안 그룹](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)을 참조하세요.

#### JSON
<a name="quickref-ec2-example-10.json"></a>

```
 1. "SecurityGroup": {
 2.     "Type": "AWS::EC2::SecurityGroup",
 3.     "Properties": {
 4.         "GroupDescription": "Allow connections from specified source security group",
 5.         "SecurityGroupIngress": [
 6.             {
 7.                 "IpProtocol": "tcp",
 8.                 "FromPort": "22",
 9.                 "ToPort": "22",
10.                 "SourceSecurityGroupName": "MyAdminSecurityGroup",
11.                 "SourceSecurityGroupOwnerId": "1111-2222-3333"
12.             },
13.             {
14.                 "IpProtocol": "tcp",
15.                 "FromPort": "80",
16.                 "ToPort": "80",
17.                 "SourceSecurityGroupName": {
18.                     "Ref": "MySecurityGroupCreatedInCFNTemplate"
19.                 }
20.             }
21.         ]
22.     }
23. }
```

#### YAML
<a name="quickref-ec2-example-10.yaml"></a>

```
 1. SecurityGroup:
 2.   Type: AWS::EC2::SecurityGroup
 3.   Properties:
 4.     GroupDescription: Allow connections from specified source security group
 5.     SecurityGroupIngress:
 6.       - IpProtocol: tcp
 7.         FromPort: '22'
 8.         ToPort: '22'
 9.         SourceSecurityGroupName: MyAdminSecurityGroup
10.         SourceSecurityGroupOwnerId: '1111-2222-3333'
11.       - IpProtocol: tcp
12.         FromPort: '80'
13.         ToPort: '80'
14.         SourceSecurityGroupName:
15.           Ref: MySecurityGroupCreatedInCFNTemplate
```

### 지정된 CIDR 범위에서의 HTTP 및 SSH 액세스에 대한 인그레스 규칙이 있는 보안 그룹 생성
<a name="scenario-ec2-security-group-two-ports"></a>

다음 코드 조각은 두 가지 인바운드 규칙이 있는 Amazon EC2 인스턴스용 보안 그룹을 생성합니다. 인바운드 규칙은 지정된 CIDR 범위에서 지정된 포트로 들어오는 TCP 트래픽을 허용합니다. 규칙을 지정하는 데 [AWS::EC2::SecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) 리소스가 사용됩니다. 각 규칙마다 프로토콜을 지정해야 합니다. TCP의 경우 포트 또는 포트 범위도 지정해야 합니다. 소스 보안 그룹 또는 CIDR 범위를 지정하지 않으면 스택이 성공적으로 시작되지만 규칙이 보안 그룹에 적용되지 않습니다.

보안 그룹에 대한 자세한 내용은 *Amazon EC2 사용 설명서*의 [Amazon EC2 인스턴스에 대한 Amazon EC2 보안 그룹](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html)을 참조하세요.

#### JSON
<a name="quickref-ec2-example-9.json"></a>

```
 1. "ServerSecurityGroup": {
 2.   "Type": "AWS::EC2::SecurityGroup",
 3.   "Properties": {
 4.     "GroupDescription": "Allow connections from specified CIDR ranges",
 5.     "SecurityGroupIngress": [
 6.       {
 7.         "IpProtocol": "tcp",
 8.         "FromPort": "80",
 9.         "ToPort": "80",
10.         "CidrIp": "192.0.2.0/24"
11.       },
12.       {
13.         "IpProtocol": "tcp",
14.         "FromPort": "22",
15.         "ToPort": "22",
16.         "CidrIp": "192.0.2.0/24"
17.       }
18.     ]
19.   }
20. }
```

#### YAML
<a name="quickref-ec2-example-9.yaml"></a>

```
 1. ServerSecurityGroup:
 2.   Type: AWS::EC2::SecurityGroup
 3.   Properties:
 4.     GroupDescription: Allow connections from specified CIDR ranges
 5.     SecurityGroupIngress:
 6.       - IpProtocol: tcp
 7.         FromPort: 80
 8.         ToPort: 80
 9.         CidrIp: 192.0.2.0/24
10.       - IpProtocol: tcp
11.         FromPort: 22
12.         ToPort: 22
13.         CidrIp: 192.0.2.0/24
```

### 인그레스 규칙이 있는 교차 참조 보안 그룹 생성
<a name="scenario-ec2-security-group-ingress"></a>

다음 코드 조각은 [AWS::EC2::SecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) 리소스를 사용하여 두 개의 Amazon EC2 보안 그룹 `SGroup1` 및 `SGroup2`을(를) 생성합니다. 두 보안 그룹 간의 통신을 허용하는 인그레스 규칙은 [AWS::EC2::SecurityGroupIngress](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroupingress.html) 리소스를 사용하여 생성됩니다. `SGroup1Ingress`은(는) 소스 보안 그룹 `SGroup2`에서 포트 80으로 들어오는 TCP 트래픽을 허용하는 `SGroup1`의 인그레스 규칙을 설정합니다. `SGroup2Ingress`은(는) 소스 보안 그룹 `SGroup1`에서 포트 80으로 들어오는 TCP 트래픽을 허용하는 `SGroup2`의 인그레스 규칙을 설정합니다.

#### JSON
<a name="quickref-ec2-example-12.json"></a>

```
 1. "SGroup1": {
 2.     "Type": "AWS::EC2::SecurityGroup",
 3.     "Properties": {
 4.         "GroupDescription": "EC2 instance access"
 5.     }
 6. },
 7. "SGroup2": {
 8.     "Type": "AWS::EC2::SecurityGroup",
 9.     "Properties": {
10.         "GroupDescription": "EC2 instance access"
11.     }
12. },
13. "SGroup1Ingress": {
14.     "Type": "AWS::EC2::SecurityGroupIngress",
15.     "Properties": {
16.         "GroupName": {
17.             "Ref": "SGroup1"
18.         },
19.         "IpProtocol": "tcp",
20.         "ToPort": "80",
21.         "FromPort": "80",
22.         "SourceSecurityGroupName": {
23.             "Ref": "SGroup2"
24.         }
25.     }
26. },
27. "SGroup2Ingress": {
28.     "Type": "AWS::EC2::SecurityGroupIngress",
29.     "Properties": {
30.         "GroupName": {
31.             "Ref": "SGroup2"
32.         },
33.         "IpProtocol": "tcp",
34.         "ToPort": "80",
35.         "FromPort": "80",
36.         "SourceSecurityGroupName": {
37.             "Ref": "SGroup1"
38.         }
39.     }
40. }
```

#### YAML
<a name="quickref-ec2-example-12.yaml"></a>

```
 1. SGroup1:
 2.   Type: AWS::EC2::SecurityGroup
 3.   Properties:
 4.     GroupDescription: EC2 Instance access
 5. SGroup2:
 6.   Type: AWS::EC2::SecurityGroup
 7.   Properties:
 8.     GroupDescription: EC2 Instance access
 9. SGroup1Ingress:
10.   Type: AWS::EC2::SecurityGroupIngress
11.   Properties:
12.     GroupName: !Ref SGroup1
13.     IpProtocol: tcp
14.     ToPort: 80
15.     FromPort: 80
16.     SourceSecurityGroupName: !Ref SGroup2
17. SGroup2Ingress:
18.   Type: AWS::EC2::SecurityGroupIngress
19.   Properties:
20.     GroupName: !Ref SGroup2
21.     IpProtocol: tcp
22.     ToPort: 80
23.     FromPort: 80
24.     SourceSecurityGroupName: !Ref SGroup1
```

## 보안 그룹 인그레스 규칙이 있는 Elastic Load Balancer 생성
<a name="scenario-ec2-security-group-elbingress"></a>

다음 템플릿은 지정된 가용 영역에 [AWS::ElasticLoadBalancing::LoadBalancer](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancing-loadbalancer.html) 리소스를 생성합니다. [AWS::ElasticLoadBalancing::LoadBalancer](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-elasticloadbalancing-loadbalancer.html) 리소스는 포트 80에서 HTTP 트래픽을 수신하고 포트 80에서 인스턴스로 직접 요청을 보내도록 구성됩니다. Elastic Load Balancer는 인스턴스 간에 들어오는 HTTP 트래픽의 로드 밸런싱을 담당합니다.

 또한 이 템플릿은 로드 밸런서와 연결된 [AWS::EC2::SecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html) 리소스를 생성합니다. 이 보안 그룹은 포트 80에서 들어오는 TCP 트래픽을 허용하는 단일 인그레스 규칙(`ELB ingress group`(으)로 설명됨)으로 생성됩니다. 이 인그레스 규칙의 소스는 로드 밸런서 리소스에서 속성을 검색하는 `Fn::GetAtt` 함수를 사용하여 정의됩니다. `SourceSecurityGroupOwnerId`은(는) `Fn::GetAtt`을 사용하여 로드 밸런서 소스 보안 그룹의 `OwnerAlias`을(를) 가져옵니다. `SourceSecurityGroupName`은(는) `Fn::Getatt`을(를) 사용하여 ELB 소스 보안 그룹의 `GroupName`을(를) 가져옵니다.

이 설정은 ELB와 인스턴스 간의 보안 통신을 보장합니다.

로드 밸런싱에 대한 자세한 내용은 [Elastic Load Balancing 사용 설명서](https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/)를 참조하세요.

### JSON
<a name="quickref-ec2-example-11.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Resources": {
        "MyELB": {
            "Type": "AWS::ElasticLoadBalancing::LoadBalancer",
            "Properties": {
                "AvailabilityZones": [
                    "aa-example-1a"
                ],
                "Listeners": [
                    {
                        "LoadBalancerPort": "80",
                        "InstancePort": "80",
                        "Protocol": "HTTP"
                    }
                ]
            }
        },
        "MyELBIngressGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": "ELB ingress group",
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 80,
                        "ToPort": 80,
                        "SourceSecurityGroupOwnerId": {
                            "Fn::GetAtt": [
                                "MyELB",
                                "SourceSecurityGroup.OwnerAlias"
                            ]
                        },
                        "SourceSecurityGroupName": {
                            "Fn::GetAtt": [
                                "MyELB",
                                "SourceSecurityGroup.GroupName"
                            ]
                        }
                    }
                ]
            }
        }
    }
}
```

### YAML
<a name="quickref-ec2-example-11.yaml"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  MyELB:
    Type: AWS::ElasticLoadBalancing::LoadBalancer
    Properties:
      AvailabilityZones:
        - aa-example-1a
      Listeners:
        - LoadBalancerPort: '80'
          InstancePort: '80'
          Protocol: HTTP
  MyELBIngressGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ELB ingress group
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          SourceSecurityGroupOwnerId:
            Fn::GetAtt:
              - MyELB
              - SourceSecurityGroup.OwnerAlias
          SourceSecurityGroupName:
            Fn::GetAtt:
              - MyELB
              - SourceSecurityGroup.GroupName
```

# CloudFormation을 사용하여 탄력적 IP 주소 할당 및 연결
<a name="quickref-ec2-elastic-ip"></a>

다음 템플릿 코드 조각은 Amazon EC2의 탄력적 IP 주소(EIP)와 관련된 예입니다. 이 예에서는 인스턴스의 EIP 할당, 연결 및 관리를 다룹니다.

**Topics**
+ [탄력적 IP 주소 할당 및 Amazon EC2 인스턴스와 연결](#scenario-ec2-eip)
+ [IP 주소를 지정하여 Amazon EC2 인스턴스에 탄력적 IP 주소 연결](#scenario-ec2-eip-association)
+ [IP 주소의 할당 ID를 지정하여 Amazon EC2 인스턴스에 탄력적 IP 주소 연결](#scenario-ec2-eip-association-vpc)

## 탄력적 IP 주소 할당 및 Amazon EC2 인스턴스와 연결
<a name="scenario-ec2-eip"></a>

다음 코드 조각은 [AWS::EC2::EIP](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-eip.html) 리소스를 사용하여 Amazon EC2 탄력적 IP(EIP)를 할당하고 해당 주소를 Amazon EC2 인스턴스와 연결합니다. AWS이(가) 소유한 주소 풀 또는 [고유 IP 주소 가져오기(BYOIP)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-byoip.html)를 사용하여 AWS 리소스와 함께 사용하기 위해 AWS(으)로 가져온 퍼블릭 IPv4 주소 범위에서 생성한 주소 풀의 EIP 주소를 할당할 수 있습니다. 이 예에서는 AWS이(가) 소유한 주소 풀에서 EIP를 할당합니다.

탄력적 IP 주소에 대한 자세한 내용은 *Amazon EC2 사용 설명서*의 [탄력적 IP 주소](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html)를 참조하세요.

### JSON
<a name="quickref-ec2-example-3.json"></a>

```
1. "ElasticIP": {
2.     "Type": "AWS::EC2::EIP",
3.     "Properties": {
4.         "InstanceId": {
5.             "Ref": "Ec2Instance"
6.         }
7.     }
8. }
```

### YAML
<a name="quickref-ec2-example-3.yaml"></a>

```
1. ElasticIP:
2.   Type: AWS::EC2::EIP
3.   Properties:
4.     InstanceId: !Ref EC2Instance
```

## IP 주소를 지정하여 Amazon EC2 인스턴스에 탄력적 IP 주소 연결
<a name="scenario-ec2-eip-association"></a>

다음 코드 조각은 [AWS::EC2::EIPAssociation](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-eipassociation.html) 리소스를 사용하여 기존 Amazon EC2 탄력적 IP 주소를 EC2 인스턴스에 연결합니다. 먼저 계정에서 사용할 탄력적 IP 주소를 할당해야 합니다. 탄력적 IP 주소는 하나의 인스턴스와 연결할 수 있습니다.

### JSON
<a name="quickref-ec2-example-4.json"></a>

```
1. "IPAssoc": {
2.   "Type": "AWS::EC2::EIPAssociation",
3.   "Properties": {
4.     "InstanceId": {
5.       "Ref": "Ec2Instance"
6.     },
7.     "EIP": "192.0.2.0"
8.   }
9. }
```

### YAML
<a name="quickref-ec2-example-4.yaml"></a>

```
1. IPAssoc:
2.   Type: AWS::EC2::EIPAssociation
3.   Properties:
4.     InstanceId: !Ref EC2Instance
5.     EIP: 192.0.2.0
```

## IP 주소의 할당 ID를 지정하여 Amazon EC2 인스턴스에 탄력적 IP 주소 연결
<a name="scenario-ec2-eip-association-vpc"></a>

다음 코드 조각은 [AWS::EC2::EIPAssociation](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-eipassociation.html) 리소스를 사용하여 할당 ID를 지정하여 기존 탄력적 IP 주소를 Amazon EC2 인스턴스에 연결합니다. 탄력적 IP 주소 할당 시 탄력적 IP 주소에 할당 ID가 할당됩니다.

### JSON
<a name="quickref-ec2-example-5.json"></a>

```
1. "IPAssoc": {
2.     "Type": "AWS::EC2::EIPAssociation",
3.     "Properties": {
4.         "InstanceId": {
5.             "Ref": "Ec2Instance"
6.         },
7.         "AllocationId": "eipalloc-1234567890abcdef0"
8.     }
9. }
```

### YAML
<a name="quickref-ec2-example-5.yaml"></a>

```
1. IPAssoc:
2.   Type: AWS::EC2::EIPAssociation
3.   Properties:
4.     InstanceId: !Ref EC2Instance
5.     AllocationId: eipalloc-1234567890abcdef0
```

# CloudFormation을 사용하여 Amazon VPC 리소스 구성
<a name="quickref-ec2-vpc"></a>

이 섹션에서는 CloudFormation을 사용하여 Amazon VPC 리소스를 구성하는 예를 제공합니다. VPC를 사용하면 AWS 내에서 가상 네트워크를 생성할 수 있으며, 다음 코드 조각은 네트워킹 요구 사항에 맞게 VPC의 측면을 구성하는 방법을 보여 줍니다.

**Topics**
+ [VPC에서 IPv6 외부 전용 인터넷 액세스 활성화](#quickref-ec2-route-egressonlyinternetgateway)
+ [탄력적 네트워크 인터페이스(ENI) 템플릿 코드 조각](#cfn-template-snippets-eni)

## VPC에서 IPv6 외부 전용 인터넷 액세스 활성화
<a name="quickref-ec2-route-egressonlyinternetgateway"></a>

외부 전용 인터넷 게이트웨이를 사용하면 VPC 내의 인스턴스가 인터넷에 액세스할 수 있으며 인터넷의 리소스가 인스턴스와 통신하는 것을 방지할 수 있습니다. 다음 코드 조각은 VPC 내에서 IPv6 외부 전용 인터넷 액세스를 활성화합니다. [AWS::EC2::VPC](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-vpc.html) 리소스를 사용하여 IPv4 주소 범위가 `10.0.0/16`인 VPC를 생성합니다. 라우팅 테이블은 [AWS::EC2::RouteTable](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-routetable.html) 리소스를 사용하여 이 VPC 리소스와 연결됩니다. 라우팅 테이블은 VPC 내 인스턴스의 경로를 관리합니다. [AWS::EC2::EgressOnlyInternetGateway](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-egressonlyinternetgateway.html)는 인바운드 트래픽을 차단하면서 VPC 내 인스턴스로부터의 아웃바운드 트래픽에 대해 IPv6 통신을 활성화하는 외부 전용 인터넷 게이트웨이를 생성하는 데 사용됩니다. [AWS::EC2::Route](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-route.html) 리소스는 모든 아웃바운드 IPv6 트래픽(`::/0`)을 외부 전용 인터넷 게이트웨이로 보내는 IPv6 경로를 라우팅 테이블에 생성하도록 지정됩니다.

송신 전용 인터넷 게이트웨이에 대한 자세한 내용은 *Amazon VPC 사용 설명서*의 [송신 전용 인터넷 게이트웨이를 사용하여 아웃바운드 IPv6 트래픽 활성화](https://docs.aws.amazon.com/vpc/latest/userguide/egress-only-internet-gateway.html)를 참조하세요.

### JSON
<a name="quickref-ec2-example-16.json"></a>

```
"DefaultIpv6Route": {
    "Type": "AWS::EC2::Route",
    "Properties": {
        "DestinationIpv6CidrBlock": "::/0",
        "EgressOnlyInternetGatewayId": {
            "Ref": "EgressOnlyInternetGateway"
        },
        "RouteTableId": {
            "Ref": "RouteTable"
        }
    }
},
"EgressOnlyInternetGateway": {
    "Type": "AWS::EC2::EgressOnlyInternetGateway",
    "Properties": {
        "VpcId": {
            "Ref": "VPC"
        }
    }
},
"RouteTable": {
    "Type": "AWS::EC2::RouteTable",
    "Properties": {
        "VpcId": {
            "Ref": "VPC"
        }
    }
},
"VPC": {
    "Type": "AWS::EC2::VPC",
    "Properties": {
        "CidrBlock": "10.0.0.0/16"
    }
}
```

### YAML
<a name="quickref-ec2-example-16.yaml"></a>

```
DefaultIpv6Route:
  Type: AWS::EC2::Route
  Properties:
    DestinationIpv6CidrBlock: "::/0"
    EgressOnlyInternetGatewayId:
      Ref: "EgressOnlyInternetGateway"
    RouteTableId:
      Ref: "RouteTable"
EgressOnlyInternetGateway:
  Type: AWS::EC2::EgressOnlyInternetGateway
  Properties:
    VpcId:
      Ref: "VPC"
RouteTable:
  Type: AWS::EC2::RouteTable
  Properties:
    VpcId:
      Ref: "VPC"
VPC:
  Type: AWS::EC2::VPC
  Properties:
    CidrBlock: "10.0.0.0/16"
```

## 탄력적 네트워크 인터페이스(ENI) 템플릿 코드 조각
<a name="cfn-template-snippets-eni"></a>

### 탄력적 네트워크 인터페이스(ENI)를 사용하여 Amazon EC2 인스턴스 생성
<a name="cfn-template-snippets-eni-template"></a>

다음 예제 스니펫은 지정된 Amazon VPC 및 서브넷에서 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html) 리소스를 사용하여 Amazon EC2 인스턴스를 생성합니다. 인스턴스에 두 개의 네트워크 인터페이스(ENI)를 연결하고, 연결된 ENI를 통해 탄력적 IP 주소를 인스턴스에 연결하고, SSH 및 HTTP 액세스를 위한 보안 그룹을 구성합니다. 사용자 데이터는 인스턴스 생성 시 시작 구성의 일부로 인스턴스에 제공됩니다. 사용자 데이터에는 인스턴스에 전달되도록 `base64` 형식으로 인코딩된 스크립트가 포함되어 있습니다. 인스턴스가 시작되면 스크립트는 부트스트랩 프로세스의 일부로 자동으로 실행됩니다. `ec2-net-utils`을(를) 설치하고 네트워크 인터페이스를 구성한 다음 HTTP 서비스를 시작합니다.

선택한 리전을 기반으로 적절한 Amazon Machine Image(AMI)를 결정하기 위해 코드 조각은 `RegionMap` 매핑에서 값을 조회하는 `Fn::FindInMap` 함수를 사용합니다. 이 매핑은 더 큰 템플릿에서 정의해야 합니다. 두 네트워크 인터페이스는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-networkinterface.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-networkinterface.html) 리소스를 사용하여 생성됩니다. 탄력적 IP 주소는 `vpc` 도메인에 할당된 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-eip.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-eip.html) 리소스를 사용하여 지정됩니다. 해당 탄력적 IP 주소는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-eipassociation.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-eipassociation.html) 리소스를 사용하는 네트워크 인터페이스와 연결됩니다.

`Outputs` 섹션에서는 스택이 생성된 후 액세스하려는 값이나 리소스를 정의합니다. 이 코드 조각에서 정의된 출력은 `InstancePublicIp`이며 스택에서 생성한 EC2 인스턴스의 퍼블릭 IP 주소를 나타냅니다. CloudFormation 콘솔의 **출력** 탭이나 [describe-stacks](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) 명령을 사용하여 이 출력을 검색할 수 있습니다.

탄력적 네트워크 인터페이스에 대한 자세한 내용은 [탄력적 네트워크 인터페이스](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html)를 참조하세요.

#### JSON
<a name="cfn-template-snippets-eni-example-1.json"></a>

```
"Resources": {
    "ControlPortAddress": {
        "Type": "AWS::EC2::EIP",
        "Properties": {
            "Domain": "vpc"
        }
    },
    "AssociateControlPort": {
        "Type": "AWS::EC2::EIPAssociation",
        "Properties": {
            "AllocationId": {
                "Fn::GetAtt": [
                    "ControlPortAddress",
                    "AllocationId"
                ]
            },
            "NetworkInterfaceId": {
                "Ref": "controlXface"
            }
        }
    },
    "WebPortAddress": {
        "Type": "AWS::EC2::EIP",
        "Properties": {
            "Domain": "vpc"
        }
    },
    "AssociateWebPort": {
        "Type": "AWS::EC2::EIPAssociation",
        "Properties": {
            "AllocationId": {
                "Fn::GetAtt": [
                    "WebPortAddress",
                    "AllocationId"
                ]
            },
            "NetworkInterfaceId": {
                "Ref": "webXface"
            }
        }
    },
    "SSHSecurityGroup": {
        "Type": "AWS::EC2::SecurityGroup",
        "Properties": {
            "VpcId": {
                "Ref": "VpcId"
            },
            "GroupDescription": "Enable SSH access via port 22",
            "SecurityGroupIngress": [
                {
                    "CidrIp": "0.0.0.0/0",
                    "FromPort": 22,
                    "IpProtocol": "tcp",
                    "ToPort": 22
                }
            ]
        }
    },
    "WebSecurityGroup": {
        "Type": "AWS::EC2::SecurityGroup",
        "Properties": {
            "VpcId": {
                "Ref": "VpcId"
            },
            "GroupDescription": "Enable HTTP access via user-defined port",
            "SecurityGroupIngress": [
                {
                    "CidrIp": "0.0.0.0/0",
                    "FromPort": 80,
                    "IpProtocol": "tcp",
                    "ToPort": 80
                }
            ]
        }
    },
    "controlXface": {
        "Type": "AWS::EC2::NetworkInterface",
        "Properties": {
            "SubnetId": {
                "Ref": "SubnetId"
            },
            "Description": "Interface for controlling traffic such as SSH",
            "GroupSet": [
                {
                    "Fn::GetAtt": [
                        "SSHSecurityGroup",
                        "GroupId"
                    ]
                }
            ],
            "SourceDestCheck": true,
            "Tags": [
                {
                    "Key": "Network",
                    "Value": "Control"
                }
            ]
        }
    },
    "webXface": {
        "Type": "AWS::EC2::NetworkInterface",
        "Properties": {
            "SubnetId": {
                "Ref": "SubnetId"
            },
            "Description": "Interface for web traffic",
            "GroupSet": [
                {
                    "Fn::GetAtt": [
                        "WebSecurityGroup",
                        "GroupId"
                    ]
                }
            ],
            "SourceDestCheck": true,
            "Tags": [
                {
                    "Key": "Network",
                    "Value": "Web"
                }
            ]
        }
    },
    "Ec2Instance": {
        "Type": "AWS::EC2::Instance",
        "Properties": {
            "ImageId": {
                "Fn::FindInMap": [
                    "RegionMap",
                    {
                        "Ref": "AWS::Region"
                    },
                    "AMI"
                ]
            },
            "KeyName": {
                "Ref": "KeyName"
            },
            "NetworkInterfaces": [
                {
                    "NetworkInterfaceId": {
                        "Ref": "controlXface"
                    },
                    "DeviceIndex": "0"
                },
                {
                    "NetworkInterfaceId": {
                        "Ref": "webXface"
                    },
                    "DeviceIndex": "1"
                }
            ],
            "Tags": [
                {
                    "Key": "Role",
                    "Value": "Test Instance"
                }
            ],
            "UserData": {
                "Fn::Base64": {
                    "Fn::Sub": "#!/bin/bash -xe\nyum install ec2-net-utils -y\nec2ifup eth1\nservice httpd start\n"
                }
            }
        }
    }
},
"Outputs": {
    "InstancePublicIp": {
        "Description": "Public IP Address of the EC2 Instance",
        "Value": {
            "Fn::GetAtt": [
                "Ec2Instance",
                "PublicIp"
            ]
        }
    }
}
```

#### YAML
<a name="cfn-template-snippets-eni-example.yaml"></a>

```
Resources:
  ControlPortAddress:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
  AssociateControlPort:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId:
        Fn::GetAtt:
          - ControlPortAddress
          - AllocationId
      NetworkInterfaceId:
        Ref: controlXface
  WebPortAddress:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
  AssociateWebPort:
    Type: AWS::EC2::EIPAssociation
    Properties:
      AllocationId:
        Fn::GetAtt:
          - WebPortAddress
          - AllocationId
      NetworkInterfaceId:
        Ref: webXface
  SSHSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId:
        Ref: VpcId
      GroupDescription: Enable SSH access via port 22
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          FromPort: 22
          IpProtocol: tcp
          ToPort: 22
  WebSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId:
        Ref: VpcId
      GroupDescription: Enable HTTP access via user-defined port
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          FromPort: 80
          IpProtocol: tcp
          ToPort: 80
  controlXface:
    Type: AWS::EC2::NetworkInterface
    Properties:
      SubnetId:
        Ref: SubnetId
      Description: Interface for controlling traffic such as SSH
      GroupSet:
        - Fn::GetAtt:
            - SSHSecurityGroup
            - GroupId
      SourceDestCheck: true
      Tags:
        - Key: Network
          Value: Control
  webXface:
    Type: AWS::EC2::NetworkInterface
    Properties:
      SubnetId:
        Ref: SubnetId
      Description: Interface for web traffic
      GroupSet:
        - Fn::GetAtt:
            - WebSecurityGroup
            - GroupId
      SourceDestCheck: true
      Tags:
        - Key: Network
          Value: Web
  Ec2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId:
        Fn::FindInMap:
          - RegionMap
          - Ref: AWS::Region
          - AMI
      KeyName:
        Ref: KeyName
      NetworkInterfaces:
        - NetworkInterfaceId:
            Ref: controlXface
          DeviceIndex: "0"
        - NetworkInterfaceId:
            Ref: webXface
          DeviceIndex: "1"
      Tags:
        - Key: Role
          Value: Test Instance
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          yum install ec2-net-utils -y
          ec2ifup eth1
          service httpd start
Outputs:
  InstancePublicIp:
    Description: Public IP Address of the EC2 Instance
    Value:
      Fn::GetAtt:
        - Ec2Instance
        - PublicIp
```

# Amazon Elastic Container Service 샘플 템플릿
<a name="quickref-ecs"></a>

Amazon Elastic Container Service(Amazon ECS)는 Amazon Elastic Compute Cloud(Amazon EC2) 인스턴스 클러스터에서 도커 컨테이너를 손쉽게 실행, 중지 및 관리할 수 있게 해 주는 컨테이너 관리 서비스입니다.

## AL2023 Amazon ECS-Optimized-AMI를 사용하여 클러스터 생성
<a name="create-cluster-al2023"></a>

Amazon EC2에서 AL2023 인스턴스를 실행하는 용량 공급자를 사용하는 클러스터를 정의합니다.

**중요**  
최신 AMI ID는 *Amazon Elastic Container Service 개발자 안내서*의 [Amazon ECS 최적화 AMI](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html)를 참조하세요.

### JSON
<a name="quickref-ecs-example-1.json"></a>

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "EC2 ECS cluster that starts out empty, with no EC2 instances yet. An ECS capacity provider automatically launches more EC2 instances as required on the fly when you request ECS to launch services or standalone tasks.",
  "Parameters": {
      "InstanceType": {
          "Type": "String",
          "Description": "EC2 instance type",
          "Default": "t2.medium",
          "AllowedValues": [
              "t1.micro",
              "t2.2xlarge",
              "t2.large",
              "t2.medium",
              "t2.micro",
              "t2.nano",
              "t2.small",
              "t2.xlarge",
              "t3.2xlarge",
              "t3.large",
              "t3.medium",
              "t3.micro",
              "t3.nano",
              "t3.small",
              "t3.xlarge"
          ]
      },
      "DesiredCapacity": {
          "Type": "Number",
          "Default": "0",
          "Description": "Number of EC2 instances to launch in your ECS cluster."
      },
      "MaxSize": {
          "Type": "Number",
          "Default": "100",
          "Description": "Maximum number of EC2 instances that can be launched in your ECS cluster."
      },
      "ECSAMI": {
          "Description": "The Amazon Machine Image ID used for the cluster",
          "Type": "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>",
          "Default": "/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id"
      },
      "VpcId": {
          "Type": "AWS::EC2::VPC::Id",
          "Description": "VPC ID where the ECS cluster is launched",
          "Default": "vpc-1234567890abcdef0"
      },
      "SubnetIds": {
          "Type": "List<AWS::EC2::Subnet::Id>",
          "Description": "List of subnet IDs where the EC2 instances will be launched",
          "Default": "subnet-021345abcdef67890"
      }
  },
  "Resources": {
      "ECSCluster": {
          "Type": "AWS::ECS::Cluster",
          "Properties": {
              "ClusterSettings": [
                  {
                      "Name": "containerInsights",
                      "Value": "enabled"
                  }
              ]
          }
      },
      "ECSAutoScalingGroup": {
          "Type": "AWS::AutoScaling::AutoScalingGroup",
          "DependsOn": [
              "ECSCluster",
              "EC2Role"
          ],
          "Properties": {
              "VPCZoneIdentifier": {
                  "Ref": "SubnetIds"
              },
              "LaunchTemplate": {
                  "LaunchTemplateId": {
                      "Ref": "ContainerInstances"
                  },
                  "Version": {
                      "Fn::GetAtt": [
                          "ContainerInstances",
                          "LatestVersionNumber"
                      ]
                  }
              },
              "MinSize": 0,
              "MaxSize": {
                  "Ref": "MaxSize"
              },
              "DesiredCapacity": {
                  "Ref": "DesiredCapacity"
              },
              "NewInstancesProtectedFromScaleIn": true
          },
          "UpdatePolicy": {
              "AutoScalingReplacingUpdate": {
                  "WillReplace": "true"
              }
          }
      },
      "ContainerInstances": {
          "Type": "AWS::EC2::LaunchTemplate",
          "Properties": {
              "LaunchTemplateName": "asg-launch-template",
              "LaunchTemplateData": {
                  "ImageId": {
                      "Ref": "ECSAMI"
                  },
                  "InstanceType": {
                      "Ref": "InstanceType"
                  },
                  "IamInstanceProfile": {
                      "Name": {
                          "Ref": "EC2InstanceProfile"
                      }
                  },
                  "SecurityGroupIds": [
                      {
                          "Ref": "ContainerHostSecurityGroup"
                      }
                  ],
                  "UserData": {
                      "Fn::Base64": {
                          "Fn::Sub": "#!/bin/bash -xe\n echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config\n yum install -y aws-cfn-bootstrap\n /opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource ContainerInstances --configsets full_install --region ${AWS::Region} &\n"
                      }
                  },
                  "MetadataOptions": {
                      "HttpEndpoint": "enabled",
                      "HttpTokens": "required"
                  }
              }
          }
      },
      "EC2InstanceProfile": {
          "Type": "AWS::IAM::InstanceProfile",
          "Properties": {
              "Path": "/",
              "Roles": [
                  {
                      "Ref": "EC2Role"
                  }
              ]
          }
      },
      "CapacityProvider": {
          "Type": "AWS::ECS::CapacityProvider",
          "Properties": {
              "AutoScalingGroupProvider": {
                  "AutoScalingGroupArn": {
                      "Ref": "ECSAutoScalingGroup"
                  },
                  "ManagedScaling": {
                      "InstanceWarmupPeriod": 60,
                      "MinimumScalingStepSize": 1,
                      "MaximumScalingStepSize": 100,
                      "Status": "ENABLED",
                      "TargetCapacity": 100
                  },
                  "ManagedTerminationProtection": "ENABLED"
              }
          }
      },
      "CapacityProviderAssociation": {
          "Type": "AWS::ECS::ClusterCapacityProviderAssociations",
          "Properties": {
              "CapacityProviders": [
                  {
                      "Ref": "CapacityProvider"
                  }
              ],
              "Cluster": {
                  "Ref": "ECSCluster"
              },
              "DefaultCapacityProviderStrategy": [
                  {
                      "Base": 0,
                      "CapacityProvider": {
                          "Ref": "CapacityProvider"
                      },
                      "Weight": 1
                  }
              ]
          }
      },
      "ContainerHostSecurityGroup": {
          "Type": "AWS::EC2::SecurityGroup",
          "Properties": {
              "GroupDescription": "Access to the EC2 hosts that run containers",
              "VpcId": {
                  "Ref": "VpcId"
              }
          }
      },
      "EC2Role": {
          "Type": "AWS::IAM::Role",
          "Properties": {
              "AssumeRolePolicyDocument": {
                  "Statement": [
                      {
                          "Effect": "Allow",
                          "Principal": {
                              "Service": [
                                  "ec2.amazonaws.com"
                              ]
                          },
                          "Action": [
                              "sts:AssumeRole"
                          ]
                      }
                  ]
              },
              "Path": "/",
              "ManagedPolicyArns": [
                  "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role",
                  "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
              ]
          }
      },
      "ECSTaskExecutionRole": {
          "Type": "AWS::IAM::Role",
          "Properties": {
              "AssumeRolePolicyDocument": {
                  "Statement": [
                      {
                          "Effect": "Allow",
                          "Principal": {
                              "Service": [
                                  "ecs-tasks.amazonaws.com"
                              ]
                          },
                          "Action": [
                              "sts:AssumeRole"
                          ],
                          "Condition": {
                              "ArnLike": {
                                  "aws:SourceArn": {
                                      "Fn::Sub": "arn:${AWS::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:*"
                                  }
                              },
                              "StringEquals": {
                                  "aws:SourceAccount": {
                                        "Fn::Sub": "${AWS::AccountId}"
                                    }
                              }
                          }
                      }
                  ]
              },
              "Path": "/",
              "ManagedPolicyArns": [
                  "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
              ]
          }
      }
  },
  "Outputs": {
      "ClusterName": {
          "Description": "The ECS cluster into which to launch resources",
          "Value": "ECSCluster"
      },
      "ECSTaskExecutionRole": {
          "Description": "The role used to start up a task",
          "Value": "ECSTaskExecutionRole"
      },
      "CapacityProvider": {
          "Description": "The cluster capacity provider that the service should use to request capacity when it wants to start up a task",
          "Value": "CapacityProvider"
      }
  }
}
```

### YAML
<a name="quickref-ecs-example-1.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Description: EC2 ECS cluster that starts out empty, with no EC2 instances yet.
  An ECS capacity provider automatically launches more EC2 instances as required
  on the fly when you request ECS to launch services or standalone tasks.
Parameters:
  InstanceType:
    Type: String
    Description: EC2 instance type
    Default: "t2.medium"
    AllowedValues:
      - t1.micro
      - t2.2xlarge
      - t2.large
      - t2.medium
      - t2.micro
      - t2.nano
      - t2.small
      - t2.xlarge
      - t3.2xlarge
      - t3.large
      - t3.medium
      - t3.micro
      - t3.nano
      - t3.small
      - t3.xlarge
  DesiredCapacity:
    Type: Number
    Default: "0"
    Description: Number of EC2 instances to launch in your ECS cluster.
  MaxSize:
    Type: Number
    Default: "100"
    Description: Maximum number of EC2 instances that can be launched in your ECS cluster.
  ECSAMI:
    Description: The Amazon Machine Image ID used for the cluster
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id
  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: VPC ID where the ECS cluster is launched
    Default: vpc-1234567890abcdef0
  SubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
    Description: List of subnet IDs where the EC2 instances will be launched
    Default: "subnet-021345abcdef67890"
Resources:
# This is authorizes ECS to manage resources on your
  # account on your behalf. This role is likely already created on your account
  # ECSRole:
  #  Type: AWS::IAM::ServiceLinkedRole
  #  Properties:
  #    AWSServiceName: 'ecs.amazonaws.com'
  
   # ECS Resources
  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterSettings:
        - Name: containerInsights
          Value: enabled
  
  # Autoscaling group. This launches the actual EC2 instances that will register
  # themselves as members of the cluster, and run the docker containers.
  ECSAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    DependsOn:
      # This is to ensure that the ASG gets deleted first before these
    # resources, when it comes to stack teardown.
      - ECSCluster
      - EC2Role
    Properties:
      VPCZoneIdentifier:
        Ref: SubnetIds
      LaunchTemplate:
        LaunchTemplateId: !Ref ContainerInstances
        Version: !GetAtt ContainerInstances.LatestVersionNumber
      MinSize: 0
      MaxSize:
        Ref: MaxSize
      DesiredCapacity:
        Ref: DesiredCapacity
      NewInstancesProtectedFromScaleIn: true
    UpdatePolicy:
      AutoScalingReplacingUpdate:
        WillReplace: "true"
  # The config for each instance that is added to the cluster
  ContainerInstances:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateName: "asg-launch-template"
      LaunchTemplateData:
        ImageId:
          Ref: ECSAMI
        InstanceType:
          Ref: InstanceType
        IamInstanceProfile:
          Name: !Ref EC2InstanceProfile
        SecurityGroupIds:
          - !Ref ContainerHostSecurityGroup
        # This injected configuration file is how the EC2 instance
      # knows which ECS cluster on your AWS account it should be joining
        UserData:
          Fn::Base64: !Sub |
           #!/bin/bash -xe
            echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
            yum install -y aws-cfn-bootstrap
            /opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource ContainerInstances --configsets full_install --region ${AWS::Region} &
         # Disable IMDSv1, and require IMDSv2
        MetadataOptions:
          HttpEndpoint: enabled
          HttpTokens: required
  EC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles: 
      - !Ref EC2Role 
  # Create an ECS capacity provider to attach the ASG to the ECS cluster
  # so that it autoscales as we launch more containers
  CapacityProvider:
    Type: AWS::ECS::CapacityProvider
    Properties:
      AutoScalingGroupProvider:
        AutoScalingGroupArn: !Ref ECSAutoScalingGroup
        ManagedScaling:
          InstanceWarmupPeriod: 60
          MinimumScalingStepSize: 1
          MaximumScalingStepSize: 100
          Status: ENABLED
          # Percentage of cluster reservation to try to maintain
          TargetCapacity: 100
        ManagedTerminationProtection: ENABLED
   # Create a cluster capacity provider assocation so that the cluster
  # will use the capacity provider
  CapacityProviderAssociation:
    Type: AWS::ECS::ClusterCapacityProviderAssociations
    Properties:
      CapacityProviders:
        - !Ref CapacityProvider
      Cluster: !Ref ECSCluster
      DefaultCapacityProviderStrategy:
        - Base: 0
          CapacityProvider: !Ref CapacityProvider
          Weight: 1
  # A security group for the EC2 hosts that will run the containers.
  # This can be used to limit incoming traffic to or outgoing traffic
  # from the container's host EC2 instance.
  ContainerHostSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Access to the EC2 hosts that run containers
      VpcId:
        Ref: VpcId
  # Role for the EC2 hosts. This allows the ECS agent on the EC2 hosts
  # to communciate with the ECS control plane, as well as download the docker
  # images from ECR to run on your host.
  EC2Role:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
      # See reference: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonEC2ContainerServiceforEC2Role
        - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
      # This managed policy allows us to connect to the instance using SSM
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
  # This is a role which is used within Fargate to allow the Fargate agent
  # to download images, and upload logs.
  ECSTaskExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ecs-tasks.amazonaws.com
            Action:
              - sts:AssumeRole
            Condition:
              ArnLike:
                aws:SourceArn: !Sub arn:${AWS::Partition}:ecs:${AWS::Region}:${AWS::AccountId}:*
              StringEquals:
                aws:SourceAccount: !Sub ${AWS::AccountId}
      Path: /
      # This role enables all features of ECS. See reference:
    # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonECSTaskExecutionRolePolicy
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Outputs:
  ClusterName:
    Description: The ECS cluster into which to launch resources
    Value: ECSCluster
  ECSTaskExecutionRole:
    Description: The role used to start up a task
    Value: ECSTaskExecutionRole
  CapacityProvider:
    Description: The cluster capacity provider that the service should use to
      request capacity when it wants to start up a task
    Value: CapacityProvider
```

## 서비스를 배포합니다.
<a name="create-service"></a>

다음 템플릿은 용량 공급자를 통해 실행할 AL2023 용량을 요청하는 서비스를 정의합니다. 컨테이너가 온라인 상태가 되면 AL2023 인스턴스에서 실행됩니다.

### JSON
<a name="quickref-ecs-example-2.json"></a>

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "An example service that deploys in AWS VPC networking mode on EC2 capacity. Service uses a capacity provider to request EC2 instances to run on. Service runs with networking in private subnets, but still accessible to the internet via a load balancer hosted in public subnets.",
  "Parameters": {
      "VpcId": {
          "Type": "String",
          "Description": "The VPC that the service is running inside of"
      },
      "PublicSubnetIds": {
          "Type": "List<AWS::EC2::Subnet::Id>",
          "Description": "List of public subnet ID's to put the load balancer in"
      },
      "PrivateSubnetIds": {
          "Type": "List<AWS::EC2::Subnet::Id>",
          "Description": "List of private subnet ID's that the AWS VPC tasks are in"
      },
      "ClusterName": {
          "Type": "String",
          "Description": "The name of the ECS cluster into which to launch capacity."
      },
      "ECSTaskExecutionRole": {
          "Type": "String",
          "Description": "The role used to start up an ECS task"
      },
      "CapacityProvider": {
          "Type": "String",
          "Description": "The cluster capacity provider that the service should use to request capacity when it wants to start up a task"
      },
      "ServiceName": {
          "Type": "String",
          "Default": "web",
          "Description": "A name for the service"
      },
      "ImageUrl": {
          "Type": "String",
          "Default": "public.ecr.aws/docker/library/nginx:latest",
          "Description": "The url of a docker image that contains the application process that will handle the traffic for this service"
      },
      "ContainerCpu": {
          "Type": "Number",
          "Default": 256,
          "Description": "How much CPU to give the container. 1024 is 1 CPU"
      },
      "ContainerMemory": {
          "Type": "Number",
          "Default": 512,
          "Description": "How much memory in megabytes to give the container"
      },
      "ContainerPort": {
          "Type": "Number",
          "Default": 80,
          "Description": "What port that the application expects traffic on"
      },
      "DesiredCount": {
          "Type": "Number",
          "Default": 2,
          "Description": "How many copies of the service task to run"
      }
  },
  "Resources": {
      "TaskDefinition": {
          "Type": "AWS::ECS::TaskDefinition",
          "Properties": {
              "Family": {
                  "Ref": "ServiceName"
              },
              "Cpu": {
                  "Ref": "ContainerCpu"
              },
              "Memory": {
                  "Ref": "ContainerMemory"
              },
              "NetworkMode": "awsvpc",
              "RequiresCompatibilities": [
                  "EC2"
              ],
              "ExecutionRoleArn": {
                  "Ref": "ECSTaskExecutionRole"
              },
              "ContainerDefinitions": [
                  {
                      "Name": {
                          "Ref": "ServiceName"
                      },
                      "Cpu": {
                          "Ref": "ContainerCpu"
                      },
                      "Memory": {
                          "Ref": "ContainerMemory"
                      },
                      "Image": {
                          "Ref": "ImageUrl"
                      },
                      "PortMappings": [
                          {
                              "ContainerPort": {
                                  "Ref": "ContainerPort"
                              },
                              "HostPort": {
                                  "Ref": "ContainerPort"
                              }
                          }
                      ],
                      "LogConfiguration": {
                          "LogDriver": "awslogs",
                          "Options": {
                              "mode": "non-blocking",
                              "max-buffer-size": "25m",
                              "awslogs-group": {
                                  "Ref": "LogGroup"
                              },
                              "awslogs-region": {
                                  "Ref": "AWS::Region"
                              },
                              "awslogs-stream-prefix": {
                                  "Ref": "ServiceName"
                              }
                          }
                      }
                  }
              ]
          }
      },
      "Service": {
          "Type": "AWS::ECS::Service",
          "DependsOn": "PublicLoadBalancerListener",
          "Properties": {
              "ServiceName": {
                  "Ref": "ServiceName"
              },
              "Cluster": {
                  "Ref": "ClusterName"
              },
              "PlacementStrategies": [
                  {
                      "Field": "attribute:ecs.availability-zone",
                      "Type": "spread"
                  },
                  {
                      "Field": "cpu",
                      "Type": "binpack"
                  }
              ],
              "CapacityProviderStrategy": [
                  {
                      "Base": 0,
                      "CapacityProvider": {
                          "Ref": "CapacityProvider"
                      },
                      "Weight": 1
                  }
              ],
              "NetworkConfiguration": {
                  "AwsvpcConfiguration": {
                      "SecurityGroups": [
                          {
                              "Ref": "ServiceSecurityGroup"
                          }
                      ],
                      "Subnets": {
                          "Ref": "PrivateSubnetIds"
                      }
                  }
              },
              "DeploymentConfiguration": {
                  "MaximumPercent": 200,
                  "MinimumHealthyPercent": 75
              },
              "DesiredCount": {
                  "Ref": "DesiredCount"
              },
              "TaskDefinition": {
                  "Ref": "TaskDefinition"
              },
              "LoadBalancers": [
                  {
                      "ContainerName": {
                          "Ref": "ServiceName"
                      },
                      "ContainerPort": {
                          "Ref": "ContainerPort"
                      },
                      "TargetGroupArn": {
                          "Ref": "ServiceTargetGroup"
                      }
                  }
              ]
          }
      },
      "ServiceSecurityGroup": {
          "Type": "AWS::EC2::SecurityGroup",
          "Properties": {
              "GroupDescription": "Security group for service",
              "VpcId": {
                  "Ref": "VpcId"
              }
          }
      },
      "ServiceTargetGroup": {
          "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
          "Properties": {
              "HealthCheckIntervalSeconds": 6,
              "HealthCheckPath": "/",
              "HealthCheckProtocol": "HTTP",
              "HealthCheckTimeoutSeconds": 5,
              "HealthyThresholdCount": 2,
              "TargetType": "ip",
              "Port": {
                  "Ref": "ContainerPort"
              },
              "Protocol": "HTTP",
              "UnhealthyThresholdCount": 10,
              "VpcId": {
                  "Ref": "VpcId"
              },
              "TargetGroupAttributes": [
                  {
                      "Key": "deregistration_delay.timeout_seconds",
                      "Value": 0
                  }
              ]
          }
      },
      "PublicLoadBalancerSG": {
          "Type": "AWS::EC2::SecurityGroup",
          "Properties": {
              "GroupDescription": "Access to the public facing load balancer",
              "VpcId": {
                  "Ref": "VpcId"
              },
              "SecurityGroupIngress": [
                  {
                      "CidrIp": "0.0.0.0/0",
                      "IpProtocol": -1
                  }
              ]
          }
      },
      "PublicLoadBalancer": {
          "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
          "Properties": {
              "Scheme": "internet-facing",
              "LoadBalancerAttributes": [
                  {
                      "Key": "idle_timeout.timeout_seconds",
                      "Value": "30"
                  }
              ],
              "Subnets": {
                  "Ref": "PublicSubnetIds"
              },
              "SecurityGroups": [
                  {
                      "Ref": "PublicLoadBalancerSG"
                  }
              ]
          }
      },
      "PublicLoadBalancerListener": {
          "Type": "AWS::ElasticLoadBalancingV2::Listener",
          "Properties": {
              "DefaultActions": [
                  {
                      "Type": "forward",
                      "ForwardConfig": {
                          "TargetGroups": [
                              {
                                  "TargetGroupArn": {
                                      "Ref": "ServiceTargetGroup"
                                  },
                                  "Weight": 100
                              }
                          ]
                      }
                  }
              ],
              "LoadBalancerArn": {
                  "Ref": "PublicLoadBalancer"
              },
              "Port": 80,
              "Protocol": "HTTP"
          }
      },
      "ServiceIngressfromLoadBalancer": {
          "Type": "AWS::EC2::SecurityGroupIngress",
          "Properties": {
              "Description": "Ingress from the public ALB",
              "GroupId": {
                  "Ref": "ServiceSecurityGroup"
              },
              "IpProtocol": -1,
              "SourceSecurityGroupId": {
                  "Ref": "PublicLoadBalancerSG"
              }
          }
      },
      "LogGroup": {
          "Type": "AWS::Logs::LogGroup"
      }
  }
}
```

### YAML
<a name="quickref-ecs-example-2.yaml"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Description: >-
  An example service that deploys in AWS VPC networking mode on EC2 capacity.
  Service uses a capacity provider to request EC2 instances to run on. Service
  runs with networking in private subnets, but still accessible to the internet
  via a load balancer hosted in public subnets.
Parameters:
  VpcId:
    Type: String
    Description: The VPC that the service is running inside of
  PublicSubnetIds:
    Type: 'List<AWS::EC2::Subnet::Id>'
    Description: List of public subnet ID's to put the load balancer in
  PrivateSubnetIds:
    Type: 'List<AWS::EC2::Subnet::Id>'
    Description: List of private subnet ID's that the AWS VPC tasks are in
  ClusterName:
    Type: String
    Description: The name of the ECS cluster into which to launch capacity.
  ECSTaskExecutionRole:
    Type: String
    Description: The role used to start up an ECS task
  CapacityProvider:
    Type: String
    Description: >-
      The cluster capacity provider that the service should use to request
      capacity when it wants to start up a task
  ServiceName:
    Type: String
    Default: web
    Description: A name for the service
  ImageUrl:
    Type: String
    Default: 'public.ecr.aws/docker/library/nginx:latest'
    Description: >-
      The url of a docker image that contains the application process that will
      handle the traffic for this service
  ContainerCpu:
    Type: Number
    Default: 256
    Description: How much CPU to give the container. 1024 is 1 CPU
  ContainerMemory:
    Type: Number
    Default: 512
    Description: How much memory in megabytes to give the container
  ContainerPort:
    Type: Number
    Default: 80
    Description: What port that the application expects traffic on
  DesiredCount:
    Type: Number
    Default: 2
    Description: How many copies of the service task to run
Resources:
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: !Ref ServiceName
      Cpu: !Ref ContainerCpu
      Memory: !Ref ContainerMemory
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - EC2
      ExecutionRoleArn: !Ref ECSTaskExecutionRole
      ContainerDefinitions:
        - Name: !Ref ServiceName
          Cpu: !Ref ContainerCpu
          Memory: !Ref ContainerMemory
          Image: !Ref ImageUrl
          PortMappings:
            - ContainerPort: !Ref ContainerPort
              HostPort: !Ref ContainerPort
          LogConfiguration:
            LogDriver: awslogs
            Options:
              mode: non-blocking
              max-buffer-size: 25m
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: !Ref ServiceName
  Service:
    Type: AWS::ECS::Service
    DependsOn: PublicLoadBalancerListener
    Properties:
      ServiceName: !Ref ServiceName
      Cluster: !Ref ClusterName
      PlacementStrategies:
        - Field: 'attribute:ecs.availability-zone'
          Type: spread
        - Field: cpu
          Type: binpack
      CapacityProviderStrategy:
        - Base: 0
          CapacityProvider: !Ref CapacityProvider
          Weight: 1
      NetworkConfiguration:
        AwsvpcConfiguration:
          SecurityGroups:
            - !Ref ServiceSecurityGroup
          Subnets: !Ref PrivateSubnetIds
      DeploymentConfiguration:
        MaximumPercent: 200
        MinimumHealthyPercent: 75
      DesiredCount: !Ref DesiredCount
      TaskDefinition: !Ref TaskDefinition
      LoadBalancers:
        - ContainerName: !Ref ServiceName
          ContainerPort: !Ref ContainerPort
          TargetGroupArn: !Ref ServiceTargetGroup
  ServiceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for service
      VpcId: !Ref VpcId
  ServiceTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      HealthCheckIntervalSeconds: 6
      HealthCheckPath: /
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 2
      TargetType: ip
      Port: !Ref ContainerPort
      Protocol: HTTP
      UnhealthyThresholdCount: 10
      VpcId: !Ref VpcId
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: 0
  PublicLoadBalancerSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Access to the public facing load balancer
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: -1
  PublicLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Scheme: internet-facing
      LoadBalancerAttributes:
        - Key: idle_timeout.timeout_seconds
          Value: '30'
      Subnets: !Ref PublicSubnetIds
      SecurityGroups:
        - !Ref PublicLoadBalancerSG
  PublicLoadBalancerListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          ForwardConfig:
            TargetGroups:
              - TargetGroupArn: !Ref ServiceTargetGroup
                Weight: 100
      LoadBalancerArn: !Ref PublicLoadBalancer
      Port: 80
      Protocol: HTTP
  ServiceIngressfromLoadBalancer:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      Description: Ingress from the public ALB
      GroupId: !Ref ServiceSecurityGroup
      IpProtocol: -1
      SourceSecurityGroupId: !Ref PublicLoadBalancerSG
  LogGroup:
    Type: AWS::Logs::LogGroup
```

# Amazon Elastic File System 샘플 템플릿
<a name="quickref-efs"></a>

Amazon Elastic File System(Amazon EFS)는 Amazon Elastic Compute Cloud(Amazon EC2) 인스턴스에 대한 파일 스토리지 서비스입니다. Amazon EFS를 사용하면 파일을 추가하고 제거할 때마다 스토리지 용량이 자동으로 확장 및 축소되므로 애플리케이션에서 스토리지가 필요할 때 확보할 수 있습니다.

다음 샘플 템플릿은 Amazon EFS 파일 시스템과 연결되는 EC2 인스턴스를 Auto Scaling 그룹에 배포합니다. 인스턴스를 파일 시스템과 연결하기 위해 인스턴스에서 cfn-init 헬퍼 스크립트를 실행합니다. 그러면 헬퍼 스크립트에서 `nfs-utils` yum 패키지를 다운로드하여 설치하고, 새 디렉터리를 생성한 다음 파일 시스템의 DNS 이름을 사용하여 해당 디렉터리에 파일 시스템을 탑재합니다. 파일 시스템의 DNS 이름은 Amazon EC2 인스턴스의 가용 영역에서 탑재 대상의 IP 주소를 확인합니다. DNS 이름 구조에 대한 자세한 내용을 알아보려면 *Amazon Elastic File System User Guide*(Amazon Elastic File System 사용 설명서)의 [Mounting File Systems](https://docs.aws.amazon.com/efs/latest/ug/mounting-fs.html)(EFS 파일 시스템 탑재)를 참조하세요.

네트워크 파일 시스템 활동을 측정하기 위해 템플릿에 사용자 지정 Amazon CloudWatch 지표가 포함되어 있습니다. 또한 템플릿은 VPC, 서브넷 및 보안 그룹을 생성합니다. 인스턴스가 파일 시스템과 통신하도록 허용하려면 VPC에서 DNS를 활성화하고 탑재 대상과 EC2 인스턴스가 동일한 가용 영역(AZ)에 있어야 합니다. 가용 영역은 서브넷에 의해 지정됩니다.

탑재 대상의 보안 그룹은 TCP 포트 2049에 대한 네트워크 연결을 활성화합니다. NFSv4 클라이언트가 파일 시스템을 탑재하려면 네트워크 연결이 필요합니다. EC2 인스턴스 및 탑재 대상의 보안 그룹에 대한 자세한 내용을 알아보려면 [https://docs.aws.amazon.com/efs/latest/ug/](https://docs.aws.amazon.com/efs/latest/ug/)(Amazon Elastic File System 사용 설명서)의 [Security](https://docs.aws.amazon.com/efs/latest/ug/security-considerations.html)(보안)를 참조하세요.

**참고**  
탑재 대상을 업데이트하여 대체될 경우 연결된 파일 시스템을 사용하는 인스턴스 또는 애플리케이션이 중단될 수 있습니다. 그러면 작성한 커밋되지 않은 내용이 손실될 수 있습니다. 중단을 방지하려면 원하는 용량을 0으로 설정하여 탑재 대상을 업데이트할 때 인스턴스를 중지합니다. 그러면 탑재 대상이 삭제되기 이전에 인스턴스에서 파일 시스템의 탑재를 해제할 수 있습니다. 탑재 업데이트가 완료된 이후에 원하는 용량을 설정하여 후속 업데이트에서 인스턴스를 시작합니다.

## JSON
<a name="quickref-efs-example-1.json"></a>

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "This template creates an Amazon EFS file system and mount target and associates it with Amazon EC2 instances in an Auto Scaling group. **WARNING** This template creates Amazon EC2 instances and related resources. You will be billed for the AWS resources used if you create a stack from this template.",
  "Parameters": {
    "InstanceType" : {
      "Description" : "WebServer EC2 instance type",
      "Type" : "String",
      "Default" : "t2.small",
      "AllowedValues" : [ 
        "t1.micro", 
        "t2.nano", 
        "t2.micro", 
        "t2.small", 
        "t2.medium", 
        "t2.large", 
        "m1.small", 
        "m1.medium", 
        "m1.large", 
        "m1.xlarge", 
        "m2.xlarge", 
        "m2.2xlarge", 
        "m2.4xlarge", 
        "m3.medium", 
        "m3.large", 
        "m3.xlarge", 
        "m3.2xlarge", 
        "m4.large", 
        "m4.xlarge", 
        "m4.2xlarge", 
        "m4.4xlarge", 
        "m4.10xlarge", 
        "c1.medium", 
        "c1.xlarge", 
        "c3.large", 
        "c3.xlarge", 
        "c3.2xlarge", 
        "c3.4xlarge", 
        "c3.8xlarge", 
        "c4.large", 
        "c4.xlarge", 
        "c4.2xlarge", 
        "c4.4xlarge", 
        "c4.8xlarge", 
        "g2.2xlarge", 
        "g2.8xlarge", 
        "r3.large", 
        "r3.xlarge", 
        "r3.2xlarge", 
        "r3.4xlarge", 
        "r3.8xlarge", 
        "i2.xlarge", 
        "i2.2xlarge", 
        "i2.4xlarge", 
        "i2.8xlarge", 
        "d2.xlarge", 
        "d2.2xlarge", 
        "d2.4xlarge", 
        "d2.8xlarge", 
        "hi1.4xlarge", 
        "hs1.8xlarge", 
        "cr1.8xlarge", 
        "cc2.8xlarge", 
        "cg1.4xlarge"
      ],
      "ConstraintDescription" : "must be a valid EC2 instance type."
    },
    "KeyName": {
      "Type": "AWS::EC2::KeyPair::KeyName",
      "Description": "Name of an existing EC2 key pair to enable SSH access to the EC2 instances"
    },
    "AsgMaxSize": {
      "Type": "Number",
      "Description": "Maximum size and initial desired capacity of Auto Scaling Group",
      "Default": "2"
    },
    "SSHLocation" : {
      "Description" : "The IP address range that can be used to connect to the EC2 instances by using SSH",
      "Type": "String",
      "MinLength": "9",
      "MaxLength": "18",
      "Default": "0.0.0.0/0",
      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
      "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
    },
    "VolumeName" : {
      "Description" : "The name to be used for the EFS volume",
      "Type": "String",
      "MinLength": "1",
      "Default": "myEFSvolume"
    },
    "MountPoint" : {
      "Description" : "The Linux mount point for the EFS volume",
      "Type": "String",
      "MinLength": "1",
      "Default": "myEFSvolume"
    }
  },
  "Mappings" : {
    "AWSInstanceType2Arch" : {
      "t1.micro"    : { "Arch" : "HVM64"  },
      "t2.nano"     : { "Arch" : "HVM64"  },
      "t2.micro"    : { "Arch" : "HVM64"  },
      "t2.small"    : { "Arch" : "HVM64"  },
      "t2.medium"   : { "Arch" : "HVM64"  },
      "t2.large"    : { "Arch" : "HVM64"  },
      "m1.small"    : { "Arch" : "HVM64"  },
      "m1.medium"   : { "Arch" : "HVM64"  },
      "m1.large"    : { "Arch" : "HVM64"  },
      "m1.xlarge"   : { "Arch" : "HVM64"  },
      "m2.xlarge"   : { "Arch" : "HVM64"  },
      "m2.2xlarge"  : { "Arch" : "HVM64"  },
      "m2.4xlarge"  : { "Arch" : "HVM64"  },
      "m3.medium"   : { "Arch" : "HVM64"  },
      "m3.large"    : { "Arch" : "HVM64"  },
      "m3.xlarge"   : { "Arch" : "HVM64"  },
      "m3.2xlarge"  : { "Arch" : "HVM64"  },
      "m4.large"    : { "Arch" : "HVM64"  },
      "m4.xlarge"   : { "Arch" : "HVM64"  },
      "m4.2xlarge"  : { "Arch" : "HVM64"  },
      "m4.4xlarge"  : { "Arch" : "HVM64"  },
      "m4.10xlarge" : { "Arch" : "HVM64"  },
      "c1.medium"   : { "Arch" : "HVM64"  },
      "c1.xlarge"   : { "Arch" : "HVM64"  },
      "c3.large"    : { "Arch" : "HVM64"  },
      "c3.xlarge"   : { "Arch" : "HVM64"  },
      "c3.2xlarge"  : { "Arch" : "HVM64"  },
      "c3.4xlarge"  : { "Arch" : "HVM64"  },
      "c3.8xlarge"  : { "Arch" : "HVM64"  },
      "c4.large"    : { "Arch" : "HVM64"  },
      "c4.xlarge"   : { "Arch" : "HVM64"  },
      "c4.2xlarge"  : { "Arch" : "HVM64"  },
      "c4.4xlarge"  : { "Arch" : "HVM64"  },
      "c4.8xlarge"  : { "Arch" : "HVM64"  },
      "g2.2xlarge"  : { "Arch" : "HVMG2"  },
      "g2.8xlarge"  : { "Arch" : "HVMG2"  },
      "r3.large"    : { "Arch" : "HVM64"  },
      "r3.xlarge"   : { "Arch" : "HVM64"  },
      "r3.2xlarge"  : { "Arch" : "HVM64"  },
      "r3.4xlarge"  : { "Arch" : "HVM64"  },
      "r3.8xlarge"  : { "Arch" : "HVM64"  },
      "i2.xlarge"   : { "Arch" : "HVM64"  },
      "i2.2xlarge"  : { "Arch" : "HVM64"  },
      "i2.4xlarge"  : { "Arch" : "HVM64"  },
      "i2.8xlarge"  : { "Arch" : "HVM64"  },
      "d2.xlarge"   : { "Arch" : "HVM64"  },
      "d2.2xlarge"  : { "Arch" : "HVM64"  },
      "d2.4xlarge"  : { "Arch" : "HVM64"  },
      "d2.8xlarge"  : { "Arch" : "HVM64"  },
      "hi1.4xlarge" : { "Arch" : "HVM64"  },
      "hs1.8xlarge" : { "Arch" : "HVM64"  },
      "cr1.8xlarge" : { "Arch" : "HVM64"  },
      "cc2.8xlarge" : { "Arch" : "HVM64"  }
    },
    "AWSRegionArch2AMI" : {
      "us-east-1"        : {"HVM64" : "ami-0ff8a91507f77f867", "HVMG2" : "ami-0a584ac55a7631c0c"},
      "us-west-2"        : {"HVM64" : "ami-a0cfeed8", "HVMG2" : "ami-0e09505bc235aa82d"},
      "us-west-1"        : {"HVM64" : "ami-0bdb828fd58c52235", "HVMG2" : "ami-066ee5fd4a9ef77f1"},
      "eu-west-1"        : {"HVM64" : "ami-047bb4163c506cd98", "HVMG2" : "ami-0a7c483d527806435"},
      "eu-west-2"        : {"HVM64" : "ami-f976839e", "HVMG2" : "NOT_SUPPORTED"},
      "eu-west-3"        : {"HVM64" : "ami-0ebc281c20e89ba4b", "HVMG2" : "NOT_SUPPORTED"},
      "eu-central-1"     : {"HVM64" : "ami-0233214e13e500f77", "HVMG2" : "ami-06223d46a6d0661c7"},
      "ap-northeast-1"   : {"HVM64" : "ami-06cd52961ce9f0d85", "HVMG2" : "ami-053cdd503598e4a9d"},
      "ap-northeast-2"   : {"HVM64" : "ami-0a10b2721688ce9d2", "HVMG2" : "NOT_SUPPORTED"},
      "ap-northeast-3"   : {"HVM64" : "ami-0d98120a9fb693f07", "HVMG2" : "NOT_SUPPORTED"},
      "ap-southeast-1"   : {"HVM64" : "ami-08569b978cc4dfa10", "HVMG2" : "ami-0be9df32ae9f92309"},
      "ap-southeast-2"   : {"HVM64" : "ami-09b42976632b27e9b", "HVMG2" : "ami-0a9ce9fecc3d1daf8"},
      "ap-south-1"       : {"HVM64" : "ami-0912f71e06545ad88", "HVMG2" : "ami-097b15e89dbdcfcf4"},
      "us-east-2"        : {"HVM64" : "ami-0b59bfac6be064b78", "HVMG2" : "NOT_SUPPORTED"},
      "ca-central-1"     : {"HVM64" : "ami-0b18956f", "HVMG2" : "NOT_SUPPORTED"},
      "sa-east-1"        : {"HVM64" : "ami-07b14488da8ea02a0", "HVMG2" : "NOT_SUPPORTED"},
      "cn-north-1"       : {"HVM64" : "ami-0a4eaf6c4454eda75", "HVMG2" : "NOT_SUPPORTED"},
      "cn-northwest-1"   : {"HVM64" : "ami-6b6a7d09", "HVMG2" : "NOT_SUPPORTED"}
    }
  },
  "Resources": {
    "CloudWatchPutMetricsRole" : {
      "Type"  : "AWS::IAM::Role",
      "Properties" : {
          "AssumeRolePolicyDocument" : {
              "Statement" : [ {
                  "Effect" : "Allow",
                  "Principal" : {
                      "Service" : [ "ec2.amazonaws.com" ]
                  },
                  "Action" : [ "sts:AssumeRole" ]
              } ]
          },
          "Path" : "/"
      }
    },
    "CloudWatchPutMetricsRolePolicy" : {
        "Type" : "AWS::IAM::Policy",
        "Properties" : {
            "PolicyName" : "CloudWatch_PutMetricData",
            "PolicyDocument" : {
              "Version": "2012-10-17",		 	 	 
              "Statement": [
                {
                  "Sid": "CloudWatchPutMetricData",
                  "Effect": "Allow",
                  "Action": ["cloudwatch:PutMetricData"],
                  "Resource": ["*"]
                }
              ]
            },
            "Roles" : [ { "Ref" : "CloudWatchPutMetricsRole" } ]
        }
    },
    "CloudWatchPutMetricsInstanceProfile" : {
      "Type" : "AWS::IAM::InstanceProfile",
      "Properties" : {
        "Path" : "/",
        "Roles" : [ { "Ref" : "CloudWatchPutMetricsRole" } ]
      }
    },
    "VPC": {
      "Type": "AWS::EC2::VPC",
      "Properties": {
        "EnableDnsSupport" : "true",
        "EnableDnsHostnames" : "true",
        "CidrBlock": "10.0.0.0/16",
        "Tags": [ {"Key": "Application", "Value": { "Ref": "AWS::StackId"} } ]
      }
    },
    "InternetGateway" : {
      "Type" : "AWS::EC2::InternetGateway",
      "Properties" : {
        "Tags" : [
          { "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } },
          { "Key" : "Network", "Value" : "Public" }
        ]
      }
    },
    "GatewayToInternet" : {
      "Type" : "AWS::EC2::VPCGatewayAttachment",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "InternetGatewayId" : { "Ref" : "InternetGateway" }
      }
    },
    "RouteTable":{
      "Type":"AWS::EC2::RouteTable",
      "Properties":{
        "VpcId": {"Ref":"VPC"}
      }
    },
    "SubnetRouteTableAssoc": {
      "Type" : "AWS::EC2::SubnetRouteTableAssociation",
      "Properties" : {
        "RouteTableId" : {"Ref":"RouteTable"},
        "SubnetId" : {"Ref":"Subnet"}
      }
    },
    "InternetGatewayRoute": {
        "Type":"AWS::EC2::Route",
        "Properties":{
            "DestinationCidrBlock":"0.0.0.0/0",
            "RouteTableId":{"Ref":"RouteTable"},
            "GatewayId":{"Ref":"InternetGateway"}
        }
    },
    "Subnet": {
      "Type": "AWS::EC2::Subnet",
      "Properties": {
        "VpcId": { "Ref": "VPC" },
        "CidrBlock": "10.0.0.0/24",
        "Tags": [ { "Key": "Application", "Value": { "Ref": "AWS::StackId" } } ]
      }
    },    
    "InstanceSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "VpcId": { "Ref": "VPC" },
        "GroupDescription": "Enable SSH access via port 22",
        "SecurityGroupIngress": [
          { "IpProtocol": "tcp", "FromPort": 22, "ToPort": 22, "CidrIp": { "Ref": "SSHLocation" } },
          { "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "CidrIp": "0.0.0.0/0" }
         ]
      }
    },
    "MountTargetSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "VpcId": { "Ref": "VPC" },
        "GroupDescription": "Security group for mount target",
        "SecurityGroupIngress": [
          {
            "IpProtocol": "tcp",
            "FromPort": 2049,
            "ToPort": 2049,
            "CidrIp": "0.0.0.0/0"
          }
        ]
      }
    },
    "FileSystem": {
      "Type": "AWS::EFS::FileSystem",
      "Properties": {
        "PerformanceMode": "generalPurpose",
        "FileSystemTags": [
          {
            "Key": "Name",
            "Value": { "Ref" : "VolumeName" }
          }
        ]
      }
    },
    "MountTarget": {
      "Type": "AWS::EFS::MountTarget",
      "Properties": {
        "FileSystemId": { "Ref": "FileSystem" },
        "SubnetId": { "Ref": "Subnet" },
        "SecurityGroups": [ { "Ref": "MountTargetSecurityGroup" } ]        
      }
    },
    "LaunchConfiguration": {
      "Type": "AWS::AutoScaling::LaunchConfiguration",
      "Metadata" : {
        "AWS::CloudFormation::Init" : {
          "configSets" : {
            "MountConfig" : [ "setup", "mount" ]
          },
          "setup" : {
            "packages" : {
              "yum" : {
                "nfs-utils" : []
              }
            },
            "files" : {
              "/home/ec2-user/post_nfsstat" : {
                "content" : { "Fn::Join" : [ "", [
                      "#!/bin/bash\n",
                      "\n",
                      "INPUT=\"$(cat)\"\n",
                      "CW_JSON_OPEN='{ \"Namespace\": \"EFS\", \"MetricData\": [ '\n",
                      "CW_JSON_CLOSE=' ] }'\n",
                      "CW_JSON_METRIC=''\n",
                      "METRIC_COUNTER=0\n",
                      "\n",
                      "for COL in 1 2 3 4 5 6; do\n",
                      "\n",
                      " COUNTER=0\n",
                      " METRIC_FIELD=$COL\n",
                      " DATA_FIELD=$(($COL+($COL-1)))\n",
                      "\n",
                      " while read line; do\n",
                      "   if [[ COUNTER -gt 0 ]]; then\n",
                      "\n",
                      "     LINE=`echo $line | tr -s ' ' `\n",
                      "     AWS_COMMAND=\"aws cloudwatch put-metric-data --region ", { "Ref": "AWS::Region" }, "\"\n",
                      "     MOD=$(( $COUNTER % 2))\n",
                      "\n",
                      "     if [ $MOD -eq 1 ]; then\n",
                      "       METRIC_NAME=`echo $LINE | cut -d ' ' -f $METRIC_FIELD`\n",
                      "     else\n",
                      "       METRIC_VALUE=`echo $LINE | cut -d ' ' -f $DATA_FIELD`\n",
                      "     fi\n",
                      "\n",
                      "     if [[ -n \"$METRIC_NAME\" && -n \"$METRIC_VALUE\" ]]; then\n",
                      "       INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)\n",
                      "       CW_JSON_METRIC=\"$CW_JSON_METRIC { \\\"MetricName\\\": \\\"$METRIC_NAME\\\", \\\"Dimensions\\\": [{\\\"Name\\\": \\\"InstanceId\\\", \\\"Value\\\": \\\"$INSTANCE_ID\\\"} ], \\\"Value\\\": $METRIC_VALUE },\"\n",
                      "       unset METRIC_NAME\n",
                      "       unset METRIC_VALUE\n",
                      "\n",
                      "       METRIC_COUNTER=$((METRIC_COUNTER+1))\n",
                      "       if [ $METRIC_COUNTER -eq 20 ]; then\n",
                      "         # 20 is max metric collection size, so we have to submit here\n",
                      "         aws cloudwatch put-metric-data --region ", { "Ref": "AWS::Region" }, " --cli-input-json \"`echo $CW_JSON_OPEN ${CW_JSON_METRIC%?} $CW_JSON_CLOSE`\"\n",
                      "\n",
                      "         # reset\n",
                      "         METRIC_COUNTER=0\n",
                      "         CW_JSON_METRIC=''\n",
                      "       fi\n",
                      "     fi  \n",
                      "\n",
                      "\n",
                      "\n",
                      "     COUNTER=$((COUNTER+1))\n",
                      "   fi\n",
                      "\n",
                      "   if [[ \"$line\" == \"Client nfs v4:\" ]]; then\n",
                      "     # the next line is the good stuff \n",
                      "     COUNTER=$((COUNTER+1))\n",
                      "   fi\n",
                      " done <<< \"$INPUT\"\n",
                      "done\n",
                      "\n",
                      "# submit whatever is left\n",
                      "aws cloudwatch put-metric-data --region ", { "Ref": "AWS::Region" }, " --cli-input-json \"`echo $CW_JSON_OPEN ${CW_JSON_METRIC%?} $CW_JSON_CLOSE`\""
                    ] ] },
                "mode": "000755",
                "owner": "ec2-user",
                "group": "ec2-user"
              },
              "/home/ec2-user/crontab" : {
                "content" : { "Fn::Join" : [ "", [
                  "* * * * * /usr/sbin/nfsstat | /home/ec2-user/post_nfsstat\n"
                ] ] },
                "owner": "ec2-user",
                "group": "ec2-user"
              }
            },
            "commands" : {
              "01_createdir" : {
                "command" : {"Fn::Join" : [ "", [ "mkdir /", { "Ref" : "MountPoint" }]]}
              }
            }
          },
          "mount" : {
            "commands" : {
              "01_mount" : {
                "command" : { "Fn::Sub": "sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 ${FileSystem}.efs.${AWS::Region}.amazonaws.com:/ /${MountPoint}"}
              },
              "02_permissions" : {
                "command" : {"Fn::Join" : [ "", [ "chown ec2-user:ec2-user /", { "Ref" : "MountPoint" }]]}
              }
            }
          }
        }
      },
      "Properties": {
        "AssociatePublicIpAddress" : true,
        "ImageId": {
          "Fn::FindInMap": [ "AWSRegionArch2AMI", { "Ref": "AWS::Region" }, {
            "Fn::FindInMap": [ "AWSInstanceType2Arch", { "Ref": "InstanceType" }, "Arch" ]
          } ]
        },
        "InstanceType": { "Ref": "InstanceType" },
        "KeyName": { "Ref": "KeyName" },
        "SecurityGroups": [ { "Ref": "InstanceSecurityGroup" } ],
        "IamInstanceProfile" : { "Ref" : "CloudWatchPutMetricsInstanceProfile" },
        "UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
             "#!/bin/bash -xe\n",
             "yum install -y aws-cfn-bootstrap\n",

             "/opt/aws/bin/cfn-init -v ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource LaunchConfiguration ",
             "         --configsets MountConfig ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n",

             "crontab /home/ec2-user/crontab\n",

             "/opt/aws/bin/cfn-signal -e $? ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource AutoScalingGroup ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n"
        ]]}}
      }
    },
    "AutoScalingGroup": {
      "Type": "AWS::AutoScaling::AutoScalingGroup",
      "DependsOn": ["MountTarget", "GatewayToInternet"],
      "CreationPolicy" : {
        "ResourceSignal" : {
          "Timeout" : "PT15M",
          "Count"   : { "Ref": "AsgMaxSize" }
        }
      },
      "Properties": {
        "VPCZoneIdentifier": [ { "Ref": "Subnet" } ],
        "LaunchConfigurationName": { "Ref": "LaunchConfiguration" },
        "MinSize": "1",
        "MaxSize": { "Ref": "AsgMaxSize" },
        "DesiredCapacity": { "Ref": "AsgMaxSize" },
        "Tags": [ {
          "Key": "Name",
          "Value": "EFS FileSystem Mounted Instance",
          "PropagateAtLaunch": "true"
        } ]
      }
    }
  },
  "Outputs" : {
    "MountTargetID" : {
      "Description" : "Mount target ID",
      "Value" :  { "Ref" : "MountTarget" }
    },
    "FileSystemID" : {
      "Description" : "File system ID",
      "Value" :  { "Ref" : "FileSystem" }
    }
  }
}
```

## YAML
<a name="quickref-efs-example-1.yaml"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Description: This template creates an Amazon EFS file system and mount target and
  associates it with Amazon EC2 instances in an Auto Scaling group. **WARNING** This
  template creates Amazon EC2 instances and related resources. You will be billed
  for the AWS resources used if you create a stack from this template.
Parameters:
  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: t2.small
    AllowedValues:
      - t1.micro
      - t2.nano
      - t2.micro
      - t2.small
      - t2.medium
      - t2.large
      - m1.small
      - m1.medium
      - m1.large
      - m1.xlarge
      - m2.xlarge
      - m2.2xlarge
      - m2.4xlarge
      - m3.medium
      - m3.large
      - m3.xlarge
      - m3.2xlarge
      - m4.large
      - m4.xlarge
      - m4.2xlarge
      - m4.4xlarge
      - m4.10xlarge
      - c1.medium
      - c1.xlarge
      - c3.large
      - c3.xlarge
      - c3.2xlarge
      - c3.4xlarge
      - c3.8xlarge
      - c4.large
      - c4.xlarge
      - c4.2xlarge
      - c4.4xlarge
      - c4.8xlarge
      - g2.2xlarge
      - g2.8xlarge
      - r3.large
      - r3.xlarge
      - r3.2xlarge
      - r3.4xlarge
      - r3.8xlarge
      - i2.xlarge
      - i2.2xlarge
      - i2.4xlarge
      - i2.8xlarge
      - d2.xlarge
      - d2.2xlarge
      - d2.4xlarge
      - d2.8xlarge
      - hi1.4xlarge
      - hs1.8xlarge
      - cr1.8xlarge
      - cc2.8xlarge
      - cg1.4xlarge
    ConstraintDescription: must be a valid EC2 instance type.
  KeyName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: Name of an existing EC2 key pair to enable SSH access to the ECS
      instances
  AsgMaxSize:
    Type: Number
    Description: Maximum size and initial desired capacity of Auto Scaling Group
    Default: '2'
  SSHLocation:
    Description: The IP address range that can be used to connect to the EC2 instances
      by using SSH
    Type: String
    MinLength: '9'
    MaxLength: '18'
    Default: 0.0.0.0/0
    AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
  VolumeName:
    Description: The name to be used for the EFS volume
    Type: String
    MinLength: '1'
    Default: myEFSvolume
  MountPoint:
    Description: The Linux mount point for the EFS volume
    Type: String
    MinLength: '1'
    Default: myEFSvolume
Mappings:
  AWSInstanceType2Arch:
    t1.micro:
      Arch: HVM64
    t2.nano:
      Arch: HVM64
    t2.micro:
      Arch: HVM64
    t2.small:
      Arch: HVM64
    t2.medium:
      Arch: HVM64
    t2.large:
      Arch: HVM64
    m1.small:
      Arch: HVM64
    m1.medium:
      Arch: HVM64
    m1.large:
      Arch: HVM64
    m1.xlarge:
      Arch: HVM64
    m2.xlarge:
      Arch: HVM64
    m2.2xlarge:
      Arch: HVM64
    m2.4xlarge:
      Arch: HVM64
    m3.medium:
      Arch: HVM64
    m3.large:
      Arch: HVM64
    m3.xlarge:
      Arch: HVM64
    m3.2xlarge:
      Arch: HVM64
    m4.large:
      Arch: HVM64
    m4.xlarge:
      Arch: HVM64
    m4.2xlarge:
      Arch: HVM64
    m4.4xlarge:
      Arch: HVM64
    m4.10xlarge:
      Arch: HVM64
    c1.medium:
      Arch: HVM64
    c1.xlarge:
      Arch: HVM64
    c3.large:
      Arch: HVM64
    c3.xlarge:
      Arch: HVM64
    c3.2xlarge:
      Arch: HVM64
    c3.4xlarge:
      Arch: HVM64
    c3.8xlarge:
      Arch: HVM64
    c4.large:
      Arch: HVM64
    c4.xlarge:
      Arch: HVM64
    c4.2xlarge:
      Arch: HVM64
    c4.4xlarge:
      Arch: HVM64
    c4.8xlarge:
      Arch: HVM64
    g2.2xlarge:
      Arch: HVMG2
    g2.8xlarge:
      Arch: HVMG2
    r3.large:
      Arch: HVM64
    r3.xlarge:
      Arch: HVM64
    r3.2xlarge:
      Arch: HVM64
    r3.4xlarge:
      Arch: HVM64
    r3.8xlarge:
      Arch: HVM64
    i2.xlarge:
      Arch: HVM64
    i2.2xlarge:
      Arch: HVM64
    i2.4xlarge:
      Arch: HVM64
    i2.8xlarge:
      Arch: HVM64
    d2.xlarge:
      Arch: HVM64
    d2.2xlarge:
      Arch: HVM64
    d2.4xlarge:
      Arch: HVM64
    d2.8xlarge:
      Arch: HVM64
    hi1.4xlarge:
      Arch: HVM64
    hs1.8xlarge:
      Arch: HVM64
    cr1.8xlarge:
      Arch: HVM64
    cc2.8xlarge:
      Arch: HVM64
  AWSRegionArch2AMI:
    us-east-1:
      HVM64: ami-0ff8a91507f77f867
      HVMG2: ami-0a584ac55a7631c0c
    us-west-2:
      HVM64: ami-a0cfeed8
      HVMG2: ami-0e09505bc235aa82d
    us-west-1:
      HVM64: ami-0bdb828fd58c52235
      HVMG2: ami-066ee5fd4a9ef77f1
    eu-west-1:
      HVM64: ami-047bb4163c506cd98
      HVMG2: ami-0a7c483d527806435
    eu-west-2:
      HVM64: ami-f976839e
      HVMG2: NOT_SUPPORTED
    eu-west-3:
      HVM64: ami-0ebc281c20e89ba4b
      HVMG2: NOT_SUPPORTED
    eu-central-1:
      HVM64: ami-0233214e13e500f77
      HVMG2: ami-06223d46a6d0661c7
    ap-northeast-1:
      HVM64: ami-06cd52961ce9f0d85
      HVMG2: ami-053cdd503598e4a9d
    ap-northeast-2:
      HVM64: ami-0a10b2721688ce9d2
      HVMG2: NOT_SUPPORTED
    ap-northeast-3:
      HVM64: ami-0d98120a9fb693f07
      HVMG2: NOT_SUPPORTED
    ap-southeast-1:
      HVM64: ami-08569b978cc4dfa10
      HVMG2: ami-0be9df32ae9f92309
    ap-southeast-2:
      HVM64: ami-09b42976632b27e9b
      HVMG2: ami-0a9ce9fecc3d1daf8
    ap-south-1:
      HVM64: ami-0912f71e06545ad88
      HVMG2: ami-097b15e89dbdcfcf4
    us-east-2:
      HVM64: ami-0b59bfac6be064b78
      HVMG2: NOT_SUPPORTED
    ca-central-1:
      HVM64: ami-0b18956f
      HVMG2: NOT_SUPPORTED
    sa-east-1:
      HVM64: ami-07b14488da8ea02a0
      HVMG2: NOT_SUPPORTED
    cn-north-1:
      HVM64: ami-0a4eaf6c4454eda75
      HVMG2: NOT_SUPPORTED
    cn-northwest-1:
      HVM64: ami-6b6a7d09
      HVMG2: NOT_SUPPORTED
Resources:
  CloudWatchPutMetricsRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - ec2.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
  CloudWatchPutMetricsRolePolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: CloudWatch_PutMetricData
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Sid: CloudWatchPutMetricData
          Effect: Allow
          Action:
          - cloudwatch:PutMetricData
          Resource:
          - "*"
      Roles:
      - Ref: CloudWatchPutMetricsRole
  CloudWatchPutMetricsInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: "/"
      Roles:
      - Ref: CloudWatchPutMetricsRole
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      EnableDnsSupport: 'true'
      EnableDnsHostnames: 'true'
      CidrBlock: 10.0.0.0/16
      Tags:
      - Key: Application
        Value:
          Ref: AWS::StackId
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
      - Key: Application
        Value:
          Ref: AWS::StackName
      - Key: Network
        Value: Public
  GatewayToInternet:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId:
        Ref: VPC
      InternetGatewayId:
        Ref: InternetGateway
  RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: VPC
  SubnetRouteTableAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: RouteTable
      SubnetId:
        Ref: Subnet
  InternetGatewayRoute:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      RouteTableId:
        Ref: RouteTable
      GatewayId:
        Ref: InternetGateway
  Subnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId:
        Ref: VPC
      CidrBlock: 10.0.0.0/24
      Tags:
      - Key: Application
        Value:
          Ref: AWS::StackId
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId:
        Ref: VPC
      GroupDescription: Enable SSH access via port 22
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp:
          Ref: SSHLocation
      - IpProtocol: tcp
        FromPort: 80
        ToPort: 80
        CidrIp: 0.0.0.0/0
  MountTargetSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId:
        Ref: VPC
      GroupDescription: Security group for mount target
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 2049
        ToPort: 2049
        CidrIp: 0.0.0.0/0
  FileSystem:
    Type: AWS::EFS::FileSystem
    Properties:
      PerformanceMode: generalPurpose
      FileSystemTags:
      - Key: Name
        Value:
          Ref: VolumeName
  MountTarget:
    Type: AWS::EFS::MountTarget
    Properties:
      FileSystemId:
        Ref: FileSystem
      SubnetId:
        Ref: Subnet
      SecurityGroups:
      - Ref: MountTargetSecurityGroup
  LaunchConfiguration:
    Type: AWS::AutoScaling::LaunchConfiguration
    Metadata:
      AWS::CloudFormation::Init:
        configSets:
          MountConfig:
          - setup
          - mount
        setup:
          packages:
            yum:
              nfs-utils: []
          files:
            "/home/ec2-user/post_nfsstat":
              content: !Sub |
                #!/bin/bash

                INPUT="$(cat)"
                CW_JSON_OPEN='{ "Namespace": "EFS", "MetricData": [ '
                CW_JSON_CLOSE=' ] }'
                CW_JSON_METRIC=''
                METRIC_COUNTER=0

                for COL in 1 2 3 4 5 6; do

                 COUNTER=0
                 METRIC_FIELD=$COL
                 DATA_FIELD=$(($COL+($COL-1)))

                 while read line; do
                   if [[ COUNTER -gt 0 ]]; then

                     LINE=`echo $line | tr -s ' ' `
                     AWS_COMMAND="aws cloudwatch put-metric-data --region ${AWS::Region}"
                     MOD=$(( $COUNTER % 2))

                     if [ $MOD -eq 1 ]; then
                       METRIC_NAME=`echo $LINE | cut -d ' ' -f $METRIC_FIELD`
                     else
                       METRIC_VALUE=`echo $LINE | cut -d ' ' -f $DATA_FIELD`
                     fi

                     if [[ -n "$METRIC_NAME" && -n "$METRIC_VALUE" ]]; then
                       INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
                       CW_JSON_METRIC="$CW_JSON_METRIC { \"MetricName\": \"$METRIC_NAME\", \"Dimensions\": [{\"Name\": \"InstanceId\", \"Value\": \"$INSTANCE_ID\"} ], \"Value\": $METRIC_VALUE },"
                       unset METRIC_NAME
                       unset METRIC_VALUE

                       METRIC_COUNTER=$((METRIC_COUNTER+1))
                       if [ $METRIC_COUNTER -eq 20 ]; then
                         # 20 is max metric collection size, so we have to submit here
                         aws cloudwatch put-metric-data --region ${AWS::Region} --cli-input-json "`echo $CW_JSON_OPEN ${!CW_JSON_METRIC%?} $CW_JSON_CLOSE`"

                         # reset
                         METRIC_COUNTER=0
                         CW_JSON_METRIC=''
                       fi
                     fi



                     COUNTER=$((COUNTER+1))
                   fi

                   if [[ "$line" == "Client nfs v4:" ]]; then
                     # the next line is the good stuff
                     COUNTER=$((COUNTER+1))
                   fi
                 done <<< "$INPUT"
                done

                # submit whatever is left
                aws cloudwatch put-metric-data --region ${AWS::Region} --cli-input-json "`echo $CW_JSON_OPEN ${!CW_JSON_METRIC%?} $CW_JSON_CLOSE`"
              mode: '000755'
              owner: ec2-user
              group: ec2-user
            "/home/ec2-user/crontab":
              content: "* * * * * /usr/sbin/nfsstat | /home/ec2-user/post_nfsstat\n"
              owner: ec2-user
              group: ec2-user
          commands:
            01_createdir:
              command: !Sub "mkdir /${MountPoint}"
        mount:
          commands:
            01_mount:
              command: !Sub >
                mount -t nfs4 -o nfsvers=4.1 ${FileSystem}.efs.${AWS::Region}.amazonaws.com:/ /${MountPoint}
            02_permissions:
              command: !Sub "chown ec2-user:ec2-user /${MountPoint}"
    Properties:
      AssociatePublicIpAddress: true
      ImageId:
        Fn::FindInMap:
        - AWSRegionArch2AMI
        - Ref: AWS::Region
        - Fn::FindInMap:
          - AWSInstanceType2Arch
          - Ref: InstanceType
          - Arch
      InstanceType:
        Ref: InstanceType
      KeyName:
        Ref: KeyName
      SecurityGroups:
      - Ref: InstanceSecurityGroup
      IamInstanceProfile:
        Ref: CloudWatchPutMetricsInstanceProfile
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          yum install -y aws-cfn-bootstrap
          /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfiguration --configsets MountConfig --region ${AWS::Region}
          crontab /home/ec2-user/crontab
          /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource AutoScalingGroup --region ${AWS::Region}
  AutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    DependsOn:
    - MountTarget
    - GatewayToInternet
    CreationPolicy:
      ResourceSignal:
        Timeout: PT15M
        Count:
          Ref: AsgMaxSize
    Properties:
      VPCZoneIdentifier:
      - Ref: Subnet
      LaunchConfigurationName:
        Ref: LaunchConfiguration
      MinSize: '1'
      MaxSize:
        Ref: AsgMaxSize
      DesiredCapacity:
        Ref: AsgMaxSize
      Tags:
      - Key: Name
        Value: EFS FileSystem Mounted Instance
        PropagateAtLaunch: 'true'
Outputs:
  MountTargetID:
    Description: Mount target ID
    Value:
      Ref: MountTarget
  FileSystemID:
    Description: File system ID
    Value:
      Ref: FileSystem
```

# Elastic Beanstalk 템플릿 코드 조각
<a name="quickref-elasticbeanstalk"></a>

Elastic Beanstalk 사용을 통해 애플리케이션을 실행하는 인프라에 관계없이 AWS에서 애플리케이션을 신속하게 배포하고 관리할 수 있습니다. 다음 샘플 템플릿은 CloudFormation 템플릿에서 Elastic Beanstalk 리소스를 설명하는 데 도움이 될 수 있습니다.

## Elastic Beanstalk 샘플 PHP
<a name="quickref-elasticbeanstalk-sampleenv"></a>

다음 샘플 템플릿은 Amazon S3 버킷에 저장되어 있는 샘플 PHP 웹 애플리케이션을 배포합니다. 또한 이 환경은 최소 2개 및 최대 6개의 Amazon EC2 인스턴스가 있는 Auto Scaling, 로드 밸런싱 환경입니다. 레거시 시작 구성을 사용하는 Elastic Beanstalk 환경을 보여줍니다. 대신 시작 템플릿을 사용하는 방법에 대한 자세한 내용은 *AWS Elastic Beanstalk 개발자 안내서*의 [시작 템플릿을 참조하세요](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-cfg-autoscaling-launch-templates.html).

`solution-stack`을 솔루션 스택 이름(플랫폼 버전)으로 바꿉니다. 사용 가능한 솔루션 스택 목록을 보려면 AWS CLI 명령 **aws elasticbeanstalk list-available-solution-stacks**를 사용합니다.

### JSON
<a name="quickref-elasticbeanstalk-example-1.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Resources": {
        "sampleApplication": {
            "Type": "AWS::ElasticBeanstalk::Application",
            "Properties": {
                "Description": "AWS Elastic Beanstalk Sample Application"
            }
        },
        "sampleApplicationVersion": {
            "Type": "AWS::ElasticBeanstalk::ApplicationVersion",
            "Properties": {
                "ApplicationName": {
                    "Ref": "sampleApplication"
                },
                "Description": "AWS ElasticBeanstalk Sample Application Version",
                "SourceBundle": {
                    "S3Bucket": {
                        "Fn::Sub": "elasticbeanstalk-samples-${AWS::Region}"
                    },
                    "S3Key": "php-newsample-app.zip"
                }
            }
        },
        "sampleConfigurationTemplate": {
            "Type": "AWS::ElasticBeanstalk::ConfigurationTemplate",
            "Properties": {
                "ApplicationName": {
                    "Ref": "sampleApplication"
                },
                "Description": "AWS ElasticBeanstalk Sample Configuration Template",
                "OptionSettings": [
                    {
                        "Namespace": "aws:autoscaling:asg",
                        "OptionName": "MinSize",
                        "Value": "2"
                    },
                    {
                        "Namespace": "aws:autoscaling:asg",
                        "OptionName": "MaxSize",
                        "Value": "6"
                    },
                    {
                        "Namespace": "aws:elasticbeanstalk:environment",
                        "OptionName": "EnvironmentType",
                        "Value": "LoadBalanced"
                    },
                    {
                        "Namespace": "aws:autoscaling:launchconfiguration",
                        "OptionName": "IamInstanceProfile",
                        "Value": {
                            "Ref": "MyInstanceProfile"
                        }
                    }
                ],
                "SolutionStackName": "solution-stack"
            }
        },
        "sampleEnvironment": {
            "Type": "AWS::ElasticBeanstalk::Environment",
            "Properties": {
                "ApplicationName": {
                    "Ref": "sampleApplication"
                },
                "Description": "AWS ElasticBeanstalk Sample Environment",
                "TemplateName": {
                    "Ref": "sampleConfigurationTemplate"
                },
                "VersionLabel": {
                    "Ref": "sampleApplicationVersion"
                }
            }
        },
        "MyInstanceRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "ec2.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "Description": "Beanstalk EC2 role",
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier",
                    "arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker",
                    "arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier"
                ]
            }
        },
        "MyInstanceProfile": {
            "Type": "AWS::IAM::InstanceProfile",
            "Properties": {
                "Roles": [
                    {
                        "Ref": "MyInstanceRole"
                    }
                ]
            }
        }
    }
}
```

### YAML
<a name="quickref-elasticbeanstalk-example-1.yaml"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  sampleApplication:
    Type: AWS::ElasticBeanstalk::Application
    Properties:
      Description: AWS Elastic Beanstalk Sample Application
  sampleApplicationVersion:
    Type: AWS::ElasticBeanstalk::ApplicationVersion
    Properties:
      ApplicationName:
        Ref: sampleApplication
      Description: AWS ElasticBeanstalk Sample Application Version
      SourceBundle:
        S3Bucket: !Sub "elasticbeanstalk-samples-${AWS::Region}"
        S3Key: php-newsample-app.zip
  sampleConfigurationTemplate:
    Type: AWS::ElasticBeanstalk::ConfigurationTemplate
    Properties:
      ApplicationName:
        Ref: sampleApplication
      Description: AWS ElasticBeanstalk Sample Configuration Template
      OptionSettings:
      - Namespace: aws:autoscaling:asg
        OptionName: MinSize
        Value: '2'
      - Namespace: aws:autoscaling:asg
        OptionName: MaxSize
        Value: '6'
      - Namespace: aws:elasticbeanstalk:environment
        OptionName: EnvironmentType
        Value: LoadBalanced
      - Namespace: aws:autoscaling:launchconfiguration
        OptionName: IamInstanceProfile
        Value: !Ref MyInstanceProfile        
      SolutionStackName: solution-stack
  sampleEnvironment:
    Type: AWS::ElasticBeanstalk::Environment
    Properties:
      ApplicationName:
        Ref: sampleApplication
      Description: AWS ElasticBeanstalk Sample Environment
      TemplateName:
        Ref: sampleConfigurationTemplate
      VersionLabel:
        Ref: sampleApplicationVersion
  MyInstanceRole:
    Type: AWS::IAM::Role
    Properties: 
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      Description: Beanstalk EC2 role
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier
        - arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker
        - arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier
  MyInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties: 
      Roles:
        - !Ref MyInstanceRole
```

# Elastic Load Balancing 템플릿 코드 조각
<a name="quickref-elb"></a>

Application Load Balancer, Network Load Balancer 또는 Gateway Load Balancer를 생성하려면 `AWS::ElasticLoadBalancingV2`로 시작하는 V2 리소스 유형을 사용합니다. Classic Load Balancer를 생성하려면 `AWS::ElasticLoadBalancing`으로 시작하는 리소스 유형을 사용합니다.

**Topics**
+ [ELBv2 리소스](#scenario-elbv2-load-balancer)
+ [Classic Load Balancer 리소스](#scenario-elb-load-balancer)

## ELBv2 리소스
<a name="scenario-elbv2-load-balancer"></a>

이 예제에서는 HTTP 리스너와 대상 그룹으로 트래픽을 전달하는 기본 작업을 사용하여 Application Load Balancer를 정의합니다. 로드 밸런서는 기본 상태 확인 설정을 사용합니다. 대상 그룹에는 2개의 등록된 EC2 인스턴스가 있습니다.

------
#### [ YAML ]

```
Resources:
  myLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: my-alb
      Type: application
      Scheme: internal
      Subnets: 
        - !Ref subnet-AZ1
        - !Ref subnet-AZ2
      SecurityGroups: 
        - !Ref mySecurityGroup

  myHTTPlistener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref myLoadBalancer
      Protocol: HTTP
      Port: 80
      DefaultActions:
        - Type: "forward"
          TargetGroupArn: !Ref myTargetGroup
                        
  myTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: "my-target-group"
      Protocol: HTTP
      Port: 80
      TargetType: instance
      VpcId: !Ref myVPC
      Targets:
        - Id: !GetAtt Instance1.InstanceId
          Port: 80
        - Id: !GetAtt Instance2.InstanceId
          Port: 80
```

------
#### [ JSON ]

```
{
    "Resources": {
        "myLoadBalancer": {
            "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
            "Properties": {
                "Name": "my-alb",
                "Type": "application",
                "Scheme": "internal",
                "Subnets": [
                    {
                        "Ref": "subnet-AZ1"
                    },
                    {
                        "Ref": "subnet-AZ2"
                    }
                ],
                "SecurityGroups": [
                    {
                        "Ref": "mySecurityGroup"
                    }
                ]
            }
        },
        "myHTTPlistener": {
            "Type": "AWS::ElasticLoadBalancingV2::Listener",
            "Properties": {
                "LoadBalancerArn": {
                    "Ref": "myLoadBalancer"
                },
                "Protocol": "HTTP",
                "Port": 80,
                "DefaultActions": [
                    {
                        "Type": "forward",
                        "TargetGroupArn": {
                            "Ref": "myTargetGroup"
                        }
                    }
                ]
            }
        },
        "myTargetGroup": {
            "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
            "Properties": {
                "Name": "my-target-group",
                "Protocol": "HTTP",
                "Port": 80,
                "TargetType": "instance",
                "VpcId": {
                    "Ref": "myVPC"
                },
                "Targets": [
                    {
                        "Id": {
                            "Fn::GetAtt": [
                                "Instance1",
                                "InstanceId"
                            ]
                        },
                        "Port": 80
                    },
                    {
                        "Id": {
                            "Fn::GetAtt": [
                                "Instance2",
                                "InstanceId"
                            ]
                        },
                        "Port": 80
                    }
                ]
            }
        }
    }
}
```

------

## Classic Load Balancer 리소스
<a name="scenario-elb-load-balancer"></a>

이 예제에서는 1개의 HTTP 리스너가 있고 등록된 EC2 인스턴스가 없는 Classic Load Balancer를 정의합니다. 로드 밸런서는 기본 상태 확인 설정을 사용합니다.

------
#### [ YAML ]

```
myLoadBalancer:
  Type: AWS::ElasticLoadBalancing::LoadBalancer
  Properties:
    AvailabilityZones:
    - "us-east-1a"
    Listeners:
    - LoadBalancerPort: '80'
      InstancePort: '80'
      Protocol: HTTP
```

------
#### [ JSON ]

```
"myLoadBalancer" : {
    "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
    "Properties" : {
        "AvailabilityZones" : [ "us-east-1a" ],
        "Listeners" : [ {
            "LoadBalancerPort" : "80",
            "InstancePort" : "80",
            "Protocol" : "HTTP"
        } ]
    }
}
```

------

이 예제에서는 1개의 HTTP 리스너, 2개의 등록된 EC2 인스턴스 및 사용자 지정 상태 확인 설정이 있는 Classic Load Balancer를 정의합니다.

------
#### [ YAML ]

```
myClassicLoadBalancer:
  Type: AWS::ElasticLoadBalancing::LoadBalancer
  Properties:
    AvailabilityZones:
    - "us-east-1a"
    Instances:
    - Ref: Instance1
    - Ref: Instance2
    Listeners:
    - LoadBalancerPort: '80'
      InstancePort: '80'
      Protocol: HTTP
    HealthCheck:
      Target: HTTP:80/
      HealthyThreshold: '3'
      UnhealthyThreshold: '5'
      Interval: '30'
      Timeout: '5'
```

------
#### [ JSON ]

```
"myClassicLoadBalancer" : {
    "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
    "Properties" : {
        "AvailabilityZones" : [ "us-east-1a" ],
        "Instances" : [
            { "Ref" : "Instance1" },
            { "Ref" : "Instance2" }
        ],
        "Listeners" : [ {
            "LoadBalancerPort" : "80",
            "InstancePort" : "80",
            "Protocol" : "HTTP"
        } ],

        "HealthCheck" : {
            "Target" : "HTTP:80/",
            "HealthyThreshold" : "3",
            "UnhealthyThreshold" : "5",
            "Interval" : "30",
            "Timeout" : "5"
        }
    }
}
```

------

# AWS Identity and Access Management 템플릿 코드 조각
<a name="quickref-iam"></a>

이 단원에는 AWS Identity and Access Management 템플릿 조각이 포함되어 있습니다.

**Topics**
+ [IAM 사용자 리소스 선언](#scenario-iam-user)
+ [IAM 액세스 키 리소스 선언](#scenario-iam-accesskey)
+ [IAM 그룹 리소스 선언](#scenario-iam-group)
+ [그룹에 사용자 추가](#scenario-iam-addusertogroup)
+ [IAM 정책 선언](#scenario-iam-policy)
+ [Amazon S3 버킷 정책 선언](#scenario-bucket-policy)
+ [Amazon SNS 주제 정책 선언](#scenario-sns-policy)
+ [Amazon SQS 정책 선언](#scenario-sqs-policy)
+ [IAM 역할 템플릿의 예](#scenarios-iamroles)

**중요**  
IAM 리소스가 포함된 템플릿을 사용하여 스택을 생성 또는 업데이트하는 경우 IAM 기능의 사용을 승인해야 합니다. 자세한 내용은 [CloudFormation 템플릿에서 IAM 리소스 승인](control-access-with-iam.md#using-iam-capabilities) 섹션을 참조하세요.

## IAM 사용자 리소스 선언
<a name="scenario-iam-user"></a>

이 코드 조각에서는 IAM 사용자를 생성하기 위해 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html) 리소스를 선언하는 방법을 보여줍니다. 사용자는 경로(`"/"`)와 암호가 포함된 로그인 프로파일(`myP@ssW0rd`)로 선언됩니다.

정책 문서 `giveaccesstoqueueonly`는 Amazon SQS 대기열 리소스 `myqueue`에 대해 모든 Amazon SQS 작업을 수행할 수 있는 사용자 권한을 부여하고 기타 모든 Amazon SQS 대기열 리소스에 대한 액세스를 거부합니다. `Fn::GetAtt` 함수는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sqs-queue.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sqs-queue.html) 리소스 `myqueue`의 Arn 속성을 가져옵니다.

Amazon SNS 주제 리소스 `mytopic`에 대해 모든 Amazon SNS 작업을 수행하고 기타 모든 Amazon SNS 리소스에 대한 액세스를 거부할 수 있는 사용자 권한을 부여하는 정책 문서 `giveaccesstotopiconly`가 사용자에게 추가됩니다. `Ref` 함수는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-topic.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-topic.html) 리소스 `mytopic`의 ARN을 가져옵니다.

### JSON
<a name="quickref-iam-example-1.json"></a>

```
"myuser" : {
   "Type" : "AWS::IAM::User",
   "Properties" : {
      "Path" : "/",
      "LoginProfile" : {
         "Password" : "myP@ssW0rd"
      },
      "Policies" : [ {
         "PolicyName" : "giveaccesstoqueueonly",
         "PolicyDocument" : {
            "Version": "2012-10-17",		 	 	 
            "Statement" : [ {
               "Effect" : "Allow",
               "Action" : [ "sqs:*" ],
               "Resource" : [ {
                  "Fn::GetAtt" : [ "myqueue", "Arn" ]
               } ]
            }, {
               "Effect" : "Deny",
               "Action" : [ "sqs:*" ],
               "NotResource" : [ {
                  "Fn::GetAtt" : [ "myqueue", "Arn" ]
               } ]
            }
         ] }
      }, {
         "PolicyName" : "giveaccesstotopiconly",
         "PolicyDocument" : {
            "Version": "2012-10-17",		 	 	 
            "Statement" : [ {
               "Effect" : "Allow",
               "Action" : [ "sns:*" ],
               "Resource" : [ { "Ref" : "mytopic" } ]
            }, {
               "Effect" : "Deny",
               "Action" : [ "sns:*" ],
               "NotResource" : [ { "Ref" : "mytopic" } ]
            } ]
         }
      } ]
   }
}
```

### YAML
<a name="quickref-iam-example-1.yaml"></a>

```
myuser:
  Type: AWS::IAM::User
  Properties:
    Path: "/"
    LoginProfile:
      Password: myP@ssW0rd
    Policies:
    - PolicyName: giveaccesstoqueueonly
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Action:
          - sqs:*
          Resource:
          - !GetAtt myqueue.Arn
        - Effect: Deny
          Action:
          - sqs:*
          NotResource:
          - !GetAtt myqueue.Arn
    - PolicyName: giveaccesstotopiconly
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Action:
          - sns:*
          Resource:
          - !Ref mytopic
        - Effect: Deny
          Action:
          - sns:*
          NotResource:
          - !Ref mytopic
```

## IAM 액세스 키 리소스 선언
<a name="scenario-iam-accesskey"></a>

### 
<a name="quickref-iam-access-key"></a>

이 코드 조각은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-accesskey.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-accesskey.html) 리소스를 보여줍니다. `myaccesskey` 리소스는 액세스 키를 생성하여 템플릿에 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html) 리소스로 선언된 IAM 사용자에게 할당합니다.

#### JSON
<a name="quickref-iam-example-2.json"></a>

```
"myaccesskey" : {
   "Type" : "AWS::IAM::AccessKey",
   "Properties" : {
      "UserName" : { "Ref" : "myuser" }
   }
}
```

#### YAML
<a name="quickref-iam-example-2.yaml"></a>

```
myaccesskey:
  Type: AWS::IAM::AccessKey
  Properties:
    UserName:
      !Ref myuser
```

### 
<a name="quickref-iam-access-key-2"></a>

`AWS::IAM::AccessKey` 함수를 사용하여 `Fn::GetAtt` 리소스에 대한 보안 키를 가져올 수 있습니다. 보안 키는 `Output` 값에 보안 키를 입력한 경우에만 검색할 수 있습니다. `Ref` 함수를 사용하면 액세스 키를 가져올 수 있습니다. 다음 `Output` 값 선언에서는 `myaccesskey`에 대한 액세스 키 및 보안 키를 가져옵니다.

#### JSON
<a name="quickref-iam-example-3.json"></a>

```
"AccessKeyformyaccesskey" : {
   "Value" : { "Ref" : "myaccesskey" }
},
"SecretKeyformyaccesskey" : {
   "Value" : {
      "Fn::GetAtt" : [ "myaccesskey", "SecretAccessKey" ]
   }
}
```

#### YAML
<a name="quickref-iam-example-3.yaml"></a>

```
AccessKeyformyaccesskey:
  Value:
    !Ref myaccesskey
SecretKeyformyaccesskey:
  Value: !GetAtt myaccesskey.SecretAccessKey
```

### 
<a name="quickref-iam-access-key-3"></a>

또한 템플릿에 정의된 Amazon EC2 인스턴스 또는 오토 스케일링에 AWS 액세스 키 및 보안 키를 전달할 수도 있습니다. 다음 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html) 선언에서는 `UserData` 속성을 사용하여 `myaccesskey` 리소스에 대한 액세스 키 및 보안 암호 키를 전달합니다.

#### JSON
<a name="quickref-iam-example-4.json"></a>

```
"myinstance" : {
   "Type" : "AWS::EC2::Instance",
   "Properties" : {
      "AvailabilityZone" : "us-east-1a",
      "ImageId" : "ami-0ff8a91507f77f867",
      "UserData" : {
         "Fn::Base64" : {
            "Fn::Join" : [
               "", [
                  "ACCESS_KEY=", {
                     "Ref" : "myaccesskey"
                  },
                  "&",
                  "SECRET_KEY=",
                  {
                     "Fn::GetAtt" : [
                        "myaccesskey",
                        "SecretAccessKey"
                     ]
                  }
               ]
            ]
         }
      }
   }
}
```

#### YAML
<a name="quickref-iam-example-4.yaml"></a>

```
myinstance:
  Type: AWS::EC2::Instance
  Properties:
    AvailabilityZone: "us-east-1a"
    ImageId: ami-0ff8a91507f77f867
    UserData:
      Fn::Base64: !Sub "ACCESS_KEY=${myaccesskey}&SECRET_KEY=${myaccesskey.SecretAccessKey}"
```

## IAM 그룹 리소스 선언
<a name="scenario-iam-group"></a>

이 코드 조각은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-group.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-group.html) 리소스를 보여줍니다. 그룹에는 경로(`"/myapplication/"`)가 있습니다. 그룹의 사용자가 Amazon SQS 대기열 리소스 myqueue에 대해 모든 Amazon SQS 작업을 수행하고 `myqueue`를 제외한 기타 모든 Amazon SQS 리소스에 대한 액세스를 거부하도록 허용하는 정책 문서 `myapppolicy`가 그룹에 추가됩니다.

리소스에 정책을 할당하려면 IAM에는 해당 리소스에 대한 Amazon 리소스 이름(ARN)이 필요합니다. 코드 조각에서 `Fn::GetAtt` 함수는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sqs-queue.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sqs-queue.html) 리소스 대기열의 ARN을 가져옵니다.

### JSON
<a name="quickref-iam-example-5.json"></a>

```
"mygroup" : {
   "Type" : "AWS::IAM::Group",
   "Properties" : {
      "Path" : "/myapplication/",
      "Policies" : [ {
         "PolicyName" : "myapppolicy",
         "PolicyDocument" : {
            "Version": "2012-10-17",		 	 	 
            "Statement" : [ {
               "Effect" : "Allow",
               "Action" : [ "sqs:*" ],
               "Resource" : [ {
                  "Fn::GetAtt" : [ "myqueue", "Arn" ]
               } ]
            },
            {
               "Effect" : "Deny",
               "Action" : [ "sqs:*" ],
               "NotResource" : [ { "Fn::GetAtt" : [ "myqueue", "Arn" ] } ]
            }
         ] }
      } ]
   }
}
```

### YAML
<a name="quickref-iam-example-5.yaml"></a>

```
mygroup:
  Type: AWS::IAM::Group
  Properties:
    Path: "/myapplication/"
    Policies:
    - PolicyName: myapppolicy
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Action:
          - sqs:*
          Resource: !GetAtt myqueue.Arn
        - Effect: Deny
          Action:
          - sqs:*
          NotResource: !GetAtt myqueue.Arn
```

## 그룹에 사용자 추가
<a name="scenario-iam-addusertogroup"></a>

[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-usertogroupaddition.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-usertogroupaddition.html) 리소스는 그룹에 사용자를 추가합니다. 다음 코드 조각에서 `addUserToGroup` 리소스는 기존 사용자 `existinguser1` 및 템플릿에 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html) 리소스로 선언된 사용자 `myuser`를 기존 그룹 `myexistinggroup2`에 추가합니다.

### JSON
<a name="quickref-iam-example-6.json"></a>

```
"addUserToGroup" : {
   "Type" : "AWS::IAM::UserToGroupAddition",
   "Properties" : {
      "GroupName" : "myexistinggroup2",
      "Users" : [ "existinguser1", { "Ref" : "myuser" } ]
   }
}
```

### YAML
<a name="quickref-iam-example-6.yaml"></a>

```
addUserToGroup:
  Type: AWS::IAM::UserToGroupAddition
  Properties:
    GroupName: myexistinggroup2
    Users:
    - existinguser1
    - !Ref myuser
```

## IAM 정책 선언
<a name="scenario-iam-policy"></a>

이 코드 조각은 `mypolicy`라는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-policy.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-policy.html) 리소스를 사용하여 정책을 생성해 여러 그룹에 적용하는 방법을 보여줍니다. `mypolicy` 리소스에는 ARN `PolicyDocument`으로 표시되는 S3 버킷에 있는 객체에 대해 `GetObject`, `PutObject` 및 `PutObjectAcl` 작업을 허용하는 `arn:aws:s3:::myAWSBucket` 속성이 포함되어 있습니다. `mypolicy` 리소스는 기존 그룹 `myexistinggroup1` 및 템플릿에 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-group.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-group.html) 리소스로 선언된 그룹 `mygroup`에 정책을 적용합니다. 이 예에서는 `Groups` 속성을 사용하여 그룹에 정책을 적용하는 방법을 보여주지만 대신 `Users` 속성을 사용하여 사용자 목록에 정책 문서를 추가할 수도 있습니다.

### JSON
<a name="quickref-iam-example-7.json"></a>

```
"mypolicy" : {
   "Type" : "AWS::IAM::Policy",
   "Properties" : {
      "PolicyName" : "mygrouppolicy",
      "PolicyDocument" : {
         "Version": "2012-10-17",		 	 	 
         "Statement" : [ {
            "Effect" : "Allow",
            "Action" : [
               "s3:GetObject" , "s3:PutObject" , "s3:PutObjectAcl" ],
            "Resource" : "arn:aws:s3:::myAWSBucket/*"
         } ]
      },
      "Groups" : [ "myexistinggroup1", { "Ref" : "mygroup" } ]
   }
}
```

### YAML
<a name="quickref-iam-example-7.yaml"></a>

```
mypolicy:
  Type: AWS::IAM::Policy
  Properties:
    PolicyName: mygrouppolicy
    PolicyDocument:
      Version: '2012-10-17'
      Statement:
      - Effect: Allow
        Action:
        - s3:GetObject
        - s3:PutObject
        - s3:PutObjectAcl
        Resource: arn:aws:s3:::myAWSBucket/*
    Groups:
    - myexistinggroup1
    - !Ref mygroup
```

## Amazon S3 버킷 정책 선언
<a name="scenario-bucket-policy"></a>

이 코드 조각은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-s3-bucket.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-s3-bucket.html) 리소스를 사용하여 정책을 생성해 Amazon S3 버킷에 적용하는 방법을 보여줍니다. `mybucketpolicy` 리소스는 `user1` IAM 사용자가 정책이 적용되는 S3 버킷의 모든 객체에 대해 `GetObject` 작업을 수행하도록 허용하는 정책 문서를 선언합니다. 코드 조각에서 `Fn::GetAtt` 함수는 `user1` 리소스의 ARN을 가져옵니다. `mybucketpolicy` 리소스는 `AWS::S3::BucketPolicy` 리소스 mybucket에 정책을 적용합니다. `Ref` 함수는 `mybucket` 리소스의 버킷 이름을 가져옵니다.

### JSON
<a name="quickref-iam-example-8.json"></a>

```
"mybucketpolicy" : {
   "Type" : "AWS::S3::BucketPolicy",
   "Properties" : {
      "PolicyDocument" : {
         "Id" : "MyPolicy",
         "Version": "2012-10-17",		 	 	 
         "Statement" : [ {
            "Sid" : "ReadAccess",
            "Action" : [ "s3:GetObject" ],
            "Effect" : "Allow",
            "Resource" : { "Fn::Join" : [
                  "", [ "arn:aws:s3:::", { "Ref" : "mybucket" } , "/*" ]
               ] },
            "Principal" : {
               "AWS" : { "Fn::GetAtt" : [ "user1", "Arn" ] }
            }
         } ]
      },
      "Bucket" : { "Ref" : "mybucket" }
   }
}
```

### YAML
<a name="quickref-iam-example-8.yaml"></a>

```
mybucketpolicy:
  Type: AWS::S3::BucketPolicy
  Properties:
    PolicyDocument:
      Id: MyPolicy
      Version: '2012-10-17'
      Statement:
      - Sid: ReadAccess
        Action:
        - s3:GetObject
        Effect: Allow
        Resource: !Sub "arn:aws:s3:::${mybucket}/*"
        Principal:
          AWS: !GetAtt user1.Arn
    Bucket: !Ref mybucket
```

## Amazon SNS 주제 정책 선언
<a name="scenario-sns-policy"></a>

이 코드 조각은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-topicpolicy.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-topicpolicy.html) 리소스를 사용하여 정책을 생성해 Amazon SNS 주제에 적용하는 방법을 보여줍니다. `mysnspolicy` 리소스에는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html) 리소스 `myuser`가 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-topic.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sns-topic.html) 리소스 `mytopic`에서 `Publish` 작업을 수행하도록 허용하는 `PolicyDocument` 속성이 포함되어 있습니다. 이 코드 조각에서 `Fn::GetAtt` 함수는 `myuser` 리소스의 ARN을 가져오고, `Ref` 함수는 `mytopic` 리소스의 ARN을 가져옵니다.

### JSON
<a name="quickref-iam-example-9.json"></a>

```
"mysnspolicy" : {
   "Type" : "AWS::SNS::TopicPolicy",
   "Properties" : {
      "PolicyDocument" :  {
         "Id" : "MyTopicPolicy",
         "Version": "2012-10-17",		 	 	 
         "Statement" : [ {
            "Sid" : "My-statement-id",
            "Effect" : "Allow",
            "Principal" : {
               "AWS" : { "Fn::GetAtt" : [ "myuser", "Arn" ] }
            },
            "Action" : "sns:Publish",
            "Resource" : "*"
         } ]
      },
      "Topics" : [ { "Ref" : "mytopic" } ]
   }
}
```

### YAML
<a name="quickref-iam-example-9.yaml"></a>

```
mysnspolicy:
  Type: AWS::SNS::TopicPolicy
  Properties:
    PolicyDocument:
      Id: MyTopicPolicy
      Version: '2012-10-17'
      Statement:
      - Sid: My-statement-id
        Effect: Allow
        Principal:
          AWS: !GetAtt myuser.Arn
        Action: sns:Publish
        Resource: "*"
    Topics:
    - !Ref mytopic
```

## Amazon SQS 정책 선언
<a name="scenario-sqs-policy"></a>

이 코드 조각은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sqs-queuepolicy.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sqs-queuepolicy.html) 리소스를 사용하여 정책을 생성해 Amazon SQS 대기열에 적용하는 방법을 보여줍니다. `PolicyDocument` 속성은 기존 사용자 `myapp`(ARN으로 지정됨)이 기존 대기열(해당 URL로 지정됨) 및 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sqs-queue.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-sqs-queue.html) 리소스 myqueue에서 `SendMessage` 작업을 수행하도록 허용합니다. [Ref](resources-section-structure.md#resource-properties-ref) 함수는 `myqueue` 리소스 URL을 가져옵니다.

### JSON
<a name="quickref-iam-example-10.json"></a>

```
"mysqspolicy" : {
   "Type" : "AWS::SQS::QueuePolicy",
   "Properties" : {
      "PolicyDocument" : {
         "Id" : "MyQueuePolicy",
         "Version": "2012-10-17",		 	 	 
         "Statement" : [ {
            "Sid" : "Allow-User-SendMessage",
            "Effect" : "Allow",
            "Principal" : {
               "AWS" : "arn:aws:iam::123456789012:user/myapp"
            },
            "Action" : [ "sqs:SendMessage" ],
            "Resource" : "*"
         } ]
      },
      "Queues" : [
         "https://sqs.us-east-2aws-region.amazonaws.com/123456789012/myexistingqueue",
         { "Ref" : "myqueue" }
      ]
   }
}
```

### YAML
<a name="quickref-iam-example-10.yaml"></a>

```
mysqspolicy:
  Type: AWS::SQS::QueuePolicy
  Properties:
    PolicyDocument:
      Id: MyQueuePolicy
      Version: '2012-10-17'
      Statement:
      - Sid: Allow-User-SendMessage
        Effect: Allow
        Principal:
          AWS: arn:aws:iam::123456789012:user/myapp
        Action:
        - sqs:SendMessage
        Resource: "*"
    Queues:
    - https://sqs.aws-region.amazonaws.com/123456789012/myexistingqueue
    - !Ref myqueue
```

## IAM 역할 템플릿의 예
<a name="scenarios-iamroles"></a>

이 섹션에서는 EC2 인스턴스에 대한 IAM 역할의 CloudFormation 템플릿 예제를 제공합니다.

자세한 내용은 *Amazon EC2 사용 설명서*의 [Amazon EC2의 IAM 역할](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)을 참조하세요.

### EC2 관련 IAM 역할
<a name="scenario-iamrole-ec2"></a>

이 예제에서 인스턴스 프로파일은 EC2 인스턴스의 `IamInstanceProfile` 속성에서 참조합니다. 인스턴스 정책 및 역할 정책 둘 다에서 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-role.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-role.html)을 참조합니다.

#### JSON
<a name="quickref-iam-example-11.json"></a>

```
{
   "AWSTemplateFormatVersion": "2010-09-09",
   "Resources": {
      "myEC2Instance": {
         "Type": "AWS::EC2::Instance",
         "Version": "2009-05-15",
         "Properties": {
            "ImageId": "ami-0ff8a91507f77f867",
            "InstanceType": "m1.small",
            "Monitoring": "true",
            "DisableApiTermination": "false",
            "IamInstanceProfile": {
               "Ref": "RootInstanceProfile"
            }
         }
      },
      "RootRole": {
         "Type": "AWS::IAM::Role",
         "Properties": {
            "AssumeRolePolicyDocument": {
               "Version": "2012-10-17",		 	 	 
               "Statement": [ {
                  "Effect": "Allow",
                  "Principal": {
                     "Service": [ "ec2.amazonaws.com" ]
                  },
                  "Action": [ "sts:AssumeRole" ]
               } ]
            },
            "Path": "/"
         }
      },
      "RolePolicies": {
         "Type": "AWS::IAM::Policy",
         "Properties": {
            "PolicyName": "root",
            "PolicyDocument": {
               "Version": "2012-10-17",		 	 	 
               "Statement": [ {
                  "Effect": "Allow",
                  "Action": "*",
                  "Resource": "*"
               } ]
            },
            "Roles": [ { "Ref": "RootRole" } ]
         }
      },
      "RootInstanceProfile": {
         "Type": "AWS::IAM::InstanceProfile",
         "Properties": {
            "Path": "/",
            "Roles": [ { "Ref": "RootRole" } ]
         }
      }
   }
}
```

#### YAML
<a name="quickref-iam-example-11.yaml"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  myEC2Instance:
    Type: AWS::EC2::Instance
    Version: '2009-05-15'
    Properties:
      ImageId: ami-0ff8a91507f77f867
      InstanceType: m1.small
      Monitoring: 'true'
      DisableApiTermination: 'false'
      IamInstanceProfile:
        !Ref RootInstanceProfile
  RootRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - ec2.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
  RolePolicies:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: root
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Action: "*"
          Resource: "*"
      Roles:
      - !Ref RootRole
  RootInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: "/"
      Roles:
      - !Ref RootRole
```

### Auto Scaling 그룹 관련 IAM 역할
<a name="scenario-iamrole-asg"></a>

이 예제에서 인스턴스 프로파일은 Amazon EC2 Auto Scaling 시작 구성의 `IamInstanceProfile` 속성에서 참조합니다.

#### JSON
<a name="quickref-iam-example-12.json"></a>

```
{
   "AWSTemplateFormatVersion": "2010-09-09",
   "Resources": {
      "myLCOne": {
         "Type": "AWS::AutoScaling::LaunchConfiguration",
         "Version": "2009-05-15",
         "Properties": {
            "ImageId": "ami-0ff8a91507f77f867",
            "InstanceType": "m1.small",
            "InstanceMonitoring": "true",
            "IamInstanceProfile": { "Ref": "RootInstanceProfile" }
         }
      },
      "myASGrpOne": {
         "Type": "AWS::AutoScaling::AutoScalingGroup",
         "Version": "2009-05-15",
         "Properties": {
            "AvailabilityZones": [ "us-east-1a" ],
            "LaunchConfigurationName": { "Ref": "myLCOne" },
            "MinSize": "0",
            "MaxSize": "0",
            "HealthCheckType": "EC2",
            "HealthCheckGracePeriod": "120"
         }
      },
      "RootRole": {
         "Type": "AWS::IAM::Role",
         "Properties": {
            "AssumeRolePolicyDocument": {
               "Version": "2012-10-17",		 	 	 
               "Statement": [ {
                  "Effect": "Allow",
                  "Principal": {
                     "Service": [ "ec2.amazonaws.com" ]
                  },
                  "Action": [ "sts:AssumeRole" ]
               } ]
            },
            "Path": "/"
         }
      },
      "RolePolicies": {
         "Type": "AWS::IAM::Policy",
         "Properties": {
            "PolicyName": "root",
            "PolicyDocument": {
               "Version": "2012-10-17",		 	 	 
               "Statement": [ {
                  "Effect": "Allow",
                  "Action": "*",
                  "Resource": "*"
               } ]
            },
            "Roles": [ { "Ref": "RootRole" } ]
         }
      },
      "RootInstanceProfile": {
         "Type": "AWS::IAM::InstanceProfile",
         "Properties": {
            "Path": "/",
            "Roles": [ { "Ref": "RootRole" } ]
         }
      }
   }
}
```

#### YAML
<a name="quickref-iam-example-12.yaml"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  myLCOne:
    Type: AWS::AutoScaling::LaunchConfiguration
    Version: '2009-05-15'
    Properties:
      ImageId: ami-0ff8a91507f77f867
      InstanceType: m1.small
      InstanceMonitoring: 'true'
      IamInstanceProfile:
        !Ref RootInstanceProfile
  myASGrpOne:
    Type: AWS::AutoScaling::AutoScalingGroup
    Version: '2009-05-15'
    Properties:
      AvailabilityZones:
      - "us-east-1a"
      LaunchConfigurationName:
        !Ref myLCOne
      MinSize: '0'
      MaxSize: '0'
      HealthCheckType: EC2
      HealthCheckGracePeriod: '120'
  RootRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - ec2.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
  RolePolicies:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: root
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Action: "*"
          Resource: "*"
      Roles:
      - !Ref RootRole
  RootInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: "/"
      Roles:
      - !Ref RootRole
```

# AWS Lambda 템플릿
<a name="quickref-lambda"></a>

다음 템플릿에서는 AWS Lambda(Lambda) 함수와 사용자 지정 리소스를 사용하여 기존 보안 그룹 목록에 새 보안 그룹을 추가합니다. 이 함수는 목록에 새 보안 그룹과 기존 보안 그룹이 모두 포함되도록 보안 그룹의 목록을 동적으로 빌드하려는 경우에 유용합니다. 예를 들어, 기존 보안 그룹의 목록을 파라미터 값으로 전달하고, 새 값을 목록에 추가한 다음 모든 값을 EC2 인스턴스에 연결할 수 있습니다. Lambda 함수 리소스 유형에 대한 자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html)을 참조하세요.

이 예제에서 CloudFormation은 `AllSecurityGroups` 사용자 지정 리소스를 생성할 때 `AppendItemToListFunction` Lambda 함수를 간접적으로 호출합니다. CloudFormation은 기존 보안 그룹 목록과 새 보안 그룹(`NewSecurityGroup`)을 함수에 전달하고, 해당 함수는 새 보안 그룹을 목록에 추가한 다음 수정된 목록을 반환합니다. CloudFormation은 수정된 목록을 사용하여 모든 보안 그룹을 `MyEC2Instance` 리소스와 연결합니다.

## JSON
<a name="quickref-lambda-example-1.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "ExistingSecurityGroups": {
            "Type": "List<AWS::EC2::SecurityGroup::Id>"
        },
        "ExistingVPC": {
            "Type": "AWS::EC2::VPC::Id",
            "Description": "The VPC ID that includes the security groups in the ExistingSecurityGroups parameter."
        },
        "InstanceType": {
            "Type": "String",
            "Default": "t2.micro",
            "AllowedValues": [
                "t2.micro",
                "t3.micro"
            ]
        }
    },

    "Resources": {
        "SecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": "Allow HTTP traffic to the host",
                "VpcId": {
                    "Ref": "ExistingVPC"
                },
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 80,
                        "ToPort": 80,
                        "CidrIp": "0.0.0.0/0"
                    }
                ],
                "SecurityGroupEgress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 80,
                        "ToPort": 80,
                        "CidrIp": "0.0.0.0/0"
                    }
                ]
            }
        },
        "AllSecurityGroups": {
            "Type": "Custom::Split",
            "Properties": {
                "ServiceToken": {
                    "Fn::GetAtt": [
                        "AppendItemToListFunction",
                        "Arn"
                    ]
                },
                "List": {
                    "Ref": "ExistingSecurityGroups"
                },
                "AppendedItem": {
                    "Ref": "SecurityGroup"
                }
            }
        },
        "AppendItemToListFunction": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Handler": "index.handler",
                "Role": {
                    "Fn::GetAtt": [
                        "LambdaExecutionRole",
                        "Arn"
                    ]
                },
                "Code": {
                    "ZipFile": {
                        "Fn::Join": [
                            "",
                            [
                                "var response = require('cfn-response');",
                                "exports.handler = function(event, context) {",
                                "   var responseData = {Value: event.ResourceProperties.List};",
                                "   responseData.Value.push(event.ResourceProperties.AppendedItem);",
                                "   response.send(event, context, response.SUCCESS, responseData);",
                                "};"
                            ]
                        ]
                    }
                },
                "Runtime": "nodejs20.x"
            }
        },
        "MyEC2Instance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "ImageId": "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}",
                "SecurityGroupIds": {
                    "Fn::GetAtt": [
                        "AllSecurityGroups",
                        "Value"
                    ]
                },
                "InstanceType": {
                    "Ref": "InstanceType"
                }
            }
        },
        "LambdaExecutionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17", 		 	 	 
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "lambda.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "Path": "/",
                "Policies": [
                    {
                        "PolicyName": "root",
                        "PolicyDocument": {
                            "Version": "2012-10-17", 		 	 	 
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "logs:*"
                                    ],
                                    "Resource": "arn:aws:logs:*:*:*"
                                }
                            ]
                        }
                    }
                ]
            }
        }
    },
    "Outputs": {
        "AllSecurityGroups": {
            "Description": "Security Groups that are associated with the EC2 instance",
            "Value": {
                "Fn::Join": [
                    ", ",
                    {
                        "Fn::GetAtt": [
                            "AllSecurityGroups",
                            "Value"
                        ]
                    }
                ]
            }
        }
    }
}
```

## YAML
<a name="quickref-lambda-example-1.yaml"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  ExistingSecurityGroups:
    Type: List<AWS::EC2::SecurityGroup::Id>
  ExistingVPC:
    Type: AWS::EC2::VPC::Id
    Description: The VPC ID that includes the security groups in the ExistingSecurityGroups parameter.
  InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues:
      - t2.micro
      - t3.micro
Resources:
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP traffic to the host
      VpcId: !Ref ExistingVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
  AllSecurityGroups:
    Type: Custom::Split
    Properties:
      ServiceToken: !GetAtt AppendItemToListFunction.Arn
      List: !Ref ExistingSecurityGroups
      AppendedItem: !Ref SecurityGroup
  AppendItemToListFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: !Join
          - ''
          - - var response = require('cfn-response');
            - exports.handler = function(event, context) {
            - '   var responseData = {Value: event.ResourceProperties.List};'
            - '   responseData.Value.push(event.ResourceProperties.AppendedItem);'
            - '   response.send(event, context, response.SUCCESS, responseData);'
            - '};'
      Runtime: nodejs20.x
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
      SecurityGroupIds: !GetAtt AllSecurityGroups.Value
      InstanceType: !Ref InstanceType
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17' 		 	 	 
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: '2012-10-17' 		 	 	 
            Statement:
              - Effect: Allow
                Action:
                  - logs:*
                Resource: arn:aws:logs:*:*:*
Outputs:
  AllSecurityGroups:
    Description: Security Groups that are associated with the EC2 instance
    Value: !Join
      - ', '
      - !GetAtt AllSecurityGroups.Value
```

# Amazon Redshift 템플릿 코드 조각
<a name="quickref-redshift"></a>

Amazon Redshift는 클라우드에서 완전히 관리되는 페타바이트급 데이터 웨어하우스 서비스입니다. CloudFormation을 사용하여 Amazon Redshift 클러스터를 프로비저닝하고 관리할 수 있습니다.

## Amazon Redshift 클러스터
<a name="quickref-redshift-samplecluster"></a>

다음 샘플 템플릿은 스택 생성 시 지정된 파라미터 값에 따라 Amazon Redshift 클러스터를 생성합니다. Amazon Redshift 클러스터와 연결된 클러스터 파라미터 그룹은 사용자 활동 로깅을 가능하게 합니다. 또한 이 템플릿은 템플릿에 정의된 Amazon VPC에서 Amazon Redshift 클러스터를 시작합니다. VPC에는 인터넷 게이트웨이가 포함되어 있어 인터넷에서 Amazon Redshift 클러스터에 액세스할 수 있습니다. 그러나 클러스터와 인터넷 게이트웨이 간에 통신이 활성화되어 있어야 하며, 통신은 라우팅 테이블 항목을 통해 활성화합니다.

**참고**  
템플릿에는 `IsMultiNodeCluster` 파라미터 값이 `NumberOfNodes`로 설정된 경우에만 `ClusterType` 파라미터가 선언되는 `multi-node` 조건이 포함되어 있습니다.

이 예에서는 `MysqlRootPassword` 속성이 `NoEcho`로 설정된 `true` 파라미터를 정의합니다. `NoEcho` 속성을 `true`로 설정한 경우, 아래 지정된 위치에 저장된 정보를 제외하고 CloudFormation은 스택 또는 스택 이벤트를 설명하는 모든 호출에 대해 별표(\$1\$1\$1\$1\$1)로 마스킹 처리된 파라미터 값을 반환합니다.

**중요**  
`NoEcho` 속성을 사용해도 다음에 저장된 정보는 마스킹되지 않습니다.  
`Metadata` 템플릿 섹션. CloudFormation은 `Metadata` 섹션에 포함된 정보를 변환, 수정 또는 삭제하지 않습니다. 자세한 내용은 [메타데이터](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html)를 참조하십시오.
`Outputs` 템플릿 섹션. 자세한 내용은 [출력](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html)을 참조하십시오.
리소스 정의의 `Metadata` 속성입니다. 자세한 내용은 [`Metadata` 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-metadata.html)을 참조하세요.
이러한 메커니즘을 사용하여 암호나 보안 정보와 같은 중요한 정보를 포함하지 않는 것이 좋습니다.

**중요**  
AWS Systems Manager Parameter Store 또는 AWS Secrets Manager와 같이 CloudFormation 외부에서 저장 및 관리되는 중요한 정보를 참조하려면 CloudFormation 템플릿에 직접 중요한 정보를 포함하는 대신 스택 템플릿에 있는 동적 파라미터를 사용하는 것이 좋습니다.  
자세한 내용은 [템플릿에 자격 증명을 포함하지 않음](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/security-best-practices.html#creds)을 참조하십시오.

### JSON
<a name="quickref-redshift-example-1.json"></a>

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters" : {
    "DatabaseName" : {
      "Description" : "The name of the first database to be created when the cluster is created",
      "Type" : "String",
      "Default" : "dev",
      "AllowedPattern" : "([a-z]|[0-9])+"
    },
    "ClusterType" : {
      "Description" : "The type of cluster",
      "Type" : "String",
      "Default" : "single-node",
      "AllowedValues" : [ "single-node", "multi-node" ]
    },
    "NumberOfNodes" : {
      "Description" : "The number of compute nodes in the cluster. For multi-node clusters, the NumberOfNodes parameter must be greater than 1",
      "Type" : "Number",
      "Default" : "1"
    },
    "NodeType" : {
      "Description" : "The type of node to be provisioned",
      "Type" : "String",
      "Default" : "ds2.xlarge",
      "AllowedValues" : [ "ds2.xlarge", "ds2.8xlarge", "dc1.large", "dc1.8xlarge" ]
    }, 
    "MasterUsername" : {
      "Description" : "The user name that is associated with the master user account for the cluster that is being created",
      "Type" : "String",
      "Default" : "defaultuser",
      "AllowedPattern" : "([a-z])([a-z]|[0-9])*"
    },
    "MasterUserPassword" :  {
      "Description" : "The password that is associated with the master user account for the cluster that is being created.",
      "Type" : "String",
      "NoEcho" : "true"
    },
    "InboundTraffic" : {
      "Description" : "Allow inbound traffic to the cluster from this CIDR range.",
      "Type" : "String",
      "MinLength": "9",
      "MaxLength": "18",
      "Default" : "0.0.0.0/0",
      "AllowedPattern" : "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
      "ConstraintDescription" : "must be a valid CIDR range of the form x.x.x.x/x."
    },
    "PortNumber" : {
      "Description" : "The port number on which the cluster accepts incoming connections.",
      "Type" : "Number",
      "Default" : "5439"
    }
  },
  "Conditions" : {
    "IsMultiNodeCluster" : {
      "Fn::Equals" : [{ "Ref" : "ClusterType" }, "multi-node" ]        
    }
  },
  "Resources" : {
    "RedshiftCluster" : {
      "Type" : "AWS::Redshift::Cluster",
      "DependsOn" : "AttachGateway",
      "Properties" : {
        "ClusterType" : { "Ref" : "ClusterType" },
        "NumberOfNodes" : { "Fn::If" : [ "IsMultiNodeCluster",  { "Ref" : "NumberOfNodes" }, { "Ref" : "AWS::NoValue" }]},
        "NodeType" : { "Ref" : "NodeType" },
        "DBName" : { "Ref" : "DatabaseName" },
        "MasterUsername" : { "Ref" : "MasterUsername" },
        "MasterUserPassword" : { "Ref" : "MasterUserPassword" },               
        "ClusterParameterGroupName" : { "Ref" : "RedshiftClusterParameterGroup" },
        "VpcSecurityGroupIds" : [ { "Ref" : "SecurityGroup" } ],
        "ClusterSubnetGroupName" : { "Ref" : "RedshiftClusterSubnetGroup" },
        "PubliclyAccessible" : "true",
        "Port" : { "Ref" : "PortNumber" }
      }
    },
    "RedshiftClusterParameterGroup" : {
      "Type" : "AWS::Redshift::ClusterParameterGroup",
      "Properties" : {
        "Description" : "Cluster parameter group",
        "ParameterGroupFamily" : "redshift-1.0",
        "Parameters" : [{
          "ParameterName" : "enable_user_activity_logging",
          "ParameterValue" : "true"
        }]
      }
    },
    "RedshiftClusterSubnetGroup" : {
      "Type" : "AWS::Redshift::ClusterSubnetGroup",
      "Properties" : {
        "Description" : "Cluster subnet group",
        "SubnetIds" : [ { "Ref" : "PublicSubnet" } ]
      }
    },
    "VPC" : {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : "10.0.0.0/16"
      }
    },
    "PublicSubnet" : {
      "Type" : "AWS::EC2::Subnet",
      "Properties" : {
        "CidrBlock" : "10.0.0.0/24",
        "VpcId" : { "Ref" : "VPC" }
      }
    },
    "SecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Security group",
        "SecurityGroupIngress" : [ {
          "CidrIp" : { "Ref": "InboundTraffic" },
          "FromPort" : { "Ref" : "PortNumber" },
          "ToPort" : { "Ref" : "PortNumber" },
          "IpProtocol" : "tcp"
        } ],
        "VpcId" : { "Ref" : "VPC" }
      }
    },
    "myInternetGateway" : {
      "Type" : "AWS::EC2::InternetGateway"
    },
    "AttachGateway" : {
      "Type" : "AWS::EC2::VPCGatewayAttachment",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "InternetGatewayId" : { "Ref" : "myInternetGateway" }
      }
    },
    "PublicRouteTable" : {
      "Type" : "AWS::EC2::RouteTable",
      "Properties" : {
        "VpcId" : {
          "Ref" : "VPC"
        }
      }
    },
    "PublicRoute" : {
      "Type" : "AWS::EC2::Route",
      "DependsOn" : "AttachGateway",
      "Properties"  : {
        "RouteTableId" : {
          "Ref" : "PublicRouteTable"
        },
        "DestinationCidrBlock" : "0.0.0.0/0",
        "GatewayId" : {
          "Ref" : "myInternetGateway"
        }
      }
    },
    "PublicSubnetRouteTableAssociation" : {
      "Type" : "AWS::EC2::SubnetRouteTableAssociation",
      "Properties" : {
        "SubnetId" : {
          "Ref" : "PublicSubnet"
        },
        "RouteTableId" : {
          "Ref" : "PublicRouteTable"
        }
      }
    }
  },
  "Outputs" : {
    "ClusterEndpoint" : {
      "Description" : "Cluster endpoint",
      "Value" : { "Fn::Join" : [ ":", [ { "Fn::GetAtt" : [ "RedshiftCluster", "Endpoint.Address" ] }, { "Fn::GetAtt" : [ "RedshiftCluster", "Endpoint.Port" ] } ] ] }
    },
    "ClusterName" : {
      "Description" : "Name of cluster",
      "Value" : { "Ref" : "RedshiftCluster" }
    },
    "ParameterGroupName" : {
      "Description" : "Name of parameter group",
      "Value" : { "Ref" : "RedshiftClusterParameterGroup" }
    },
    "RedshiftClusterSubnetGroupName" : {
      "Description" : "Name of cluster subnet group",
      "Value" : { "Ref" : "RedshiftClusterSubnetGroup" }
    },
    "RedshiftClusterSecurityGroupName" : {
      "Description" : "Name of cluster security group",
      "Value" : { "Ref" : "SecurityGroup" }
    }
  }
}
```

### YAML
<a name="quickref-redshift-example-1.yaml"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  DatabaseName:
    Description: The name of the first database to be created when the cluster is
      created
    Type: String
    Default: dev
    AllowedPattern: "([a-z]|[0-9])+"
  ClusterType:
    Description: The type of cluster
    Type: String
    Default: single-node
    AllowedValues:
    - single-node
    - multi-node
  NumberOfNodes:
    Description: The number of compute nodes in the cluster. For multi-node clusters,
      the NumberOfNodes parameter must be greater than 1
    Type: Number
    Default: '1'
  NodeType:
    Description: The type of node to be provisioned
    Type: String
    Default: ds2.xlarge
    AllowedValues:
    - ds2.xlarge
    - ds2.8xlarge
    - dc1.large
    - dc1.8xlarge
  MasterUsername:
    Description: The user name that is associated with the master user account for
      the cluster that is being created
    Type: String
    Default: defaultuser
    AllowedPattern: "([a-z])([a-z]|[0-9])*"
  MasterUserPassword:
    Description: The password that is associated with the master user account for
      the cluster that is being created.
    Type: String
    NoEcho: 'true'
  InboundTraffic:
    Description: Allow inbound traffic to the cluster from this CIDR range.
    Type: String
    MinLength: '9'
    MaxLength: '18'
    Default: 0.0.0.0/0
    AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
    ConstraintDescription: must be a valid CIDR range of the form x.x.x.x/x.
  PortNumber:
    Description: The port number on which the cluster accepts incoming connections.
    Type: Number
    Default: '5439'
Conditions:
  IsMultiNodeCluster:
    Fn::Equals:
    - Ref: ClusterType
    - multi-node
Resources:
  RedshiftCluster:
    Type: AWS::Redshift::Cluster
    DependsOn: AttachGateway
    Properties:
      ClusterType:
        Ref: ClusterType
      NumberOfNodes:
        Fn::If:
        - IsMultiNodeCluster
        - Ref: NumberOfNodes
        - Ref: AWS::NoValue
      NodeType:
        Ref: NodeType
      DBName:
        Ref: DatabaseName
      MasterUsername:
        Ref: MasterUsername
      MasterUserPassword:
        Ref: MasterUserPassword
      ClusterParameterGroupName:
        Ref: RedshiftClusterParameterGroup
      VpcSecurityGroupIds:
      - Ref: SecurityGroup
      ClusterSubnetGroupName:
        Ref: RedshiftClusterSubnetGroup
      PubliclyAccessible: 'true'
      Port:
        Ref: PortNumber
  RedshiftClusterParameterGroup:
    Type: AWS::Redshift::ClusterParameterGroup
    Properties:
      Description: Cluster parameter group
      ParameterGroupFamily: redshift-1.0
      Parameters:
      - ParameterName: enable_user_activity_logging
        ParameterValue: 'true'
  RedshiftClusterSubnetGroup:
    Type: AWS::Redshift::ClusterSubnetGroup
    Properties:
      Description: Cluster subnet group
      SubnetIds:
      - Ref: PublicSubnet
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: 10.0.0.0/24
      VpcId:
        Ref: VPC
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group
      SecurityGroupIngress:
      - CidrIp:
          Ref: InboundTraffic
        FromPort:
          Ref: PortNumber
        ToPort:
          Ref: PortNumber
        IpProtocol: tcp
      VpcId:
        Ref: VPC
  myInternetGateway:
    Type: AWS::EC2::InternetGateway
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId:
        Ref: VPC
      InternetGatewayId:
        Ref: myInternetGateway
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId:
        Ref: VPC
  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId:
        Ref: PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId:
        Ref: myInternetGateway
  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId:
        Ref: PublicSubnet
      RouteTableId:
        Ref: PublicRouteTable
Outputs:
  ClusterEndpoint:
    Description: Cluster endpoint
    Value: !Sub "${RedshiftCluster.Endpoint.Address}:${RedshiftCluster.Endpoint.Port}"
  ClusterName:
    Description: Name of cluster
    Value:
      Ref: RedshiftCluster
  ParameterGroupName:
    Description: Name of parameter group
    Value:
      Ref: RedshiftClusterParameterGroup
  RedshiftClusterSubnetGroupName:
    Description: Name of cluster subnet group
    Value:
      Ref: RedshiftClusterSubnetGroup
  RedshiftClusterSecurityGroupName:
    Description: Name of cluster security group
    Value:
      Ref: SecurityGroup
```

## 다음 사항도 참조하세요.
<a name="w2aac11c41c72b7"></a>

[AWS::Redshift::Cluster](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-redshift-cluster.html)

# Amazon RDS 템플릿 코드 조각
<a name="quickref-rds"></a>

**Topics**
+ [Amazon RDS DB 인스턴스 리소스](#scenario-rds-instance)
+ [Amazon RDS Oracle Database DB 인스턴스 리소스](#scenario-rds-oracleinstance)
+ [CIDR 범위에 대한 Amazon RDS DBSecurityGroup 리소스](#scenario-rds-security-group-cidr)
+ [Amazon EC2 보안 그룹을 포함하는 Amazon RDS DBSecurityGroup](#scenario-rds-security-group-ec2)
+ [여러 VPC 보안 그룹](#scenario-multiple-vpc-security-groups)
+ [VPC 보안 그룹 내 Amazon RDS 데이터베이스 인스턴스](#w2aac11c41c76c15)

## Amazon RDS DB 인스턴스 리소스
<a name="scenario-rds-instance"></a>

이 예에서는 관리형 마스터 사용자 암호를 사용하는 Amazon RDS DB 인스턴스 리소스를 보여 줍니다. 자세한 내용은 **Amazon RDS 사용 설명서의 [AWS Secrets Manager를 통한 암호 관리](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-secrets-manager.html) 및 **Aurora 사용 설명서의 [AWS Secrets Manager를 통한 암호 관리](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/rds-secrets-manager.html)를 참조하세요. 선택 사항인 `EngineVersion` 속성을 지정하지 않은 경우 기본 엔진 버전이 이 DB 인스턴스에 사용됩니다. 기본 엔진 버전과 기타 기본 설정에 대한 자세한 내용은 [CreateDBInstance](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html)를 참조하십시오. `DBSecurityGroups` 속성은 `MyDbSecurityByEC2SecurityGroup`과 MyDbSecurityByCIDRIPGroup이라는 `AWS::RDS::DBSecurityGroup` 리소스에 대한 네트워크 수신을 승인합니다. 자세한 내용은 섹션을 참조하세요[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbinstance.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbinstance.html) 또한 DB 인스턴스 리소스에서는 `DeletionPolicy` 속성을 `Snapshot`으로 설정합니다. `Snapshot` `DeletionPolicy` 세트를 사용하여 CloudFormation에서는 스택 삭제 중 이 DB 인스턴스를 삭제하기 전에 스냅샷을 생성합니다.

### JSON
<a name="quickref-rds-example-1.json"></a>

```
 1. "MyDB" : {
 2.  "Type" : "AWS::RDS::DBInstance",
 3.  "Properties" : {
 4.      "DBSecurityGroups" : [
 5.         {"Ref" : "MyDbSecurityByEC2SecurityGroup"}, {"Ref" : "MyDbSecurityByCIDRIPGroup"} ],
 6.      "AllocatedStorage" : "5",
 7.      "DBInstanceClass" : "db.t2.small",
 8.      "Engine" : "MySQL",
 9.      "MasterUsername" : "MyName",
10.      "ManageMasterUserPassword" : true,
11.      "MasterUserSecret" : {
12.         "KmsKeyId" : {"Ref" : "KMSKey"}
13.      }
14.  },
15.  "DeletionPolicy" : "Snapshot"
16. }
```

### YAML
<a name="quickref-rds-example-1.yaml"></a>

```
 1. MyDB:
 2.   Type: AWS::RDS::DBInstance
 3.   Properties:
 4.     DBSecurityGroups:
 5.     - Ref: MyDbSecurityByEC2SecurityGroup
 6.     - Ref: MyDbSecurityByCIDRIPGroup
 7.     AllocatedStorage: '5'
 8.     DBInstanceClass: db.t2.small
 9.     Engine: MySQL
10.     MasterUsername: MyName
11.     ManageMasterUserPassword: true
12.     MasterUserSecret:
13.       KmsKeyId: !Ref KMSKey
14.   DeletionPolicy: Snapshot
```

## Amazon RDS Oracle Database DB 인스턴스 리소스
<a name="scenario-rds-oracleinstance"></a>

이 예에서는 관리형 마스터 사용자 암호를 사용하는 Oracle Database DB 인스턴스 리소스를 생성합니다. 자세한 내용은 **Amazon RDS 사용 설명서의 [AWS Secrets Manager를 통한 암호 관리](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-secrets-manager.html)를 참조하세요. 이 예제는 `Engine`을 `oracle-ee`로 지정하고 라이선스 모델로 기존 보유 라이선스 사용을 사용합니다. Oracle Database DB 인스턴스 설정에 대한 자세한 내용은 [CreateDBInstance](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html)를 참조하십시오. DBSecurityGroups 속성은 MyDbSecurityByEC2SecurityGroup 및 MyDbSecurityByCIDRIPGroup이라는 `AWS::RDS::DBSecurityGroup` 리소스에 네트워크 진입을 허가합니다. 자세한 내용은 섹션을 참조하세요[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbinstance.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbinstance.html) 또한 DB 인스턴스 리소스에서는 `DeletionPolicy` 속성을 `Snapshot`으로 설정합니다. `Snapshot` `DeletionPolicy` 세트를 사용하여 CloudFormation에서는 스택 삭제 중 이 DB 인스턴스를 삭제하기 전에 스냅샷을 생성합니다.

### JSON
<a name="quickref-rds-example-2.json"></a>

```
 1. "MyDB" : {
 2.  "Type" : "AWS::RDS::DBInstance",
 3.  "Properties" : {
 4.      "DBSecurityGroups" : [
 5.         {"Ref" : "MyDbSecurityByEC2SecurityGroup"}, {"Ref" : "MyDbSecurityByCIDRIPGroup"} ],
 6.      "AllocatedStorage" : "5",
 7.      "DBInstanceClass" : "db.t2.small",
 8.      "Engine" : "oracle-ee",
 9.      "LicenseModel" : "bring-your-own-license",
10.      "MasterUsername" : "master",
11.      "ManageMasterUserPassword" : true,
12.      "MasterUserSecret" : {
13.         "KmsKeyId" : {"Ref" : "KMSKey"}
14.      }
15.  },
16.  "DeletionPolicy" : "Snapshot"
17. }
```

### YAML
<a name="quickref-rds-example-2.yaml"></a>

```
 1. MyDB:
 2.   Type: AWS::RDS::DBInstance
 3.   Properties:
 4.     DBSecurityGroups:
 5.     - Ref: MyDbSecurityByEC2SecurityGroup
 6.     - Ref: MyDbSecurityByCIDRIPGroup
 7.     AllocatedStorage: '5'
 8.     DBInstanceClass: db.t2.small
 9.     Engine: oracle-ee
10.     LicenseModel: bring-your-own-license
11.     MasterUsername: master
12.     ManageMasterUserPassword: true
13.     MasterUserSecret:
14.       KmsKeyId: !Ref KMSKey
15.   DeletionPolicy: Snapshot
```

## CIDR 범위에 대한 Amazon RDS DBSecurityGroup 리소스
<a name="scenario-rds-security-group-cidr"></a>

이 예제는 `ddd.ddd.ddd.ddd/dd` 형식으로 지정된 CIDR 범위에 대한 수신 권한이 부여된 Amazon RDS `DBSecurityGroup` 리소스를 보여줍니다. 자세한 내용은 [AWS::RDS::DBSecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbsecuritygroup.html) 및 [Ingress](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-rds-dbsecuritygroup-ingress.html)를 참조하십시오.

### JSON
<a name="quickref-rds-example-3.json"></a>

```
1. "MyDbSecurityByCIDRIPGroup" : {
2.  "Type" : "AWS::RDS::DBSecurityGroup",
3.  "Properties" : {
4.      "GroupDescription" : "Ingress for CIDRIP",
5.      "DBSecurityGroupIngress" : {
6.          "CIDRIP" : "192.168.0.0/32"
7.      }
8.  }
9. }
```

### YAML
<a name="quickref-rds-example-3.yaml"></a>

```
1. MyDbSecurityByCIDRIPGroup:
2.   Type: AWS::RDS::DBSecurityGroup
3.   Properties:
4.     GroupDescription: Ingress for CIDRIP
5.     DBSecurityGroupIngress:
6.       CIDRIP: "192.168.0.0/32"
```

## Amazon EC2 보안 그룹을 포함하는 Amazon RDS DBSecurityGroup
<a name="scenario-rds-security-group-ec2"></a>

이 예제는 `MyEc2SecurityGroup`에서 참조되는 Amazon EC2 보안 그룹으로부터 수신 권한 부여를 받은 [AWS::RDS::DBSecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbsecuritygroup.html) 리소스를 보여줍니다.

이렇게 하려면 EC2 보안 그룹을 정의한 다음 내장 `Ref` 함수를 사용하여 `DBSecurityGroup` 내에서 EC2 보안 그룹을 참조합니다.

### JSON
<a name="quickref-rds-example-4.json"></a>

```
"DBInstance" : {
   "Type": "AWS::RDS::DBInstance",
   "Properties": {
      "DBName"            : { "Ref" : "DBName" },
      "Engine"            : "MySQL",
      "MasterUsername"    : { "Ref" : "DBUsername" },
      "DBInstanceClass"   : { "Ref" : "DBClass" },
      "DBSecurityGroups"  : [ { "Ref" : "DBSecurityGroup" } ],
      "AllocatedStorage"  : { "Ref" : "DBAllocatedStorage" },
      "MasterUserPassword": { "Ref" : "DBPassword" }
   }
},

"DBSecurityGroup": {
   "Type": "AWS::RDS::DBSecurityGroup",
   "Properties": {
      "DBSecurityGroupIngress": {
         "EC2SecurityGroupName": {
            "Fn::GetAtt": ["WebServerSecurityGroup", "GroupName"]
         }
      },
      "GroupDescription" : "Frontend Access"
   }
},

"WebServerSecurityGroup" : {
   "Type" : "AWS::EC2::SecurityGroup",
   "Properties" : {
      "GroupDescription" : "Enable HTTP access via port 80 and SSH access",
      "SecurityGroupIngress" : [
         {"IpProtocol" : "tcp", "FromPort" : 80, "ToPort" : 80, "CidrIp" : "0.0.0.0/0"},
         {"IpProtocol" : "tcp", "FromPort" : 22, "ToPort" : 22, "CidrIp" : "0.0.0.0/0"}
      ]
   }
}
```

### YAML
<a name="quickref-rds-example-4.yaml"></a>

이 예는 다음 전체 예제에서 추출되었습니다. [Drupal\$1Single\$1Instance\$1With\$1RDS.template](https://s3.amazonaws.com/cloudformation-templates-us-east-1/Drupal_Single_Instance_With_RDS.template)

```
DBInstance:
  Type: AWS::RDS::DBInstance
  Properties:
    DBName:
      Ref: DBName
    Engine: MySQL
    MasterUsername:
      Ref: DBUsername
    DBInstanceClass:
      Ref: DBClass
    DBSecurityGroups:
    - Ref: DBSecurityGroup
    AllocatedStorage:
      Ref: DBAllocatedStorage
    MasterUserPassword:
      Ref: DBPassword
DBSecurityGroup:
  Type: AWS::RDS::DBSecurityGroup
  Properties:
    DBSecurityGroupIngress:
      EC2SecurityGroupName:
        Ref: WebServerSecurityGroup
    GroupDescription: Frontend Access
WebServerSecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: Enable HTTP access via port 80 and SSH access
    SecurityGroupIngress:
    - IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      CidrIp: 0.0.0.0/0
    - IpProtocol: tcp
      FromPort: 22
      ToPort: 22
      CidrIp: 0.0.0.0/0
```

## 여러 VPC 보안 그룹
<a name="scenario-multiple-vpc-security-groups"></a>

이 예제에서는 [AWS::RDS::DBSecurityGroupIngress](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbsecuritygroupingress.html)에서 여러 Amazon EC2 VPC 보안 그룹에 대한 수신 권한 부여를 받은 [AWS::RDS::DBSecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbsecuritygroup.html) 리소스를 보여줍니다.

### JSON
<a name="quickref-rds-example-5.json"></a>

```
{
   "Resources" : {
      "DBinstance" : {
         "Type" : "AWS::RDS::DBInstance",
         "Properties" : {
            "AllocatedStorage" : "5",
            "DBInstanceClass" : "db.t2.small",
           "DBName" : {"Ref": "MyDBName" },
            "DBSecurityGroups" : [ { "Ref" : "DbSecurityByEC2SecurityGroup" } ],
            "DBSubnetGroupName" : { "Ref" : "MyDBSubnetGroup" },
            "Engine" : "MySQL",
           "MasterUserPassword": { "Ref" : "MyDBPassword" },
           "MasterUsername"    : { "Ref" : "MyDBUsername" }
        },
         "DeletionPolicy" : "Snapshot"
      },
      "DbSecurityByEC2SecurityGroup" : {
         "Type" : "AWS::RDS::DBSecurityGroup",
         "Properties" : {
            "GroupDescription" : "Ingress for Amazon EC2 security group",
           "EC2VpcId" : { "Ref" : "MyVPC" },
            "DBSecurityGroupIngress" : [ {
               "EC2SecurityGroupId" : "sg-b0ff1111",
               "EC2SecurityGroupOwnerId" : "111122223333"
            }, {
               "EC2SecurityGroupId" : "sg-ffd722222",
               "EC2SecurityGroupOwnerId" : "111122223333"
            } ]
         }
      }
   }
}
```

### YAML
<a name="quickref-rds-example-5.yaml"></a>

```
Resources:
  DBinstance:
    Type: AWS::RDS::DBInstance
    Properties:
      AllocatedStorage: '5'
      DBInstanceClass: db.t2.small
      DBName:
        Ref: MyDBName
      DBSecurityGroups:
      - Ref: DbSecurityByEC2SecurityGroup
      DBSubnetGroupName:
        Ref: MyDBSubnetGroup
      Engine: MySQL
      MasterUserPassword:
        Ref: MyDBPassword
      MasterUsername:
        Ref: MyDBUsername
    DeletionPolicy: Snapshot
  DbSecurityByEC2SecurityGroup:
    Type: AWS::RDS::DBSecurityGroup
    Properties:
      GroupDescription: Ingress for Amazon EC2 security group
      EC2VpcId:
        Ref: MyVPC
      DBSecurityGroupIngress:
      - EC2SecurityGroupId: sg-b0ff1111
        EC2SecurityGroupOwnerId: '111122223333'
      - EC2SecurityGroupId: sg-ffd722222
        EC2SecurityGroupOwnerId: '111122223333'
```

## VPC 보안 그룹 내 Amazon RDS 데이터베이스 인스턴스
<a name="w2aac11c41c76c15"></a>

이 예에서는 Amazon EC2 VPC 보안 그룹과 연결된 Amazon RDS 데이터베이스 인스턴스를 보여줍니다.

### JSON
<a name="quickref-rds-example-6.json"></a>

```
{
  "DBEC2SecurityGroup": {
    "Type": "AWS::EC2::SecurityGroup",
    "Properties" : {
      "GroupDescription": "Open database for access",
      "SecurityGroupIngress" : [{
        "IpProtocol" : "tcp",
        "FromPort" : 3306,
        "ToPort" : 3306,
        "SourceSecurityGroupName" : { "Ref" : "WebServerSecurityGroup" }
      }]
    }
  },
  "DBInstance" : {
    "Type": "AWS::RDS::DBInstance",
    "Properties": {
      "DBName"            : { "Ref" : "DBName" },
      "Engine"            : "MySQL",
      "MultiAZ"           : { "Ref": "MultiAZDatabase" },
      "MasterUsername"    : { "Ref" : "DBUser" },
      "DBInstanceClass"   : { "Ref" : "DBClass" },
      "AllocatedStorage"  : { "Ref" : "DBAllocatedStorage" },
      "MasterUserPassword": { "Ref" : "DBPassword" },
      "VPCSecurityGroups" : [ { "Fn::GetAtt": [ "DBEC2SecurityGroup", "GroupId" ] } ]
    }
  }
}
```

### YAML
<a name="quickref-rds-example-6.yaml"></a>

```
DBEC2SecurityGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: Open database for access
    SecurityGroupIngress:
    - IpProtocol: tcp
      FromPort: 3306
      ToPort: 3306
      SourceSecurityGroupName:
        Ref: WebServerSecurityGroup
DBInstance:
  Type: AWS::RDS::DBInstance
  Properties:
    DBName:
      Ref: DBName
    Engine: MySQL
    MultiAZ:
      Ref: MultiAZDatabase
    MasterUsername:
      Ref: DBUser
    DBInstanceClass:
      Ref: DBClass
    AllocatedStorage:
      Ref: DBAllocatedStorage
    MasterUserPassword:
      Ref: DBPassword
    VPCSecurityGroups:
    - !GetAtt DBEC2SecurityGroup.GroupId
```

# Route 53 템플릿 코드 조각
<a name="quickref-route53"></a>

**Topics**
+ [호스팅 영역 이름 또는 ID를 사용하는 Amazon Route 53 리소스 레코드 세트](#scenario-route53-recordset-by-host)
+ [RecordSetGroup을 사용하여 가중치 기반 리소스 레코드 세트 설정](#scenario-recordsetgroup-weighted)
+ [RecordSetGroup을 사용하여 별칭 리소스 레코드 세트 설정](#scenario-recordsetgroup-zoneapex)
+ [CloudFront 배포에 대한 별칭 리소스 레코드 세트](#scenario-user-friendly-url-for-cloudfront-distribution)

## 호스팅 영역 이름 또는 ID를 사용하는 Amazon Route 53 리소스 레코드 세트
<a name="scenario-route53-recordset-by-host"></a>

Amazon Route 53 리소스 레코드 세트 생성 시 이러한 레코드 세트를 추가할 호스팅 영역을 지정해야 합니다. CloudFormation은 호스팅 영역을 지정하는 두 가지 방법을 제공합니다.
+ `HostedZoneId` 속성을 사용하여 호스팅 영역을 명시적으로 지정할 수 있습니다.
+ `HostedZoneName` 속성을 사용하여 CloudFormation에서 호스팅 영역을 찾도록 할 수 있습니다. `HostedZoneName` 속성을 사용하며 이름이 동일한 여러 호스팅 영역이 있는 경우 CloudFormation은 스택을 생성하지 않습니다.

### HostedZoneId를 사용하여 RecordSet 추가
<a name="scenario-recordset-using-id"></a>

이 예제는 `HostedZoneId` 속성을 사용하여 호스팅 영역을 지정하는 도메인 이름 `mysite.example.com`에 대한 `SPF` 레코드가 들어 있는 Amazon Route 53 리소스 레코드 세트를 추가합니다.

#### JSON
<a name="quickref-route53-example-1.json"></a>

```
 1. "myDNSRecord" : {
 2.   "Type" : "AWS::Route53::RecordSet",
 3.   "Properties" : 
 4.   {
 5.     "HostedZoneId" : "Z3DG6IL3SJCGPX",
 6.     "Name" : "mysite.example.com.",
 7.     "Type" : "SPF",
 8.     "TTL" : "900",
 9.     "ResourceRecords" : [ "\"v=spf1 ip4:192.168.0.1/16 -all\"" ]
10.   }
11. }
```

#### YAML
<a name="quickref-route53-example-1.yaml"></a>

```
1. myDNSRecord:
2.   Type: AWS::Route53::RecordSet
3.   Properties:
4.     HostedZoneId: Z3DG6IL3SJCGPX
5.     Name: mysite.example.com.
6.     Type: SPF
7.     TTL: '900'
8.     ResourceRecords:
9.     - '"v=spf1 ip4:192.168.0.1/16 -all"'
```

### HostedZoneName를 사용하여 RecordSet 추가
<a name="scenario-recordset-using-name"></a>

이 예제에서는 `HostedZoneName` 속성을 사용하여 호스팅 영역을 지정하는 도메인 이름 "mysite.example.com"에 대한 Amazon Route 53 리소스 레코드 세트를 추가합니다.

#### JSON
<a name="quickref-route53-example-2.json"></a>

```
 1. "myDNSRecord2" : {
 2.             "Type" : "AWS::Route53::RecordSet",
 3.             "Properties" : {
 4.                 "HostedZoneName" : "example.com.",
 5.                 "Name" : "mysite.example.com.",
 6.                 "Type" : "A",
 7.                 "TTL" : "900",
 8.                 "ResourceRecords" : [
 9.                     "192.168.0.1",
10.                     "192.168.0.2"
11.                 ]
12.             }
13.         }
```

#### YAML
<a name="quickref-route53-example-2.yaml"></a>

```
 1. myDNSRecord2:
 2.   Type: AWS::Route53::RecordSet
 3.   Properties:
 4.     HostedZoneName: example.com.
 5.     Name: mysite.example.com.
 6.     Type: A
 7.     TTL: '900'
 8.     ResourceRecords:
 9.     - 192.168.0.1
10.     - 192.168.0.2
```

## RecordSetGroup을 사용하여 가중치 기반 리소스 레코드 세트 설정
<a name="scenario-recordsetgroup-weighted"></a>

이 예제에서는 [AWS::Route53::RecordSetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-route53-recordsetgroup.html)을 사용하여 'example.com'에 대한 2개의 CNAME 레코드를 설정합니다. 호스팅 영역입니다. `RecordSets` 속성에는 "mysite.example.com" DNS 이름의 CNAME 레코드 세트가 들어 있습니다. 각 레코드 세트에는 식별자(`SetIdentifier`)와 가중치(`Weight`)가 포함되어 있습니다. 리소스로 라우팅되는 인터넷 트래픽의 비율은 다음 계산을 기반으로 합니다.
+ `Frontend One`: `140/(140+60)` = `140/200` = 70%
+ `Frontend Two`: `60/(140+60)` = `60/200` = 30%

가중치 기반 리소스 레코드 세트에 대한 자세한 내용을 알아보려면 *Amazon Route 53 개발자 안내서*의 [가중치 기반 라우팅](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-weighted.html)을 참조하세요.

### JSON
<a name="quickref-route53-example-3.json"></a>

```
 1.         "myDNSOne" : {
 2.             "Type" : "AWS::Route53::RecordSetGroup",
 3.             "Properties" : {
 4.                 "HostedZoneName" : "example.com.",
 5.                 "Comment" : "Weighted RR for my frontends.",
 6.                 "RecordSets" : [
 7.                   {
 8.                     "Name" : "mysite.example.com.",
 9.                     "Type" : "CNAME",
10.                     "TTL" : "900",
11.                     "SetIdentifier" : "Frontend One",
12.                     "Weight" : "140",
13.                     "ResourceRecords" : ["example-ec2.amazonaws.com"]
14.                   },
15.                   {
16.                     "Name" : "mysite.example.com.",
17.                     "Type" : "CNAME",
18.                     "TTL" : "900",
19.                     "SetIdentifier" : "Frontend Two",
20.                     "Weight" : "60",
21.                     "ResourceRecords" : ["example-ec2-larger.amazonaws.com"]
22.                   }
23.                   ]
24.             }
25.         }
```

### YAML
<a name="quickref-route53-example-3.yaml"></a>

```
 1. myDNSOne:
 2.   Type: AWS::Route53::RecordSetGroup
 3.   Properties:
 4.     HostedZoneName: example.com.
 5.     Comment: Weighted RR for my frontends.
 6.     RecordSets:
 7.     - Name: mysite.example.com.
 8.       Type: CNAME
 9.       TTL: '900'
10.       SetIdentifier: Frontend One
11.       Weight: '140'
12.       ResourceRecords:
13.       - example-ec2.amazonaws.com
14.     - Name: mysite.example.com.
15.       Type: CNAME
16.       TTL: '900'
17.       SetIdentifier: Frontend Two
18.       Weight: '60'
19.       ResourceRecords:
20.       - example-ec2-larger.amazonaws.com
```

## RecordSetGroup을 사용하여 별칭 리소스 레코드 세트 설정
<a name="scenario-recordsetgroup-zoneapex"></a>

다음 예제에서는 [AWS::Route53::RecordSetGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-route53-recordsetgroup.html)을 사용하여 ELB 버전 1(Classic) 로드 밸런서 및 버전 2(애플리케이션 또는 네트워크) 로드 밸런서로 트래픽을 라우팅하는 `example.com`이라는 별칭 리소스 레코드 세트를 설정합니다. [AliasTarget](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-route53-recordset-aliastarget.html) 속성은 `GetAtt` 내장 함수를 사용하여 `myELB` `LoadBalancer`의 호스팅 영역 ID와 DNS 이름을 지정합니다. `GetAtt`는 트래픽을 버전 1 또는 버전 2 중에서 어떤 로드 밸런서로 라우팅하는지에 따라 `myELB` 리소스의 다른 속성을 검색합니다.
+ 버전 1 로드 밸런서: `CanonicalHostedZoneNameID` 및 `DNSName`
+ 버전 2 로드 밸런서: `CanonicalHostedZoneID` 및 `DNSName`

별칭 리소스 레코드 세트에 대한 자세한 내용을 알아보려면 *Route 53 개발자 안내서*의 [별칭 및 비별칭 레코드 선택](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html)을 참조하세요.

### 버전 1 로드 밸런서용 JSON
<a name="quickref-route53-example-4.json"></a>

```
 1.       "myELB" : {
 2.         "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
 3.         "Properties" : {
 4.             "AvailabilityZones" : [ "us-east-1a" ],
 5.             "Listeners" : [ {
 6.                 "LoadBalancerPort" : "80",
 7.                 "InstancePort" : "80",
 8.                 "Protocol" : "HTTP"
 9.             } ]
10.         }
11.       },
12.       "myDNS" : {
13.         "Type" : "AWS::Route53::RecordSetGroup",
14.         "Properties" : {
15.           "HostedZoneName" : "example.com.",
16.           "Comment" : "Zone apex alias targeted to myELB LoadBalancer.",
17.           "RecordSets" : [
18.             {
19.               "Name" : "example.com.",
20.               "Type" : "A",
21.               "AliasTarget" : {
22.                   "HostedZoneId" : { "Fn::GetAtt" : ["myELB", "CanonicalHostedZoneNameID"] },
23.                   "DNSName" : { "Fn::GetAtt" : ["myELB","DNSName"] }
24.               }
25.             }
26.           ]
27.         }
28.     }
```

### 버전 1 로드 밸런서용 YAML
<a name="quickref-route53-example-4.yaml"></a>

```
 1. myELB:
 2.   Type: AWS::ElasticLoadBalancing::LoadBalancer
 3.   Properties:
 4.     AvailabilityZones:
 5.     - "us-east-1a"
 6.     Listeners:
 7.     - LoadBalancerPort: '80'
 8.       InstancePort: '80'
 9.       Protocol: HTTP
10. myDNS:
11.   Type: AWS::Route53::RecordSetGroup
12.   Properties:
13.     HostedZoneName: example.com.
14.     Comment: Zone apex alias targeted to myELB LoadBalancer.
15.     RecordSets:
16.     - Name: example.com.
17.       Type: A
18.       AliasTarget:
19.         HostedZoneId: !GetAtt 'myELB.CanonicalHostedZoneNameID'
20.         DNSName: !GetAtt 'myELB.DNSName'
```

### 버전 2 로드 밸런서용 JSON
<a name="quickref-route53-example-4-v2.json"></a>

```
 1.       "myELB" : {
 2.         "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
 3.         "Properties" : {
 4.             "Subnets" : [ 
 5.                 {"Ref": "SubnetAZ1"}, 
 6.                 {"Ref" : "SubnetAZ2"}
 7.             ]
 8.         }
 9.       },
10.       "myDNS" : {
11.         "Type" : "AWS::Route53::RecordSetGroup",
12.         "Properties" : {
13.           "HostedZoneName" : "example.com.",
14.           "Comment" : "Zone apex alias targeted to myELB LoadBalancer.",
15.           "RecordSets" : [
16.             {
17.               "Name" : "example.com.",
18.               "Type" : "A",
19.               "AliasTarget" : {
20.                   "HostedZoneId" : { "Fn::GetAtt" : ["myELB", "CanonicalHostedZoneID"] },
21.                   "DNSName" : { "Fn::GetAtt" : ["myELB","DNSName"] }
22.               }
23.             }
24.           ]
25.         }
26.     }
```

### 버전 2 로드 밸런서용 YAML
<a name="quickref-route53-example-4-v2.yaml"></a>

```
 1. myELB:
 2.   Type: AWS::ElasticLoadBalancingV2::LoadBalancer
 3.   Properties:
 4.     Subnets:
 5.     - Ref: SubnetAZ1
 6.     - Ref: SubnetAZ2
 7. myDNS:
 8.   Type: AWS::Route53::RecordSetGroup
 9.   Properties:
10.     HostedZoneName: example.com.
11.     Comment: Zone apex alias targeted to myELB LoadBalancer.
12.     RecordSets:
13.     - Name: example.com.
14.       Type: A
15.       AliasTarget:
16.         HostedZoneId: !GetAtt 'myELB.CanonicalHostedZoneID'
17.         DNSName: !GetAtt 'myELB.DNSName'
```

## CloudFront 배포에 대한 별칭 리소스 레코드 세트
<a name="scenario-user-friendly-url-for-cloudfront-distribution"></a>

다음 예에서는 사용자 지정 도메인 이름을 기존 CloudFront 배포에 매핑하는 별칭 A 레코드를 생성합니다. `myHostedZoneID`는 동일한 템플릿의 실제 `AWS::Route53::HostedZone` 리소스 또는 파라미터에 대한 참조로 간주됩니다. `myCloudFrontDistribution`는 동일한 템플릿 내의 `AWS::CloudFront::Distribution` 리소스를 참조합니다. 별칭 레코드는 표준 CloudFront 호스팅 영역 ID(`Z2FDTNDATAQYW2`)를 사용하며, `Fn::GetAtt`를 사용하여 배포의 도메인 이름을 자동으로 확인합니다. 이 설정을 사용하면 IP 주소 없이 웹 트래픽을 사용자 지정 도메인에서 CloudFront 배포로 라우팅할 수 있습니다.

**참고**  
별칭 리소스 레코드 세트를 생성할 때 `Z2FDTNDATAQYW2` 속성을 `HostedZoneId`로 지정해야 합니다. 프라이빗 영역에서는 CloudFront에 대한 별칭 리소스 레코드 세트를 생성할 수 없습니다.

### JSON
<a name="quickref-route53-example-5.json"></a>

```
 1. {
 2.     "myDNS": {
 3.         "Type": "AWS::Route53::RecordSetGroup",
 4.         "Properties": {
 5.             "HostedZoneId": {
 6.                 "Ref": "myHostedZoneID"
 7.             },
 8.             "RecordSets": [
 9.                 {
10.                     "Name": {
11.                         "Ref": "myRecordSetDomainName"
12.                     },
13.                     "Type": "A",
14.                     "AliasTarget": {
15.                         "HostedZoneId": "Z2FDTNDATAQYW2",
16.                         "DNSName": {
17.                             "Fn::GetAtt": [
18.                                 "myCloudFrontDistribution",
19.                                 "DomainName"
20.                             ]
21.                         },
22.                         "EvaluateTargetHealth": false
23.                     }
24.                 }
25.             ]
26.         }
27.     }
28. }
```

### YAML
<a name="quickref-route53-example-5.yaml"></a>

```
 1. myDNS:
 2.   Type: AWS::Route53::RecordSetGroup
 3.   Properties:
 4.     HostedZoneId: !Ref myHostedZoneID
 5.     RecordSets:
 6.       - Name: !Ref myRecordSetDomainName
 7.         Type: A
 8.         AliasTarget:
 9.           HostedZoneId: Z2FDTNDATAQYW2
10.           DNSName: !GetAtt 
11.             - myCloudFrontDistribution
12.             - DomainName
13.           EvaluateTargetHealth: false
```

# Amazon S3 템플릿 코드 조각
<a name="quickref-s3"></a>

이러한 Amazon S3 샘플 템플릿을 사용하면 CloudFormation에서 Amazon S3 버킷을 쉽게 설명할 수 있습니다. 더 많은 예는 `AWS::S3::Bucket` 리소스의 [예](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-s3-bucket.html#aws-resource-s3-bucket--examples) 섹션을 참조하세요.

**Topics**
+ [기본값을 사용하여 Amazon S3 버킷 생성](#scenario-s3-bucket)
+ [`DeletionPolicy`를 사용하여 웹 사이트 호스팅용 Amazon S3 버킷 생성](#scenario-s3-bucket-website)
+ [사용자 지정 도메인을 사용하여 정적 웹 사이트 생성](#scenario-s3-bucket-website-customdomain)

## 기본값을 사용하여 Amazon S3 버킷 생성
<a name="scenario-s3-bucket"></a>

이 예제에서는 [AWS::S3::Bucket](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-s3-bucket.html)을 사용하여 기본 설정으로 버킷을 생성합니다.

### JSON
<a name="quickref-s3-example-1.json"></a>

```
1. "myS3Bucket" : {
2.       "Type" : "AWS::S3::Bucket"
3.       }
```

### YAML
<a name="quickref-s3-example-1.yaml"></a>

```
1. MyS3Bucket:
2.     Type: AWS::S3::Bucket
```

## `DeletionPolicy`를 사용하여 웹 사이트 호스팅용 Amazon S3 버킷 생성
<a name="scenario-s3-bucket-website"></a>

이 예제에서는 버킷을 웹 사이트로 만들고 퍼블릭 액세스 차단은 비활성화합니다(웹 사이트 호스팅용으로 설정된 버킷에는 퍼블릭 읽기 권한 필요). 이후 퍼블릭 버킷 정책이 버킷에 추가됩니다. 이 버킷 리소스에서 `DeletionPolicy` 속성이 `Retain`으로 설정되었으므로 CloudFormation에서는 스택을 삭제할 때 이 버킷을 삭제하지 않습니다. `Output` 섹션에서는 `Fn::GetAtt`를 사용하여 `S3Bucket` 리소스의 `WebsiteURL` 속성과 `DomainName` 속성을 검색합니다.

**참고**  
다음 예제에서는 퍼블릭 액세스 차단 설정 `BlockPublicPolicy` 및 `RestrictPublicBuckets`가 계정 수준에서 비활성화되었다고 가정합니다.

### JSON
<a name="quickref-s3-example-2.json"></a>

```
 1. {
 2.     "AWSTemplateFormatVersion": "2010-09-09",
 3.     "Resources": {
 4.         "S3Bucket": {
 5.             "Type": "AWS::S3::Bucket",
 6.             "Properties": {
 7.                 "PublicAccessBlockConfiguration": {
 8.                     "BlockPublicAcls": false,
 9.                     "BlockPublicPolicy": false,
10.                     "IgnorePublicAcls": false,
11.                     "RestrictPublicBuckets": false
12.                 },
13.                 "WebsiteConfiguration": {
14.                     "IndexDocument": "index.html",
15.                     "ErrorDocument": "error.html"
16.                 }
17.             },
18.             "DeletionPolicy": "Retain",
19.             "UpdateReplacePolicy": "Retain"
20.         },
21.         "BucketPolicy": {
22.             "Type": "AWS::S3::BucketPolicy",
23.             "Properties": {
24.                 "PolicyDocument": {
25.                     "Id": "MyPolicy",
26.                     "Version": "2012-10-17", 		 	 	 
27.                     "Statement": [
28.                         {
29.                             "Sid": "PublicReadForGetBucketObjects",
30.                             "Effect": "Allow",
31.                             "Principal": "*",
32.                             "Action": "s3:GetObject",
33.                             "Resource": {
34.                                 "Fn::Join": [
35.                                     "",
36.                                     [
37.                                         "arn:aws:s3:::",
38.                                         {
39.                                             "Ref": "S3Bucket"
40.                                         },
41.                                         "/*"
42.                                     ]
43.                                 ]
44.                             }
45.                         }
46.                     ]
47.                 },
48.                 "Bucket": {
49.                     "Ref": "S3Bucket"
50.                 }
51.             }
52.         }
53.     },
54.     "Outputs": {
55.         "WebsiteURL": {
56.             "Value": {
57.                 "Fn::GetAtt": [
58.                     "S3Bucket",
59.                     "WebsiteURL"
60.                 ]
61.             },
62.             "Description": "URL for website hosted on S3"
63.         },
64.         "S3BucketSecureURL": {
65.             "Value": {
66.                 "Fn::Join": [
67.                     "",
68.                     [
69.                         "https://",
70.                         {
71.                             "Fn::GetAtt": [
72.                                 "S3Bucket",
73.                                 "DomainName"
74.                             ]
75.                         }
76.                     ]
77.                 ]
78.             },
79.             "Description": "Name of S3 bucket to hold website content"
80.         }
81.     }
82. }
```

### YAML
<a name="quickref-s3-example-2.yaml"></a>

```
 1. AWSTemplateFormatVersion: 2010-09-09
 2. Resources:
 3.   S3Bucket:
 4.     Type: AWS::S3::Bucket
 5.     Properties:
 6.       PublicAccessBlockConfiguration:
 7.         BlockPublicAcls: false
 8.         BlockPublicPolicy: false
 9.         IgnorePublicAcls: false
10.         RestrictPublicBuckets: false
11.       WebsiteConfiguration:
12.         IndexDocument: index.html
13.         ErrorDocument: error.html
14.     DeletionPolicy: Retain
15.     UpdateReplacePolicy: Retain
16.   BucketPolicy:
17.     Type: AWS::S3::BucketPolicy
18.     Properties:
19.       PolicyDocument:
20.         Id: MyPolicy
21.         Version: 2012-10-17 		 	 	 
22.         Statement:
23.           - Sid: PublicReadForGetBucketObjects
24.             Effect: Allow
25.             Principal: '*'
26.             Action: 's3:GetObject'
27.             Resource: !Join 
28.               - ''
29.               - - 'arn:aws:s3:::'
30.                 - !Ref S3Bucket
31.                 - /*
32.       Bucket: !Ref S3Bucket
33. Outputs:
34.   WebsiteURL:
35.     Value: !GetAtt 
36.       - S3Bucket
37.       - WebsiteURL
38.     Description: URL for website hosted on S3
39.   S3BucketSecureURL:
40.     Value: !Join 
41.       - ''
42.       - - 'https://'
43.         - !GetAtt 
44.           - S3Bucket
45.           - DomainName
46.     Description: Name of S3 bucket to hold website content
```

## 사용자 지정 도메인을 사용하여 정적 웹 사이트 생성
<a name="scenario-s3-bucket-website-customdomain"></a>

등록된 도메인과 함께 Route 53을 사용할 수 있습니다. 다음 샘플에서는 도메인에 대해 Route 53에서 호스팅 영역을 이미 생성했다고 가정합니다. 이 예제는 웹 사이트 호스팅용 버킷 두 개를 생성합니다. 루트 버킷은 콘텐츠를 호스팅하고 다른 버킷은 `www.domainname.com` 요청을 루트 버킷으로 리디렉션합니다. 레코드 세트는 도메인 이름을 Amazon S3 엔드포인트로 매핑합니다.

위 예에 표시된 대로 버킷 정책도 추가해야 합니다.

사용자 지정 도메인 사용에 대한 자세한 내용을 알아보려면 **Amazon Simple Storage Service 사용 설명서의 [자습서: Route 53에 등록된 사용자 지정 도메인을 사용하여 정적 웹 사이트 구성](https://docs.aws.amazon.com/AmazonS3/latest/userguide/website-hosting-custom-domain-walkthrough.html)을 참조하세요.

**참고**  
다음 예제에서는 퍼블릭 액세스 차단 설정 `BlockPublicPolicy` 및 `RestrictPublicBuckets`가 계정 수준에서 비활성화되었다고 가정합니다.

### JSON
<a name="quickref-s3-example-3.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Mappings" : {
        "RegionMap" : {
            "us-east-1" : { "S3hostedzoneID" : "Z3AQBSTGFYJSTF", "websiteendpoint" : "s3-website-us-east-1.amazonaws.com" },
            "us-west-1" : { "S3hostedzoneID" : "Z2F56UZL2M1ACD", "websiteendpoint" : "s3-website-us-west-1.amazonaws.com" },
            "us-west-2" : { "S3hostedzoneID" : "Z3BJ6K6RIION7M", "websiteendpoint" : "s3-website-us-west-2.amazonaws.com" },            
            "eu-west-1" : { "S3hostedzoneID" : "Z1BKCTXD74EZPE", "websiteendpoint" : "s3-website-eu-west-1.amazonaws.com" },
            "ap-southeast-1" : { "S3hostedzoneID" : "Z3O0J2DXBE1FTB", "websiteendpoint" : "s3-website-ap-southeast-1.amazonaws.com" },
            "ap-southeast-2" : { "S3hostedzoneID" : "Z1WCIGYICN2BYD", "websiteendpoint" : "s3-website-ap-southeast-2.amazonaws.com" },
            "ap-northeast-1" : { "S3hostedzoneID" : "Z2M4EHUR26P7ZW", "websiteendpoint" : "s3-website-ap-northeast-1.amazonaws.com" },
            "sa-east-1" : { "S3hostedzoneID" : "Z31GFT0UA1I2HV", "websiteendpoint" : "s3-website-sa-east-1.amazonaws.com" }
        }
    },
    "Parameters": {
        "RootDomainName": {
            "Description": "Domain name for your website (example.com)",
            "Type": "String"
        }
    },
    "Resources": {
        "RootBucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {
                "BucketName" : {"Ref":"RootDomainName"},
                "PublicAccessBlockConfiguration": {
                    "BlockPublicAcls": false,
                    "BlockPublicPolicy": false,
                    "IgnorePublicAcls": false,
                    "RestrictPublicBuckets": false
                },
                "WebsiteConfiguration": {
                    "IndexDocument":"index.html",
                    "ErrorDocument":"404.html"
                }
            }
        },
        "WWWBucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {
                "BucketName": {
                    "Fn::Join": ["", ["www.", {"Ref":"RootDomainName"}]]
                },
                "AccessControl": "BucketOwnerFullControl",
                "WebsiteConfiguration": {
                    "RedirectAllRequestsTo": {
                        "HostName": {"Ref": "RootBucket"}
                    }
                }
            }
        },
        "myDNS": {
            "Type": "AWS::Route53::RecordSetGroup",
            "Properties": {
                "HostedZoneName": {
                    "Fn::Join": ["", [{"Ref": "RootDomainName"}, "."]]
                },
                "Comment": "Zone apex alias.",
                "RecordSets": [
                    {
                        "Name": {"Ref": "RootDomainName"},
                        "Type": "A",
                        "AliasTarget": {
                            "HostedZoneId": {"Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "S3hostedzoneID"]},
                            "DNSName": {"Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "websiteendpoint"]}
                        }
                    },
                    {
                        "Name": {
                            "Fn::Join": ["", ["www.", {"Ref":"RootDomainName"}]]
                        },
                        "Type": "CNAME",
                        "TTL" : "900",
                        "ResourceRecords" : [
                            {"Fn::GetAtt":["WWWBucket", "DomainName"]}
                        ]
                    }
                ]
            }
        }
    },
    "Outputs": {
        "WebsiteURL": {
            "Value": {"Fn::GetAtt": ["RootBucket", "WebsiteURL"]},
            "Description": "URL for website hosted on S3"
        }
    }
}
```

### YAML
<a name="quickref-s3-example-3.yaml"></a>

```
Parameters:
  RootDomainName:
    Description: Domain name for your website (example.com)
    Type: String
Mappings:
  RegionMap:
    us-east-1:
      S3hostedzoneID: Z3AQBSTGFYJSTF
      websiteendpoint: s3-website-us-east-1.amazonaws.com
    us-west-1:
      S3hostedzoneID: Z2F56UZL2M1ACD
      websiteendpoint: s3-website-us-west-1.amazonaws.com
    us-west-2:
      S3hostedzoneID: Z3BJ6K6RIION7M
      websiteendpoint: s3-website-us-west-2.amazonaws.com
    eu-west-1:
      S3hostedzoneID: Z1BKCTXD74EZPE
      websiteendpoint: s3-website-eu-west-1.amazonaws.com
    ap-southeast-1:
      S3hostedzoneID: Z3O0J2DXBE1FTB
      websiteendpoint: s3-website-ap-southeast-1.amazonaws.com
    ap-southeast-2:
      S3hostedzoneID: Z1WCIGYICN2BYD
      websiteendpoint: s3-website-ap-southeast-2.amazonaws.com
    ap-northeast-1:
      S3hostedzoneID: Z2M4EHUR26P7ZW
      websiteendpoint: s3-website-ap-northeast-1.amazonaws.com
    sa-east-1:
      S3hostedzoneID: Z31GFT0UA1I2HV
      websiteendpoint: s3-website-sa-east-1.amazonaws.com
Resources:
  RootBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref RootDomainName
      PublicAccessBlockConfiguration:
        BlockPublicAcls: false
        BlockPublicPolicy: false
        IgnorePublicAcls: false
        RestrictPublicBuckets: false
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: 404.html
  WWWBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub
        - www.${Domain}
        - Domain: !Ref RootDomainName
      AccessControl: BucketOwnerFullControl
      WebsiteConfiguration:
        RedirectAllRequestsTo:
          HostName: !Ref RootBucket
  myDNS:
    Type: AWS::Route53::RecordSetGroup
    Properties:
      HostedZoneName: !Sub 
        - ${Domain}.
        - Domain: !Ref RootDomainName
      Comment: Zone apex alias.
      RecordSets:
        - Name: !Ref RootDomainName
          Type: A
          AliasTarget:
            HostedZoneId: !FindInMap [ RegionMap, !Ref 'AWS::Region', S3hostedzoneID]
            DNSName: !FindInMap [ RegionMap, !Ref 'AWS::Region', websiteendpoint]
        - Name: !Sub
            - www.${Domain}
            - Domain: !Ref RootDomainName
          Type: CNAME
          TTL: 900
          ResourceRecords:
            - !GetAtt WWWBucket.DomainName
Outputs:
  WebsiteURL:
    Value: !GetAtt RootBucket.WebsiteURL
    Description: URL for website hosted on S3
```

# Amazon SNS 템플릿 코드 조각
<a name="quickref-sns"></a>

이 예에서는 Amazon SNS 주제 리소스를 보여줍니다. 여기에는 유효한 이메일 주소가 필요합니다.

## JSON
<a name="quickref-sns-example-1.json"></a>

```
1. "MySNSTopic" : {
2.     "Type" : "AWS::SNS::Topic",
3.     "Properties" : {
4.         "Subscription" : [ {
5.             "Endpoint" : "add valid email address",
6.             "Protocol" : "email"
7.         } ]
8.     }
9. }
```

## YAML
<a name="quickref-sns-example-1.yaml"></a>

```
1. MySNSTopic:
2.   Type: AWS::SNS::Topic
3.   Properties:
4.     Subscription:
5.     - Endpoint: "add valid email address"
6.       Protocol: email
```

# Amazon SQS 템플릿 코드 조각
<a name="scenario-sqs-queue"></a>

이 예제에서는 Amazon SQS 대기열을 보여줍니다.

## JSON
<a name="scenario-sqs-queue-example-1.json"></a>

```
1. "MyQueue" : {
2.     "Type" : "AWS::SQS::Queue",
3.     "Properties" : {
4.         "VisibilityTimeout" : "value"
5.     }
6. }
```

## YAML
<a name="scenario-sqs-queue-example-1.yaml"></a>

```
1. MyQueue:
2.   Type: AWS::SQS::Queue
3.   Properties:
4.     VisibilityTimeout: value
```

# Amazon Timestream 템플릿 코드 조각
<a name="scenario-timestream-queue"></a>

InfluxDB용 Amazon Timestream을 사용하면 애플리케이션 개발자와 DevOps 팀이 오픈 소스 API를 사용하여 AWS에서 실시간 시계열 애플리케이션을 위한 완전관리형 InfluxDB 데이터베이스를 쉽게 실행할 수 있습니다. 까다로운 시계열 워크로드를 처리하는 InfluxDB 데이터베이스를 빠르게 생성할 수 있습니다. 몇 번의 간단한 API 호출로 AWS에서 자동 소프트웨어 패치, 백업 및 복구를 통해 InfluxDB 데이터베이스의 설정, 마이그레이션, 운영 및 확장을 수행할 수 있습니다. GitHub의 [awslabs/amazon-timestream-tools/tree/mainline/integrations/cloudformation/timestream-influxdb](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/integrations/cloudformation/timestream-influxdb)에서도 이러한 샘플을 찾을 수 있습니다.

**Topics**
+ [기본값을 사용하는 최소 샘플](#scenario-timestream-influxdb-example-1)
+ [파라미터가 포함된 보다 완전한 예제](#scenario-timestream-influxdb-example-2)

이러한 CloudFormation 템플릿은 InfluxDB용 Amazon Timestream 인스턴스를 성공적으로 생성, 연결 및 모니터링하는 데 필요한 다음과 같은 리소스를 생성합니다.

**Amazon VPC**
+ `VPC`
+ 하나 이상의 `Subnet`
+ `InternetGateway`
+ `RouteTable`
+ `SecurityGroup`

**Amazon S3**
+ `Bucket`

**Amazon Timestream**
+ `InfluxDBInstance`

## 기본값을 사용하는 최소 샘플
<a name="scenario-timestream-influxdb-example-1"></a>

이 예제에서는 가능한 경우 기본값을 사용하여 다중 AZ 및 퍼블릭 액세스 가능 인스턴스를 배포합니다.

### JSON
<a name="scenario-timestream-influxdb-example-1.json"></a>

```
{
  "Metadata": {
    "AWS::CloudFormation::Interface": {
      "ParameterGroups": [
        {
          "Label": {"default": "Amazon Timestream for InfluxDB Configuration"},
          "Parameters": [
            "DbInstanceName",
            "InfluxDBPassword"
          ]
        }
      ],
      "ParameterLabels": {
        "VPCCIDR": {"default": "VPC CIDR"}
      }
    }
  },
  "Parameters": {
    "DbInstanceName": {
      "Description": "The name that uniquely identifies the DB instance when interacting with the Amazon Timestream for InfluxDB API and CLI commands. This name will also be a prefix included in the endpoint. DB instance names must be unique per customer and per Region.",
      "Type": "String",
      "Default": "mydbinstance",
      "MinLength": 3,
      "MaxLength": 40,
      "AllowedPattern": "^[a-zA-z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$"
    },
    "InfluxDBPassword": {
      "Description": "The password of the initial admin user created in InfluxDB. This password will allow you to access the InfluxDB UI to perform various administrative tasks and also use the InfluxDB CLI to create an operator token. These attributes will be stored in a Secret created in AWS Secrets Manager in your account.",
      "Type": "String",
      "NoEcho": true,
      "MinLength": 8,
      "MaxLength": 64,
      "AllowedPattern": "^[a-zA-Z0-9]+$"
    }
  },
  "Resources": {
    "VPC": {
      "Type": "AWS::EC2::VPC",
      "Properties": {"CidrBlock": "10.0.0.0/16"}
    },
    "InternetGateway": {"Type": "AWS::EC2::InternetGateway"},
    "InternetGatewayAttachment": {
      "Type": "AWS::EC2::VPCGatewayAttachment",
      "Properties": {
        "InternetGatewayId": {"Ref": "InternetGateway"},
        "VpcId": {"Ref": "VPC"}
      }
    },
    "Subnet1": {
      "Type": "AWS::EC2::Subnet",
      "Properties": {
        "VpcId": {"Ref": "VPC"},
        "AvailabilityZone": {
          "Fn::Select": [
            0,
            {"Fn::GetAZs": ""}
          ]
        },
        "CidrBlock": {
          "Fn::Select": [
            0,
            {
              "Fn::Cidr": [
                {
                  "Fn::GetAtt": [
                    "VPC",
                    "CidrBlock"
                  ]
                },
                2,
                12
              ]
            }
          ]
        },
        "MapPublicIpOnLaunch": true
      }
    },
    "Subnet2": {
      "Type": "AWS::EC2::Subnet",
      "Properties": {
        "VpcId": {"Ref": "VPC"},
        "AvailabilityZone": {
          "Fn::Select": [
            1,
            {"Fn::GetAZs": ""}
          ]
        },
        "CidrBlock": {
          "Fn::Select": [
            1,
            {
              "Fn::Cidr": [
                {
                  "Fn::GetAtt": [
                    "VPC",
                    "CidrBlock"
                  ]
                },
                2,
                12
              ]
            }
          ]
        },
        "MapPublicIpOnLaunch": true
      }
    },
    "RouteTable": {
      "Type": "AWS::EC2::RouteTable",
      "Properties": {
        "VpcId": {"Ref": "VPC"}
      }
    },
    "DefaultRoute": {
      "Type": "AWS::EC2::Route",
      "DependsOn": "InternetGatewayAttachment",
      "Properties": {
        "RouteTableId": {"Ref": "RouteTable"},
        "DestinationCidrBlock": "0.0.0.0/0",
        "GatewayId": {"Ref": "InternetGateway"}
      }
    },
    "Subnet1RouteTableAssociation": {
      "Type": "AWS::EC2::SubnetRouteTableAssociation",
      "Properties": {
        "RouteTableId": {"Ref": "RouteTable"},
        "SubnetId": {"Ref": "Subnet1"}
      }
    },
    "Subnet2RouteTableAssociation": {
      "Type": "AWS::EC2::SubnetRouteTableAssociation",
      "Properties": {
        "RouteTableId": {"Ref": "RouteTable"},
        "SubnetId": {"Ref": "Subnet2"}
      }
    },
    "InfluxDBSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupName": "influxdb-sg",
        "GroupDescription": "Security group allowing port 8086 ingress for InfluxDB",
        "VpcId": {"Ref": "VPC"}
      }
    },
    "InfluxDBSecurityGroupIngress": {
      "Type": "AWS::EC2::SecurityGroupIngress",
      "Properties": {
        "GroupId": {"Ref": "InfluxDBSecurityGroup"},
        "IpProtocol": "tcp",
        "CidrIp": "0.0.0.0/0",
        "FromPort": 8086,
        "ToPort": 8086
      }
    },
    "InfluxDBLogsS3Bucket": {
      "Type": "AWS::S3::Bucket",
      "DeletionPolicy": "Retain"
    },
    "InfluxDBLogsS3BucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "InfluxDBLogsS3Bucket"},
        "PolicyDocument": {
          "Version": "2012-10-17",		 	 	 
          "Statement": [
            {
              "Action": "s3:PutObject",
              "Effect": "Allow",
              "Resource": {"Fn::Sub": "arn:aws:s3:::${InfluxDBLogsS3Bucket}/InfluxLogs/*"},
              "Principal": {"Service": "timestream-influxdb.amazonaws.com"}
            },
            {
              "Action": "s3:*",
              "Effect": "Deny",
              "Resource": [
                {"Fn::Sub": "arn:aws:s3:::${InfluxDBLogsS3Bucket}/*"},
                {"Fn::Sub": "arn:aws:s3:::${InfluxDBLogsS3Bucket}"}
              ],
              "Principal": "*",
              "Condition": {
                "Bool": {"aws:SecureTransport": false}
              }
            }
          ]
        }
      }
    },
    "DbInstance": {
      "Type": "AWS::Timestream::InfluxDBInstance",
      "DependsOn": "InfluxDBLogsS3BucketPolicy",
      "Properties": {
        "AllocatedStorage": 20,
        "DbInstanceType": "db.influx.medium",
        "Name": {"Ref": "DbInstanceName"},
        "Password": {"Ref": "InfluxDBPassword"},
        "PubliclyAccessible": true,
        "DeploymentType": "WITH_MULTIAZ_STANDBY",
        "VpcSecurityGroupIds": [
          {"Ref": "InfluxDBSecurityGroup"}
        ],
        "VpcSubnetIds": [
          {"Ref": "Subnet1"},
          {"Ref": "Subnet2"}
        ],
        "LogDeliveryConfiguration": {
          "S3Configuration": {
            "BucketName": {"Ref": "InfluxDBLogsS3Bucket"},
            "Enabled": true
          }
        }
      }
    }
  },
  "Outputs": {
    "VPC": {
      "Description": "A reference to the VPC used to create network resources",
      "Value": {"Ref": "VPC"}
    },
    "Subnets": {
      "Description": "A list of the subnets created",
      "Value": {
        "Fn::Join": [
          ",",
          [
            {"Ref": "Subnet1"},
            {"Ref": "Subnet2"}
          ]
        ]
      }
    },
    "Subnet1": {
      "Description": "A reference to the subnet in the 1st Availability Zone",
      "Value": {"Ref": "Subnet1"}
    },
    "Subnet2": {
      "Description": "A reference to the subnet in the 2nd Availability Zone",
      "Value": {"Ref": "Subnet2"}
    },
    "InfluxDBSecurityGroup": {
      "Description": "Security group with port 8086 ingress rule",
      "Value": {"Ref": "InfluxDBSecurityGroup"}
    },
    "InfluxDBLogsS3Bucket": {
      "Description": "S3 Bucket containing InfluxDB logs from the DB instance",
      "Value": {"Ref": "InfluxDBLogsS3Bucket"}
    },
    "DbInstance": {
      "Description": "A reference to the Timestream for InfluxDB DB instance",
      "Value": {"Ref": "DbInstance"}
    },
    "InfluxAuthParametersSecretArn": {
      "Description": "The Amazon Resource Name (ARN) of the AWS Secrets Manager secret containing the initial InfluxDB authorization parameters. The secret value is a JSON formatted key-value pair holding InfluxDB authorization values: organization, bucket, username, and password.",
      "Value": {
        "Fn::GetAtt": [
          "DbInstance",
          "InfluxAuthParametersSecretArn"
        ]
      }
    },
    "Endpoint": {
      "Description": "The endpoint URL to connect to InfluxDB",
      "Value": {
        "Fn::Join": [
          "",
          [
            "https://",
            {
              "Fn::GetAtt": [
                "DbInstance",
                "Endpoint"
              ]
            },
            ":8086"
          ]
        ]
      }
    }
  }
}
```

### YAML
<a name="scenario-timestream-influxdb-example-1.yaml"></a>

```
Metadata: 
  AWS::CloudFormation::Interface:
    ParameterGroups:
      -
        Label:
          default: "Amazon Timestream for InfluxDB Configuration"
        Parameters:
          - DbInstanceName
          - InfluxDBPassword
    ParameterLabels:
      VPCCIDR:
        default: VPC CIDR

Parameters:
  DbInstanceName:
    Description: The name that uniquely identifies the DB instance when interacting with the Amazon Timestream for InfluxDB API and CLI commands. This name will also be a prefix included in the endpoint. DB instance names must be unique per customer and per Region.
    Type: String
    Default: mydbinstance
    MinLength: 3
    MaxLength: 40
    AllowedPattern: ^[a-zA-z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$
  InfluxDBPassword:
    Description: The password of the initial admin user created in InfluxDB. This password will allow you to access the InfluxDB UI to perform various administrative tasks and also use the InfluxDB CLI to create an operator token. These attributes will be stored in a Secret created in AWS Secrets Manager in your account.
    Type: String
    NoEcho: true
    MinLength: 8
    MaxLength: 64
    AllowedPattern: ^[a-zA-Z0-9]+$

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
  InternetGateway:
    Type: AWS::EC2::InternetGateway
  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC
  Subnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs '']
      CidrBlock: !Select [0, !Cidr [!GetAtt VPC.CidrBlock, 2, 12 ]]
      MapPublicIpOnLaunch: true
  Subnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [1, !GetAZs  '']
      CidrBlock: !Select [1, !Cidr [!GetAtt VPC.CidrBlock, 2, 12 ]]
      MapPublicIpOnLaunch: true
  RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
  DefaultRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
  Subnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref RouteTable
      SubnetId: !Ref Subnet1
  Subnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref RouteTable
      SubnetId: !Ref Subnet2
  InfluxDBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: "influxdb-sg"
      GroupDescription: "Security group allowing port 8086 ingress for InfluxDB"
      VpcId: !Ref VPC
  InfluxDBSecurityGroupIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref InfluxDBSecurityGroup
      IpProtocol: tcp
      CidrIp: 0.0.0.0/0
      FromPort: 8086
      ToPort: 8086
  InfluxDBLogsS3Bucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
  InfluxDBLogsS3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref InfluxDBLogsS3Bucket
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Action: "s3:PutObject"
            Effect: Allow
            Resource: !Sub arn:aws:s3:::${InfluxDBLogsS3Bucket}/InfluxLogs/*
            Principal:
              Service: timestream-influxdb.amazonaws.com
          - Action: "s3:*"
            Effect: Deny
            Resource:
              - !Sub arn:aws:s3:::${InfluxDBLogsS3Bucket}/*
              - !Sub arn:aws:s3:::${InfluxDBLogsS3Bucket}
            Principal: "*"
            Condition:
              Bool:
                aws:SecureTransport: false
  DbInstance:
    Type: AWS::Timestream::InfluxDBInstance
    DependsOn: InfluxDBLogsS3BucketPolicy
    Properties:
      AllocatedStorage: 20
      DbInstanceType: db.influx.medium
      Name: !Ref DbInstanceName
      Password: !Ref InfluxDBPassword
      PubliclyAccessible: true
      DeploymentType: WITH_MULTIAZ_STANDBY
      VpcSecurityGroupIds: 
        - !Ref InfluxDBSecurityGroup
      VpcSubnetIds:
        - !Ref Subnet1
        - !Ref Subnet2
      LogDeliveryConfiguration:
        S3Configuration:
          BucketName: !Ref InfluxDBLogsS3Bucket
          Enabled: true

Outputs:
  # Network Resources
  VPC:
    Description: A reference to the VPC used to create network resources
    Value: !Ref VPC
  Subnets:
    Description: A list of the subnets created
    Value: !Join [",", [!Ref Subnet1, !Ref Subnet2]]
  Subnet1:
    Description: A reference to the subnet in the 1st Availability Zone
    Value: !Ref Subnet1
  Subnet2:
    Description: A reference to the subnet in the 2nd Availability Zone
    Value: !Ref Subnet2
  InfluxDBSecurityGroup:
    Description: Security group with port 8086 ingress rule
    Value: !Ref InfluxDBSecurityGroup

  # Timestream for InfluxDB Resources
  InfluxDBLogsS3Bucket:
    Description: S3 Bucket containing InfluxDB logs from the DB instance
    Value: !Ref InfluxDBLogsS3Bucket
  DbInstance:
    Description: A reference to the Timestream for InfluxDB DB instance
    Value: !Ref DbInstance
  InfluxAuthParametersSecretArn:
    Description: "The Amazon Resource Name (ARN) of the AWS Secrets Manager secret containing the initial InfluxDB authorization parameters. The secret value is a JSON formatted key-value pair holding InfluxDB authorization values: organization, bucket, username, and password."
    Value: !GetAtt DbInstance.InfluxAuthParametersSecretArn
  Endpoint:
    Description: The endpoint URL to connect to InfluxDB
    Value: !Join ["", ["https://", !GetAtt DbInstance.Endpoint, ":8086"]]
```

## 파라미터가 포함된 보다 완전한 예제
<a name="scenario-timestream-influxdb-example-2"></a>

이 예제 템플릿에서는 제공된 파라미터에 따라 네트워크 리소스를 동적으로 변경합니다. 파라미터에는 `PubliclyAccessible` 및 `DeploymentType`이 포함됩니다.

### JSON
<a name="scenario-timestream-influxdb-example-2.json"></a>

```
{
  "Metadata": {
    "AWS::CloudFormation::Interface": {
      "ParameterGroups": [
        {
          "Label": {"default": "Network Configuration"},
          "Parameters": ["VPCCIDR"]
        },
        {
          "Label": {"default": "Amazon Timestream for InfluxDB Configuration"},
          "Parameters": [
            "DbInstanceName",
            "InfluxDBUsername",
            "InfluxDBPassword",
            "InfluxDBOrganization",
            "InfluxDBBucket",
            "DbInstanceType",
            "DbStorageType",
            "AllocatedStorage",
            "PubliclyAccessible",
            "DeploymentType"
          ]
        }
      ],
      "ParameterLabels": {
        "VPCCIDR": {"default": "VPC CIDR"}
      }
    }
  },
  "Parameters": {
    "VPCCIDR": {
      "Description": "Please enter the IP range (CIDR notation) for the new VPC",
      "Type": "String",
      "Default": "10.0.0.0/16"
    },
    "DbInstanceName": {
      "Description": "The name that uniquely identifies the DB instance when interacting with the Amazon Timestream for InfluxDB API and CLI commands. This name will also be a prefix included in the endpoint. DB instance names must be unique per customer and per Region.",
      "Type": "String",
      "Default": "mydbinstance",
      "MinLength": 3,
      "MaxLength": 40,
      "AllowedPattern": "^[a-zA-z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$"
    },
    "InfluxDBUsername": {
      "Description": "The username of the initial admin user created in InfluxDB. Must start with a letter and can't end with a hyphen or contain two consecutive hyphens. For example, my-user1. This username will allow you to access the InfluxDB UI to perform various administrative tasks and also use the InfluxDB CLI to create an operator token. These attributes will be stored in a Secret created in AWS Secrets Manager in your account.",
      "Type": "String",
      "Default": "admin",
      "MinLength": 1,
      "MaxLength": 64
    },
    "InfluxDBPassword": {
      "Description": "The password of the initial admin user created in InfluxDB. This password will allow you to access the InfluxDB UI to perform various administrative tasks and also use the InfluxDB CLI to create an operator token. These attributes will be stored in a Secret created in AWS Secrets Manager in your account.",
      "Type": "String",
      "NoEcho": true,
      "MinLength": 8,
      "MaxLength": 64,
      "AllowedPattern": "^[a-zA-Z0-9]+$"
    },
    "InfluxDBOrganization": {
      "Description": "The name of the initial organization for the initial admin user in InfluxDB. An InfluxDB organization is a workspace for a group of users.",
      "Type": "String",
      "Default": "org",
      "MinLength": 1,
      "MaxLength": 64
    },
    "InfluxDBBucket": {
      "Description": "The name of the initial InfluxDB bucket. All InfluxDB data is stored in a bucket. A bucket combines the concept of a database and a retention period (the duration of time that each data point persists). A bucket belongs to an organization.",
      "Type": "String",
      "Default": "bucket",
      "MinLength": 2,
      "MaxLength": 64,
      "AllowedPattern": "^[^_\\\"][^\\\"]*$"
    },
    "DeploymentType": {
      "Description": "Specifies whether the Timestream for InfluxDB is deployed as Single-AZ or with a MultiAZ Standby for High availability",
      "Type": "String",
      "Default": "WITH_MULTIAZ_STANDBY",
      "AllowedValues": [
        "SINGLE_AZ",
        "WITH_MULTIAZ_STANDBY"
      ]
    },
    "AllocatedStorage": {
      "Description": "The amount of storage to allocate for your DB storage type in GiB (gibibytes).",
      "Type": "Number",
      "Default": 400,
      "MinValue": 20,
      "MaxValue": 16384
    },
    "DbInstanceType": {
      "Description": "The Timestream for InfluxDB DB instance type to run InfluxDB on.",
      "Type": "String",
      "Default": "db.influx.medium",
      "AllowedValues": [
        "db.influx.medium",
        "db.influx.large",
        "db.influx.xlarge",
        "db.influx.2xlarge",
        "db.influx.4xlarge",
        "db.influx.8xlarge",
        "db.influx.12xlarge",
        "db.influx.16xlarge"
      ]
    },
    "DbStorageType": {
      "Description": "The Timestream for InfluxDB DB storage type to read and write InfluxDB data.",
      "Type": "String",
      "Default": "InfluxIOIncludedT1",
      "AllowedValues": [
        "InfluxIOIncludedT1",
        "InfluxIOIncludedT2",
        "InfluxIOIncludedT3"
      ]
    },
    "PubliclyAccessible": {
      "Description": "Configures the DB instance with a public IP to facilitate access.",
      "Type": "String",
      "Default": true,
      "AllowedValues": [
        true,
        false
      ]
    }
  },
  "Conditions": {
    "IsMultiAZ": {
      "Fn::Equals": [
        {"Ref": "DeploymentType"},
        "WITH_MULTIAZ_STANDBY"
      ]
    },
    "IsPublic": {
      "Fn::Equals": [
        {"Ref": "PubliclyAccessible"},
        true
      ]
    }
  },
  "Resources": {
    "VPC": {
      "Type": "AWS::EC2::VPC",
      "Properties": {
        "CidrBlock": {"Ref": "VPCCIDR"}
      }
    },
    "InternetGateway": {
      "Type": "AWS::EC2::InternetGateway",
      "Condition": "IsPublic"
    },
    "InternetGatewayAttachment": {
      "Type": "AWS::EC2::VPCGatewayAttachment",
      "Condition": "IsPublic",
      "Properties": {
        "InternetGatewayId": {"Ref": "InternetGateway"},
        "VpcId": {"Ref": "VPC"}
      }
    },
    "Subnet1": {
      "Type": "AWS::EC2::Subnet",
      "Properties": {
        "VpcId": {"Ref": "VPC"},
        "AvailabilityZone": {
          "Fn::Select": [
            0,
            {"Fn::GetAZs": ""}
          ]
        },
        "CidrBlock": {
          "Fn::Select": [
            0,
            {
              "Fn::Cidr": [
                {
                  "Fn::GetAtt": [
                    "VPC",
                    "CidrBlock"
                  ]
                },
                2,
                12
              ]
            }
          ]
        },
        "MapPublicIpOnLaunch": {
          "Fn::If": [
            "IsPublic",
            true,
            false
          ]
        }
      }
    },
    "Subnet2": {
      "Type": "AWS::EC2::Subnet",
      "Condition": "IsMultiAZ",
      "Properties": {
        "VpcId": {"Ref": "VPC"},
        "AvailabilityZone": {
          "Fn::Select": [
            1,
            {"Fn::GetAZs": ""}
          ]
        },
        "CidrBlock": {
          "Fn::Select": [
            1,
            {
              "Fn::Cidr": [
                {
                  "Fn::GetAtt": [
                    "VPC",
                    "CidrBlock"
                  ]
                },
                2,
                12
              ]
            }
          ]
        },
        "MapPublicIpOnLaunch": {
          "Fn::If": [
            "IsPublic",
            true,
            false
          ]
        }
      }
    },
    "RouteTable": {
      "Type": "AWS::EC2::RouteTable",
      "Properties": {
        "VpcId": {"Ref": "VPC"}
      }
    },
    "DefaultRoute": {
      "Type": "AWS::EC2::Route",
      "Condition": "IsPublic",
      "DependsOn": "InternetGatewayAttachment",
      "Properties": {
        "RouteTableId": {"Ref": "RouteTable"},
        "DestinationCidrBlock": "0.0.0.0/0",
        "GatewayId": {"Ref": "InternetGateway"}
      }
    },
    "Subnet1RouteTableAssociation": {
      "Type": "AWS::EC2::SubnetRouteTableAssociation",
      "Properties": {
        "RouteTableId": {"Ref": "RouteTable"},
        "SubnetId": {"Ref": "Subnet1"}
      }
    },
    "Subnet2RouteTableAssociation": {
      "Type": "AWS::EC2::SubnetRouteTableAssociation",
      "Condition": "IsMultiAZ",
      "Properties": {
        "RouteTableId": {"Ref": "RouteTable"},
        "SubnetId": {"Ref": "Subnet2"}
      }
    },
    "InfluxDBSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupName": "influxdb-sg",
        "GroupDescription": "Security group allowing port 8086 ingress for InfluxDB",
        "VpcId": {"Ref": "VPC"}
      }
    },
    "InfluxDBSecurityGroupIngress": {
      "Type": "AWS::EC2::SecurityGroupIngress",
      "Properties": {
        "GroupId": {"Ref": "InfluxDBSecurityGroup"},
        "IpProtocol": "tcp",
        "CidrIp": "0.0.0.0/0",
        "FromPort": 8086,
        "ToPort": 8086
      }
    },
    "InfluxDBLogsS3Bucket": {
      "Type": "AWS::S3::Bucket",
      "DeletionPolicy": "Retain"
    },
    "InfluxDBLogsS3BucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "InfluxDBLogsS3Bucket"},
        "PolicyDocument": {
          "Version": "2012-10-17",		 	 	 
          "Statement": [
            {
              "Action": "s3:PutObject",
              "Effect": "Allow",
              "Resource": {"Fn::Sub": "arn:aws:s3:::${InfluxDBLogsS3Bucket}/InfluxLogs/*"},
              "Principal": {"Service": "timestream-influxdb.amazonaws.com"}
            },
            {
              "Action": "s3:*",
              "Effect": "Deny",
              "Resource": [
                {"Fn::Sub": "arn:aws:s3:::${InfluxDBLogsS3Bucket}/*"},
                {"Fn::Sub": "arn:aws:s3:::${InfluxDBLogsS3Bucket}"}
              ],
              "Principal": "*",
              "Condition": {
                "Bool": {"aws:SecureTransport": false}
              }
            }
          ]
        }
      }
    },
    "DbInstance": {
      "Type": "AWS::Timestream::InfluxDBInstance",
      "DependsOn": "InfluxDBLogsS3BucketPolicy",
      "Properties": {
        "DbStorageType": {"Ref": "DbStorageType"},
        "AllocatedStorage": {"Ref": "AllocatedStorage"},
        "DbInstanceType": {"Ref": "DbInstanceType"},
        "Name": {"Ref": "DbInstanceName"},
        "Username": {"Ref": "InfluxDBUsername"},
        "Password": {"Ref": "InfluxDBPassword"},
        "Organization": {"Ref": "InfluxDBOrganization"},
        "Bucket": {"Ref": "InfluxDBBucket"},
        "PubliclyAccessible": {
          "Fn::If": [
            "IsPublic",
            true,
            false
          ]
        },
        "DeploymentType": {"Ref": "DeploymentType"},
        "VpcSecurityGroupIds": [
          {"Ref": "InfluxDBSecurityGroup"}
        ],
        "VpcSubnetIds": {
          "Fn::If": [
            "IsMultiAZ",
            [
              {"Ref": "Subnet1"},
              {"Ref": "Subnet2"}
            ],
            [
              {"Ref": "Subnet1"}
            ]
          ]
        },
        "LogDeliveryConfiguration": {
          "S3Configuration": {
            "BucketName": {"Ref": "InfluxDBLogsS3Bucket"},
            "Enabled": true
          }
        }
      }
    }
  },
  "Outputs": {
    "VPC": {
      "Description": "A reference to the VPC used to create network resources",
      "Value": {"Ref": "VPC"}
    },
    "Subnets": {
      "Description": "A list of the subnets created",
      "Value": {
        "Fn::If": [
          "IsMultiAZ",
          {
            "Fn::Join": [
              ",",
              [
                {"Ref": "Subnet1"},
                {"Ref": "Subnet2"}
              ]
            ]
          },
          {"Ref": "Subnet1"}
        ]
      }
    },
    "Subnet1": {
      "Description": "A reference to the subnet in the 1st Availability Zone",
      "Value": {"Ref": "Subnet1"}
    },
    "Subnet2": {
      "Condition": "IsMultiAZ",
      "Description": "A reference to the subnet in the 2nd Availability Zone",
      "Value": {"Ref": "Subnet2"}
    },
    "InfluxDBSecurityGroup": {
      "Description": "Security group with port 8086 ingress rule",
      "Value": {"Ref": "InfluxDBSecurityGroup"}
    },
    "InfluxDBLogsS3Bucket": {
      "Description": "S3 Bucket containing InfluxDB logs from the DB instance",
      "Value": {"Ref": "InfluxDBLogsS3Bucket"}
    },
    "DbInstance": {
      "Description": "A reference to the Timestream for InfluxDB DB instance",
      "Value": {"Ref": "DbInstance"}
    },
    "InfluxAuthParametersSecretArn": {
      "Description": "The Amazon Resource Name (ARN) of the AWS Secrets Manager secret containing the initial InfluxDB authorization parameters. The secret value is a JSON formatted key-value pair holding InfluxDB authorization values: organization, bucket, username, and password.",
      "Value": {
        "Fn::GetAtt": [
          "DbInstance",
          "InfluxAuthParametersSecretArn"
        ]
      }
    },
    "Endpoint": {
      "Description": "The endpoint URL to connect to InfluxDB",
      "Value": {
        "Fn::Join": [
          "",
          [
            "https://",
            {
              "Fn::GetAtt": [
                "DbInstance",
                "Endpoint"
              ]
            },
            ":8086"
          ]
        ]
      }
    }
  }
}
```

### YAML
<a name="scenario-timestream-influxdb-example-2.yaml"></a>

```
Metadata: 
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - 
        Label:
          default: "Network Configuration"
        Parameters:
          - VPCCIDR
      -
        Label:
          default: "Amazon Timestream for InfluxDB Configuration"
        Parameters:
          - DbInstanceName
          - InfluxDBUsername
          - InfluxDBPassword
          - InfluxDBOrganization
          - InfluxDBBucket
          - DbInstanceType
          - DbStorageType
          - AllocatedStorage
          - PubliclyAccessible
          - DeploymentType
    ParameterLabels:
      VPCCIDR:
        default: VPC CIDR

Parameters:
  # Network Configuration
  VPCCIDR:
    Description: Please enter the IP range (CIDR notation) for the new VPC
    Type: String
    Default: 10.0.0.0/16
  # Timestream for InfluxDB Configuration
  DbInstanceName:
    Description: The name that uniquely identifies the DB instance when interacting with the Amazon Timestream for InfluxDB API and CLI commands. This name will also be a prefix included in the endpoint. DB instance names must be unique per customer and per Region.
    Type: String
    Default: mydbinstance
    MinLength: 3
    MaxLength: 40    
    AllowedPattern: ^[a-zA-z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*$
  # InfluxDB initial user configurations
  InfluxDBUsername:
    Description: The username of the initial admin user created in InfluxDB. Must start with a letter and can't end with a hyphen or contain two consecutive hyphens. For example, my-user1. This username will allow you to access the InfluxDB UI to perform various administrative tasks and also use the InfluxDB CLI to create an operator token. These attributes will be stored in a Secret created in AWS Secrets Manager in your account.
    Type: String
    Default: admin
    MinLength: 1
    MaxLength: 64
  InfluxDBPassword:
    Description: The password of the initial admin user created in InfluxDB. This password will allow you to access the InfluxDB UI to perform various administrative tasks and also use the InfluxDB CLI to create an operator token. These attributes will be stored in a Secret created in AWS in your account.
    Type: String
    NoEcho: true
    MinLength: 8
    MaxLength: 64
    AllowedPattern: ^[a-zA-Z0-9]+$
  InfluxDBOrganization:
    Description: The name of the initial organization for the initial admin user in InfluxDB. An InfluxDB organization is a workspace for a group of users.
    Type: String
    Default: org
    MinLength: 1
    MaxLength: 64
  InfluxDBBucket:
    Description: The name of the initial InfluxDB bucket. All InfluxDB data is stored in a bucket. A bucket combines the concept of a database and a retention period (the duration of time that each data point persists). A bucket belongs to an organization.
    Type: String
    Default: bucket
    MinLength: 2
    MaxLength: 64
    AllowedPattern: ^[^_\"][^\"]*$
  DeploymentType:
    Description: Specifies whether the Timestream for InfluxDB is deployed as Single-AZ or with a MultiAZ Standby for High availability
    Type: String
    Default: WITH_MULTIAZ_STANDBY
    AllowedValues:
      - SINGLE_AZ
      - WITH_MULTIAZ_STANDBY
  AllocatedStorage:
    Description: The amount of storage to allocate for your DB storage type in GiB (gibibytes).
    Type: Number
    Default: 400
    MinValue: 20
    MaxValue: 16384
  DbInstanceType:
    Description: The Timestream for InfluxDB DB instance type to run InfluxDB on.
    Type: String
    Default: db.influx.medium
    AllowedValues:
      - db.influx.medium
      - db.influx.large
      - db.influx.xlarge
      - db.influx.2xlarge
      - db.influx.4xlarge
      - db.influx.8xlarge
      - db.influx.12xlarge
      - db.influx.16xlarge
  DbStorageType:
    Description: The Timestream for InfluxDB DB storage type to read and write InfluxDB data.
    Type: String
    Default: InfluxIOIncludedT1
    AllowedValues:
      - InfluxIOIncludedT1
      - InfluxIOIncludedT2
      - InfluxIOIncludedT3
  PubliclyAccessible:
    Description: Configures the DB instance with a public IP to facilitate access.
    Type: String
    Default: true
    AllowedValues:
      - true
      - false

Conditions:
  IsMultiAZ: !Equals [!Ref DeploymentType, WITH_MULTIAZ_STANDBY]
  IsPublic: !Equals [!Ref PubliclyAccessible, true]

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCIDR
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Condition: IsPublic
  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Condition: IsPublic
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC
  Subnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs '']
      CidrBlock: !Select [0, !Cidr [!GetAtt VPC.CidrBlock, 2, 12 ]]
      MapPublicIpOnLaunch: !If [IsPublic, true, false]
  Subnet2:
    Type: AWS::EC2::Subnet
    Condition: IsMultiAZ
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [1, !GetAZs  '']
      CidrBlock: !Select [1, !Cidr [!GetAtt VPC.CidrBlock, 2, 12 ]]
      MapPublicIpOnLaunch: !If [IsPublic, true, false]
  RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
  DefaultRoute:
    Type: AWS::EC2::Route
    Condition: IsPublic
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
  Subnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref RouteTable
      SubnetId: !Ref Subnet1
  Subnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Condition: IsMultiAZ
    Properties:
      RouteTableId: !Ref RouteTable
      SubnetId: !Ref Subnet2
  InfluxDBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: "influxdb-sg"
      GroupDescription: "Security group allowing port 8086 ingress for InfluxDB"
      VpcId: !Ref VPC
  InfluxDBSecurityGroupIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref InfluxDBSecurityGroup
      IpProtocol: tcp
      CidrIp: 0.0.0.0/0
      FromPort: 8086
      ToPort: 8086
  InfluxDBLogsS3Bucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
  InfluxDBLogsS3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref InfluxDBLogsS3Bucket
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Action: "s3:PutObject"
            Effect: Allow
            Resource: !Sub arn:aws:s3:::${InfluxDBLogsS3Bucket}/InfluxLogs/*
            Principal:
              Service: timestream-influxdb.amazonaws.com
          - Action: "s3:*"
            Effect: Deny
            Resource:
              - !Sub arn:aws:s3:::${InfluxDBLogsS3Bucket}/*
              - !Sub arn:aws:s3:::${InfluxDBLogsS3Bucket}
            Principal: "*"
            Condition:
              Bool:
                aws:SecureTransport: false
  DbInstance:
    Type: AWS::Timestream::InfluxDBInstance
    DependsOn: InfluxDBLogsS3BucketPolicy
    Properties:
      DbStorageType: !Ref DbStorageType
      AllocatedStorage: !Ref AllocatedStorage
      DbInstanceType: !Ref DbInstanceType
      Name: !Ref DbInstanceName
      Username: !Ref InfluxDBUsername
      Password: !Ref InfluxDBPassword
      Organization: !Ref InfluxDBOrganization
      Bucket: !Ref InfluxDBBucket
      PubliclyAccessible: !If [IsPublic, true, false]
      DeploymentType: !Ref DeploymentType
      VpcSecurityGroupIds: 
        - !Ref InfluxDBSecurityGroup
      VpcSubnetIds: !If
        - IsMultiAZ
        -
          - !Ref Subnet1
          - !Ref Subnet2
        -
          - !Ref Subnet1
      LogDeliveryConfiguration:
        S3Configuration:
          BucketName: !Ref InfluxDBLogsS3Bucket
          Enabled: true

Outputs:
  # Network Resources
  VPC:
    Description: A reference to the VPC used to create network resources
    Value: !Ref VPC
  Subnets:
    Description: A list of the subnets created
    Value: !If
      - IsMultiAZ
      - !Join [",", [!Ref Subnet1, !Ref Subnet2]]
      - !Ref Subnet1
  Subnet1:
    Description: A reference to the subnet in the 1st Availability Zone
    Value: !Ref Subnet1
  Subnet2:
    Condition: IsMultiAZ
    Description: A reference to the subnet in the 2nd Availability Zone
    Value: !Ref Subnet2
  InfluxDBSecurityGroup:
    Description: Security group with port 8086 ingress rule
    Value: !Ref InfluxDBSecurityGroup

  # Timestream for InfluxDB Resources
  InfluxDBLogsS3Bucket:
    Description: S3 Bucket containing InfluxDB logs from the DB instance
    Value: !Ref InfluxDBLogsS3Bucket
  DbInstance:
    Description: A reference to the Timestream for InfluxDB DB instance
    Value: !Ref DbInstance
  InfluxAuthParametersSecretArn:
    Description: "The Amazon Resource Name (ARN) of the AWS Secrets Manager secret containing the initial InfluxDB authorization parameters. The secret value is a JSON formatted key-value pair holding InfluxDB authorization values: organization, bucket, username, and password."
    Value: !GetAtt DbInstance.InfluxAuthParametersSecretArn
  Endpoint:
    Description: The endpoint URL to connect to InfluxDB
    Value: !Join ["", ["https://", !GetAtt DbInstance.Endpoint, ":8086"]]
```

# CloudFormation을 사용하여 Windows 기반 스택 배포
<a name="cfn-windows-stacks"></a>

이 페이지에서는 Windows 기반 배포에 일반적으로 사용되는 CloudFormation 리소스에 대한 기술 참조 설명서 링크를 제공합니다.

CloudFormation은 Infrastructure as Code (IaC)를 통해 Microsoft Windows 스택을 배포하고 관리할 수 있도록 지원합니다. CloudFormation을 사용하여 Windows 기반 EC2 인스턴스, Amazon RDS의 SQL Server, Directory Service를 통한 Microsoft Active Directory를 자동으로 프로비저닝할 수 있습니다.

AWS는 Amazon EC2에 애플리케이션을 빠르게 배포할 수 있도록 Windows 플랫폼용으로 특별히 설계되어 사전 구성된 Amazon Machine Image(AMI)를 제공합니다. 이러한 AMI에는 기본 Microsoft 설정과 AWS 특정 사용자 지정이 포함됩니다. CloudFormation을 사용하면 다른 Windows Server와 마찬가지로 적절한 AMI를 선택하고, 인스턴스를 시작하고, 원격 데스크톱 연결을 사용하여 액세스할 수 있습니다. AMI에는 최적의 성능과 AWS 서비스와의 호환성을 보장하기 위해 EC2Launch(버전은 Windows Server 에디션에 따라 다름), AWS Systems Manager, CloudFormation, AWS Tools for PowerShell, 다양한 네트워크, 스토리지 및 그래픽 드라이버를 포함한 필수 소프트웨어 구성 요소가 포함되어 있습니다. 자세한 내용은 [AWSWindows AMI 참조](https://docs.aws.amazon.com/ec2/latest/windows-ami-reference/windows-amis.html)를 참조하세요.

CloudFormation은 EC2 인스턴스가 처음 부팅될 때 PowerShell 또는 배치 명령을 실행할 수 있는 `UserData` 스크립트와 같은 소프트웨어 구성 도구도 지원합니다. 또한 헬퍼 스크립트(`cfn-init`, `cfn-signal`, `cfn-get-metadata`, `cfn-hup`)를 제공하며 Windows 인스턴스에서 패키지, 파일, 서비스를 관리하기 위한 `AWS::CloudFormation::Init` 메타데이터를 지원합니다.

엔터프라이즈 환경의 경우 CloudFormation은 도메인 조인, EC2 라이선스 모델을 통한 Windows 라이선스 관리, AWS Secrets Manager를 통한 보안 자격 증명 처리를 지원합니다. CloudFormation은 버전 제어 템플릿 및 반복 가능한 배포와 결합하여 조직이 여러 AWS 리전 및 계정에서 일관되고 안전하며 확장 가능한 Windows 환경을 유지하도록 지원합니다.

Windows 기반 배포에 일반적으로 사용되는 CloudFormation 리소스에 대한 자세한 내용은 다음 기술 참조 주제를 참조하세요.


| 리소스 유형 | 설명 | 
| --- | --- | 
|  [AWS::EC2::Instance](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-instance.html)  |  Windows EC2 인스턴스를 시작하기 위한 리소스입니다.  | 
|  [AWS::EC2::SecurityGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html)  |  Windows 워크로드에 대한 방화벽 규칙을 정의하기 위한 리소스입니다.  | 
|  [AWS::AutoScaling::AutoScalingGroup](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-autoscaling-autoscalinggroup.html) [AWS::EC2::LaunchTemplate](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-launchtemplate.html)  |  Windows EC2 인스턴스 크기를 조정하기 위한 리소스입니다.  | 
|  [AWS::DirectoryService::MicrosoftAD](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-directoryservice-microsoftad.html)  |  Microsoft Active Directory를 배포하기 위한 리소스입니다.  | 
|  [AWS::FSx::FileSystem](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-fsx-filesystem.html)  |  FSx for Windows File Server를 배포하기 위한 리소스입니다.  | 
|  [AWS::RDS::DBInstance](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-rds-dbinstance.html)  |  Amazon RDS에 SQL Server를 프로비저닝하기 위한 리소스입니다.  | 
|  [AWS::CloudFormation::Init](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-init.html)  |  EC2 메타데이터 내에서 인스턴스 구성을 위해 사용되는 리소스입니다. 자세한 내용은 [Windows 기반 CloudFormation 스택 부트스트래핑](cfn-windows-stacks-bootstrapping.md) 섹션을 참조하세요.  | 
|  [AWS::SecretsManager::Secret](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-secretsmanager-secret.html)  |  자격 증명 및 Windows 암호를 안전하게 관리하기 위한 리소스입니다.  | 
|  [AWS::SSM::Parameter](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ssm-parameter.html)  |  구성 값을 안전하게 저장하기 위한 리소스입니다.  | 
|  [AWS::IAM::InstanceProfile](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-instanceprofile.html) [AWS::IAM::Role](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-role.html)  |  EC2 인스턴스에서 실행되는 애플리케이션에 권한을 부여하기 위한 리소스입니다.  | 

# Windows 기반 CloudFormation 스택 부트스트래핑
<a name="cfn-windows-stacks-bootstrapping"></a>

이 주제에서는 Windows 스택을 부트스트랩하고 스택 생성 문제를 해결하는 방법을 설명합니다.

**Topics**
+ [EC2 인스턴스의 사용자 데이터](#cfn-windows-bootstrapping-user-data)
+ [CloudFormation 헬퍼 스크립트](#cfn-windows-bootstrapping-helper-scripts)
+ [Windows 스택 부트스트래핑 예](#cfn-windows-bootstrapping-example)
+ [Windows 파일 경로의 백슬래시 이스케이프 처리](#cfn-windows-stacks-escape-backslashes)
+ [Windows 서비스 관리](#cfn-windows-stacks-manage-windows-services)
+ [스택 생성 문제 해결](#cfn-windows-stacks-troubleshooting)

## EC2 인스턴스의 사용자 데이터
<a name="cfn-windows-bootstrapping-user-data"></a>

사용자 데이터는 Amazon EC2 실행 시에 스크립트 또는 구성 정보를 EC2 인스턴스에 전달할 수 있는 Amazon EC2 기능입니다.

Windows EC2 인스턴스의 경우:
+ 배치 스크립트(`<script>` 태그 사용) 또는 PowerShell 스크립트(`<powershell>` 태그 사용)를 사용할 수 있습니다.
+ 스크립트 실행은 EC2Launch에 의해 처리됩니다.

**중요**  
CloudFormation에서 사용할 자체 Windows AMI를 생성하는 경우 EC2Launch v2가 올바르게 구성되었는지 확인합니다. 스택 생성 중에 CloudFormation 부트스트래핑 도구가 Windows 인스턴스를 올바르게 초기화하고 구성하려면 EC2Launch v2가 필요합니다. 자세한 내용은 *Amazon EC2 사용 설명서*의 [EC2Launch v2 에이전트를 사용하여 EC2 Windows 인스턴스 시작 중 태스크 수행](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2launch-v2.html)을 참조하세요.  
AWS Windows AMI에 대한 자세한 내용은 [AWSWindows AMI 참조](https://docs.aws.amazon.com/ec2/latest/windows-ami-reference/windows-amis.html)를 참조하세요.

## CloudFormation 헬퍼 스크립트
<a name="cfn-windows-bootstrapping-helper-scripts"></a>

헬퍼 스크립트는 부트스트래핑 프로세스 중에 인스턴스를 구성하기 위한 유틸리티로, Amazon EC2 사용자 데이터와 함께 사용되며 강력한 구성 옵션을 제공합니다.

CloudFormation에서는 스택의 일부로 생성한 Amazon EC2 인스턴스에서 소프트웨어를 설치하고 서비스를 시작하는 데 사용할 수 있도록 다음과 같은 Python 헬퍼 스크립트 세트를 제공합니다.
+  `cfn-init` - 리소스 메타데이터를 검색 및 해석하고, 패키지를 설치하고, 파일을 생성하고, 서비스를 시작하는 데 사용됩니다.
+  `cfn-signal` - 필수 리소스나 애플리케이션이 준비될 때 스택에서 다른 리소스를 동기화할 수 있도록 `CreationPolicy`에서 신호를 전송하는 데 사용됩니다.
+  `cfn-get-metadata` - 특정 키에 대한 리소스나 경로의 메타데이터를 검색하는 데 사용됩니다.
+  `cfn-hup` - 메타데이터에 대한 업데이트가 있는지 확인하고 변경 사항이 감지된 경우 사용자 지정 후크를 실행하는 데 사용됩니다.

템플릿에서 직접 헬퍼 스크립트를 호출할 수 있습니다. 헬퍼 스크립트는 동일한 템플릿에서 정의한 리소스 메타데이터와 함께 작동합니다. 헬퍼 스크립트는 스택 생성 과정에서 Amazon EC2 인스턴스에서 실행됩니다.

자세한 내용은 *CloudFormation 템플릿 참조 가이드*의 [CloudFormation 헬퍼 스크립트 참조](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/cfn-helper-scripts-reference.html)를 참조하세요.

## Windows 스택 부트스트래핑 예
<a name="cfn-windows-bootstrapping-example"></a>

다음 작업을 수행하는 Windows Server 서버 템플릿의 예제 코드 조각을 살펴보겠습니다.
+ Windows Server 2022 AMI에서 `TestInstance`라는 EC2 인스턴스를 시작합니다.
+ 간단한 테스트 파일을 생성하여 `cfn-init`가 작동하는지 확인합니다.
+ 지속적인 구성 관리를 위해 `cfn-hup`를 구성합니다.
+ `CreationPolicy`를 사용하여 인스턴스가 성공적인 완료를 알리는지 확인합니다.

`cfn-init` 헬퍼 스크립트는 템플릿에 있는 `AWS::CloudFormation::Init` 리소스의 정보를 기반으로 이러한 각 작업을 수행하는 데 사용됩니다.

`AWS::CloudFormation::Init` 섹션 이름은 `TestInstance`이고 이 섹션은 표준 선언으로 시작합니다.

```
TestInstance:
  Type: AWS::EC2::Instance
  Metadata:
    AWS::CloudFormation::Init:
      configSets:
        default:
          - create_files
          - start_services
```

이후에 `AWS::CloudFormation::Init`의 `files` 섹션이 선언됩니다.

```
      create_files:
        files:
          c:\cfn\test.txt:
            content: !Sub |
              Hello from ${AWS::StackName}
          c:\cfn\cfn-hup.conf:
            content: !Sub |
              [main]
              stack=${AWS::StackName}
              region=${AWS::Region}
              interval=2
          c:\cfn\hooks.d\cfn-auto-reloader.conf:
            content: !Sub |
              [cfn-auto-reloader-hook]
              triggers=post.update
              path=Resources.TestInstance.Metadata.AWS::CloudFormation::Init
              action=cfn-init.exe -v -s ${AWS::StackName} -r TestInstance -c default --region ${AWS::Region}
```

여기서 3개 파일이 생성되어 서버 인스턴스의 `C:\cfn` 디렉터리에 배치됩니다.
+ `test.txt`: `cfn-init`가 올바르게 작동하는지 확인하고 동적 콘텐츠로 파일을 생성할 수 있는 간단한 테스트 파일.
+ `cfn-hup.conf`: 검사 간격이 2분인 `cfn-hup`에 대한 구성 파일.
+ `cfn-auto-reloader.conf` - `AWS::CloudFormation::Init`의 메타데이터가 변경될 때 `cfn-hup`가 업데이트를 시작(`cfn-init` 직접 호출)하는 데 사용되는 후크에 대한 구성 파일입니다.

다음은 Windows 서비스를 구성하는 `start_services` 섹션입니다.

```
      start_services:
        services:
          windows:
            cfn-hup:
              enabled: true
              ensureRunning: true
              files:
                - c:\cfn\cfn-hup.conf
                - c:\cfn\hooks.d\cfn-auto-reloader.conf
```

이 섹션에서는 `cfn-hup` 서비스가 시작되고 구성 파일이 수정되면 자동으로 다시 시작되도록 보장합니다. 서비스는 CloudFormation 메타데이터의 변경 사항을 모니터링하고 업데이트가 감지되면 `cfn-init`를 다시 실행합니다.

다음은 `Properties` 섹션입니다.

```
TestInstance:
  Type: AWS::EC2::Instance
  CreationPolicy:
    ResourceSignal:
      Timeout: PT20M
  Metadata:
    AWS::CloudFormation::Init:
      # ... metadata configuration ...
  Properties:
    InstanceType: t2.large
    ImageId: '{{resolve:ssm:/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-Base}}'
    SecurityGroupIds:
      - !Ref InstanceSecurityGroup
    KeyName: !Ref KeyPairName
    UserData:
      Fn::Base64: !Sub |
        <powershell>
        cfn-init.exe -v -s ${AWS::StackName} -r TestInstance -c default --region ${AWS::Region}
        cfn-signal.exe -e $lastexitcode --stack ${AWS::StackName} --resource TestInstance --region ${AWS::Region}
        </powershell>
```

이 섹션에서 `UserData` 속성에는 EC2Launch에 의해 실행될 PowerShell 스크립트가 `<powershell>` 태그로 둘러싸여 있습니다. 스크립트는 `default` configSet와 함께 `cfn-init`를 실행한 다음 `cfn-signal`을 사용하여 종료 코드를 CloudFormation에 다시 보고합니다. `CreationPolicy`는 스택 생성이 완료된 것으로 간주되기 전에 인스턴스가 올바르게 구성되었는지 확인하는 데 사용됩니다.

`ImageId` 속성은 Systems Manager Parameter Store 퍼블릭 파라미터를 사용하여 최신 Windows Server 2022 AMI ID를 자동으로 검색합니다. 이 접근 방식을 사용하면 리전별 AMI 매핑이 필요하지 않으며 항상 최신 AMI를 얻을 수 있습니다. AMI ID에 대한 Systems Manager 파라미터를 사용하는 것이 최신 AMI 참조를 유지하는 모범 사례입니다. 인스턴스에 연결하려는 경우 `SecurityGroupIds` 속성이 RDP 액세스를 허용하는 보안 그룹을 참조하는지 확인합니다.

`CreationPolicy`는 리소스 속성의 일부로 선언되며 제한 시간을 지정합니다. 인스턴스 구성이 완료되면 사용자 데이터에서 `cfn-signal` 명령이 신호를 보냅니다.

```
TestInstance:
  Type: AWS::EC2::Instance
  CreationPolicy:
    ResourceSignal:
      Timeout: PT20M
  Properties:
    # ... other properties ...
```

부트스트래핑 프로세스는 최소이며 파일을 생성하고 서비스만 시작하기 때문에 `CreationPolicy`는 제한 시간이 초과되기 전에 20분(PT20M)을 기다립니다. 제한 시간은 ISO 8601 지속 시간 형식을 사용하여 지정됩니다. Windows 인스턴스는 Linux 인스턴스보다 일반적으로 시작하는 데 시간이 오래 걸리므로 철저하게 테스트하여 요구 사항에 가장 적합한 제한 시간 값을 결정합니다.

모두 잘 진행되면 `CreationPolicy`가 성공적으로 완료되며 해당 퍼블릭 IP 주소를 사용하여 Windows Server 인스턴스에 액세스할 수 있습니다. 스택 생성이 완료되면 인스턴스 ID 및 퍼블릭 IP 주소가 CloudFormation 콘솔의 **출력** 탭에 표시됩니다.

```
Outputs:
  InstanceId:
    Value: !Ref TestInstance
    Description: Instance ID of the Windows Server
  PublicIP:
    Value: !GetAtt TestInstance.PublicIp
    Description: Public IP address of the Windows Server
```

또한 RDP를 통해 인스턴스에 연결하고 `C:\cfn\test.txt` 파일이 존재하고 예상 콘텐츠를 포함하는지 확인하여 부트스트래핑이 올바르게 작동하는지 수동으로 확인할 수 있습니다. Windows 인스턴스에 연결에 대한 자세한 내용은 *Amazon EC2 사용자 설명서*의 [RDP를 사용하여 Windows 인스턴스에 연결](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connecting_to_windows_instance.html)을 참조하세요.

## Windows 파일 경로의 백슬래시 이스케이프 처리
<a name="cfn-windows-stacks-escape-backslashes"></a>

CloudFormation 템플릿에서 Windows 경로를 참조하는 경우 항상 사용 중인 템플릿 형식에 따라 백슬래시(`\`)를 올바르게 이스케이프해야 합니다.
+ JSON 템플릿의 경우 JSON은 백슬래시를 이스케이프 문자로 취급하므로 Windows 파일 경로에서 이중 백슬래시를 사용해야 합니다. 첫 번째 백슬래시는 두 번째 백슬래시를 이스케이프 처리하므로 단일 리터럴 백슬래시로 해석됩니다.

  ```
  "commands" : {
    "1-extract" : {
      "command" : "C:\\SharePoint\\SharePointFoundation2010.exe /extract:C:\\SharePoint\\SPF2010 /quiet /log:C:\\SharePoint\\SharePointFoundation2010-extract.log"
    }
  }
  ```
+ YAML 템플릿의 경우 일반적으로 단일 백슬래시로 충분합니다.

  ```
  commands:
    1-extract:
      command: C:\SharePoint\SharePointFoundation2010.exe /extract:C:\SharePoint\SPF2010 /quiet /log:C:\SharePoint\SharePointFoundation2010-extract.log
  ```

## Windows 서비스 관리
<a name="cfn-windows-stacks-manage-windows-services"></a>

`sysvinit` 대신 `windows` 키를 사용한다는 점을 제외하면 Linux 서비스와 동일한 방법으로 Windows 서비스를 관리합니다. 다음 예제에서는 `cfn-hup` 서비스를 시작하고 Automatic으로 설정한 다음 `cfn-init`가 `c:\cfn\cfn-hup.conf` 또는 `c:\cfn\hooks.d\cfn-auto-reloader.conf` 구성 파일을 수정하면 서비스를 다시 시작합니다.

```
        services:
          windows:
            cfn-hup:
              enabled: true
              ensureRunning: true
              files:
                - c:\cfn\cfn-hup.conf
                - c:\cfn\hooks.d\cfn-auto-reloader.conf
```

이름(표시 이름 아님)으로 서비스를 참조하여 동일한 방식으로 다른 Windows 서비스를 관리할 수 있습니다.

## 스택 생성 문제 해결
<a name="cfn-windows-stacks-troubleshooting"></a>

생성 중에 스택이 실패할 경우 기본 동작은 실패 시 롤백입니다. 일반적으로 기본 동작은 불필요한 과금을 피할 수 있다는 점은 좋지만 스택 생성이 실패한 원인을 디버깅하기 어렵습니다.

CloudFormation 콘솔을 사용하여 스택을 생성하거나 업데이트할 때 이 동작을 끄려면 **스택 실패 옵션**에서 **성공적으로 프로비저닝된 리소스 보존** 옵션을 선택합니다. 자세한 내용은 [리소스 프로비저닝 시 실패 처리 방법 선택](stack-failure-options.md) 섹션을 참조하세요. 그러면 인스턴스에 로그인한 후 로그 파일을 보고 시작 스크립트를 실행할 때 발생한 문제를 정확히 파악할 수 있습니다.

검토할 중요 로그는 다음과 같습니다.
+ `%ProgramData%\Amazon\EC2Launch\log\agent.log`의 EC2 구성 로그
+ `C:\cfn\log\cfn-init.log`의 **cfn-init** 로그(특정 장애 지점에 대한 종료 코드 및 오류 메시지 확인)

자세한 로그는 *Amazon EC2 사용 설명서*에서 다음 주제를 참조하세요.
+ [EC2Launch 디렉터리 구조](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2config-service.html#UsingConfigXML_WinAMI)
+ [EC2Launch v2 디렉터리 구조](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2launch-v2.html#ec2launch-v2-directory)

부트스트래핑 문제 해결에 대한 자세한 내용은 [Windows 인스턴스의 CloudFormation 스택에서 부트스트랩되지 않는 도우미 스크립트 문제를 해결하려면 어떻게 해야 합니까?](https://repost.aws/knowledge-center/cloudformation-helper-scripts-windows)를 참조하세요.

# CloudFormation에서 제공하는 리소스 유형을 사용하여 템플릿의 기능 확장
<a name="cloudformation-supplied-resource-types"></a>

CloudFormation은 기능을 단순한 스택 템플릿 이상으로 확대할 수 있는 여러 리소스 유형을 제공합니다.

이러한 리소스 유형에는 다음이 포함됩니다.


| 리소스 유형 | 설명 | 설명서 | 
| --- | --- | --- | 
|  사용자 지정 리소스  |  `AWS::CloudFormation::CustomResource` 리소스 유형에서는 특정 프로비저닝 태스크를 수행하거나 CloudFormation 리소스 유형으로 사용할 수 없는 리소스를 포함할 수 있는 사용자 지정 리소스를 생성할 수 있습니다.  |  [사용자 지정 리소스](template-custom-resources.md) | 
|  매크로  |  `AWS::CloudFormation::Macro` 리소스 유형에서는 CloudFormation 템플릿에서 사용자 지정 프로세싱을 수행할 수 있는 재사용 가능한 코드를 정의합니다. 매크로에서는 스택 생성 또는 업데이트 중에 템플릿을 수정하거나, 추가 리소스를 생성하거나, 기타 사용자 지정 작업을 수행할 수 있습니다.  | [템플릿 매크로](template-macros.md) | 
|  중첩 스택  |  `AWS::CloudFormation::Stack` 리소스 유형에서는 보다 모듈화되고 재사용 가능한 스택 아키텍처를 위해 CloudFormation 템플릿 내에 중첩 스택을 생성할 수 있습니다.  | [중첩 스택](using-cfn-nested-stacks.md) | 
|  StackSet  |  `AWS::CloudFormation::StackSet` 리소스 유형에서는 여러 AWS 계정 및 리전에 배포될 수 있는 스택용 컨테이너인 CloudFormation StackSet를 생성하거나 업데이트합니다.  | [StackSets를 사용하여 스택 관리](what-is-cfnstacksets.md) | 
|  대기 조건  |  `AWS::CloudFormation::WaitCondition` 리소스 유형에서는 장기 실행 프로세스의 성공적인 완료 또는 외부 리소스 가용성과 같은 특정 조건이 충족될 때까지 스택 생성 또는 업데이트를 일시 중지합니다.  | [대기 조건](using-cfn-waitcondition.md) | 
|  대기 조건 핸들  |  `AWS::CloudFormation::WaitConditionHandle` 리소스 유형은 `AWS::CloudFormation::WaitCondition` 리소스 유형과 함께 작동합니다. 특정 조건이 충족되었음을 나타내는 신호를 전송하는 데 사용되는 미리 서명된 URL을 제공합니다. 이러한 신호를 통해 스택 생성 또는 업데이트 프로세스를 진행할 수 있습니다.  | [대기 조건](using-cfn-waitcondition.md) | 

# 사용자 지정 리소스를 사용하여 사용자 지정 프로비저닝 로직 생성
<a name="template-custom-resources"></a>

사용자 지정 리소스는 CloudFormation 템플릿에 사용자 지정 프로비저닝 로직을 작성하고 스택을 생성, 업데이트(사용자 지정 리소스를 변경하는 경우) 또는 삭제할 때마다 CloudFormation이 실행되도록 하는 방법을 제공합니다. 이는 프로비저닝 요구 사항이 CloudFormation의 기본 제공 리소스 유형으로 표현할 수 없는 복잡한 로직 또는 워크플로와 관련된 경우 유용할 수 있습니다.

예를 들어 CloudFormation 리소스 유형으로 사용할 수 없는 리소스를 포함하려고 할 수 있습니다. 이러한 리소스는 사용자 지정 리소스를 사용하여 포함할 수 있습니다. 이러한 방식으로 단일 스택에서 관련 리소스를 모두 관리할 수 있습니다.

CloudFormation 템플릿에서 사용자 지정 리소스를 정의하려면 `AWS::CloudFormation::CustomResource` 또는 `Custom::MyCustomResourceTypeName` 리소스 유형을 사용합니다. 사용자 지정 리소스에는 하나의 속성 즉, 서비스 토큰이 필요합니다. 서비스 토큰은 CloudFormation에서 요청을 보내는 위치(예: Amazon SNS 주제 또는 Lambda 함수)를 지정합니다.

다음 주제는 사용자 지정 리소스 사용 방법에 관한 정보를 제공합니다.

**Topics**
+ [사용자 지정 리소스가 작동하는 방식](#how-custom-resources-work)
+ [응답 제한 시간](#response-timeout)
+ [CloudFormation 사용자 지정 리소스 요청 및 응답 참조](crpg-ref.md)
+ [Amazon SNS 지원 사용자 지정 리소스](template-custom-resources-sns.md)
+ [Lambda 지원 사용자 지정 리소스](template-custom-resources-lambda.md)

**참고**  
CloudFormation 레지스트리와 사용자 지정 리소스에는 각각 고유한 이점이 있습니다. 사용자 지정 리소스는 다음과 같은 이점을 제공합니다.  
리소스를 등록할 필요는 없습니다.
등록하지 않고도 전체 리소스를 템플릿의 일부로 포함할 수 있습니다.
`Create`, `Update` 및 `Delete` 작업을 지원합니다.
레지스트리 기반 리소스가 제공하는 이점은 다음과 같습니다.  
서드 파티 애플리케이션 리소스의 모델링, 프로비저닝 및 관리 지원
`Create`, `Read`, `Update`, `Delete` 및 `List`(`CRUDL`) 작업 지원
프라이빗 및 서드 파티 리소스 유형에 대한 드리프트 감지 지원
사용자 지정 리소스와 달리 레지스트리 기반 리소스의 경우 `CRUDL` 작업을 수행하기 위해 Amazon SNS 주제 또는 Lambda 함수를 연결할 필요가 없습니다. 자세한 내용은 [CloudFormation 레지스트리를 통해 익스텐션 관리](registry.md) 섹션을 참조하세요.

## 사용자 지정 리소스가 작동하는 방식
<a name="how-custom-resources-work"></a>

새 사용자 지정 리소스를 설정하는 일반적인 프로세스에는 다음 단계가 포함됩니다. 이러한 단계에는 사용자 지정 리소스를 소유하는 사용자 지정 리소스 공급자와 사용자 지정 리소스 유형이 포함된 템플릿을 생성하는 템플릿 개발자라는 두 가지 역할이 포함됩니다.**** 한 사람이 두 역할을 모두 수행할 수도 있지만, 그렇지 않은 경우 사용자 지정 리소스 공급자와 템플릿 개발자가 협력해야 합니다.

1. 사용자 지정 리소스 공급자는 CloudFormation의 요청을 처리하고 사용자 지정 리소스에서 작업을 수행하는 방법을 결정하는 로직을 작성합니다.

1. 사용자 지정 리소스 공급자는 CloudFormation이 요청을 전송할 수 있는 Amazon SNS 주제 또는 Lambda 함수를 생성합니다. Amazon SNS 주제 또는 Lambda 함수는 스택이 생성될 리전과 동일한 리전에 있어야 합니다.

1. 사용자 지정 리소스 공급자가 템플릿 개발자에게 Amazon SNS 주제 ARN 또는 Lambda 함수 ARN을 제공합니다.

1. 템플릿 개발자는 자신의 CloudFormation 템플릿에서 사용자 지정 리소스를 정의합니다. 여기에는 서비스 토큰 및 모든 입력 데이터 파라미터가 포함됩니다. 서비스 토큰 및 입력 데이터 구조는 사용자 지정 리소스 공급자가 정의합니다. 서비스 토큰은 Amazon SNS 주제 ARN 또는 Lambda 함수 ARN을 지정하며 항상 필요하지만 입력 데이터는 사용자 지정 리소스에 따르는 선택 사항입니다.

이제 사용자가 템플릿을 사용하여 사용자 지정 리소스를 생성, 업데이트 또는 삭제할 때마다 CloudFormation에서 지정된 서비스 토큰에 대한 요청을 보낸 다음 스택 작업을 진행하기 전에 응답을 기다립니다.

다음은 템플릿에서 스택을 생성하는 흐름을 요약한 것입니다.

1. CloudFormation은 지정된 서비스 토큰에 대한 요청을 보냅니다. 이 요청에는 요청 유형, 미리 서명된 Amazon S3 버킷 URL, 사용자 지정 리소스가 응답을 전송하는 위치와 같은 정보가 포함됩니다. 요청에 포함되는 정보에 대한 자세한 내용은 [CloudFormation 사용자 지정 리소스 요청 및 응답 참조](crpg-ref.md) 단원을 참조하십시오.

   다음 샘플 데이터는 CloudFormation에서 `Create` 요청에 포함하는 정보를 보여줍니다. 이 예제에서 `ResourceProperties`는 CloudFormation이 Lambda 함수로 보낼 사용자 지정 페이로드를 생성하도록 합니다.

   ```
   {
      "RequestType" : "Create",
      "RequestId" : "unique id for this create request",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "ResponseURL" : "http://pre-signed-S3-url-for-response",
      "ResourceType" : "Custom::TestResource",
      "LogicalResourceId" : "MyTestResource",
      "ResourceProperties" : {
         "Name" : "Value",
         "List" : [ "1", "2", "3" ]
      }
   }
   ```

1. 사용자 지정 리소스 공급자는 CloudFormation 요청을 처리하고 미리 서명된 URL에 `SUCCESS` 또는 `FAILED`의 응답을 반환합니다. custom resource provider는 JSON 형식 파일로 응답을 제공하고 미리 서명된 S3 URL에 업로드합니다. 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [미리 서명된 URL을 통해 객체 공유](https://docs.aws.amazon.com/AmazonS3/latest/userguide/PresignedUrlUploadObject.html)를 참조하세요.

   또한 custom resource provider는 응답에 template developer가 액세스할 수 있는 이름-값 페어를 포함할 수 있습니다. 예를 들어, 응답에는 요청에 성공한 경우에는 출력 데이터를, 요청에 실패한 경우에는 오류 메시지를 포함할 수 있습니다. 응답에 대한 자세한 내용은 [CloudFormation 사용자 지정 리소스 요청 및 응답 참조](crpg-ref.md) 단원을 참조하십시오.
**중요**  
이름-값 페어에 중요한 정보가 들어 있는 경우 `NoEcho` 필드를 사용하여 사용자 지정 리소스의 출력을 마스킹해야 합니다. 그러지 않으면 속성값(예: `DescribeStackEvents`)을 드러내는 API를 통해 값이 표시될 수 있습니다.  
`NoEcho`를 사용하여 민감한 정보를 마스킹 처리하는 방법에 대한 자세한 내용은 [템플릿에 자격 증명을 포함하지 않음](security-best-practices.md#creds) 모범 사례를 참조하세요.

   custom resource provider는 요청 수신 및 요청에 대한 응답을 담당합니다. 예를 들어 Amazon SNS 알림의 경우 사용자 지정 리소스 공급자는 특정 주제 ARN으로 전송된 알림을 수신하고 해당 알림에 응답해야 합니다. CloudFormation은 미리 서명된 URL 위치에서 응답을 대기해 수신합니다.

   다음 샘플 데이터는 사용자 지정 리소스가 응답에 포함할 수 있는 정보를 보여줍니다.

   ```
   {
      "Status" : "SUCCESS",
      "RequestId" : "unique id for this create request",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "LogicalResourceId" : "MyTestResource",
      "PhysicalResourceId" : "TestResource1",
      "Data" : {
         "OutputName1" : "Value1",
         "OutputName2" : "Value2",
      }
   }
   ```

1. `SUCCESS` 응답을 수신한 후 CloudFormation에서는 스택 작업을 진행합니다. `FAILED` 응답 또는 응답 없음이 반환되면 작업에 실패합니다. 사용자 지정 리소스의 모든 출력 데이터는 미리 서명된 URL 위치에 저장됩니다. 템플릿 개발자는 [Fn::GetAtt](resources-section-structure.md#resource-properties-getatt) 함수를 사용하여 해당 데이터를 검색할 수 있습니다.

**참고**  
AWS PrivateLink를 사용하는 경우 VPC의 사용자 지정 리소스는 CloudFormation 고유의 S3 버킷에 액세스할 수 있어야 합니다. 사용자 지정 리소스는 미리 서명된 Amazon S3 URL로 응답을 전송해야 합니다. Amazon S3에 응답을 보내지 못하면 CloudFormation이 응답을 수신하지 않고 스택 작업이 실패합니다. 자세한 내용은 [인터페이스 엔드포인트를 사용하여 CloudFormation에 액세스(AWS PrivateLink)](vpc-interface-endpoints.md) 섹션을 참조하세요.

## 응답 제한 시간
<a name="response-timeout"></a>

사용자 지정 리소스의 기본 제한 시간은 3600초(1시간)입니다. 이 시간 동안 응답이 수신되지 않으면 스택 작업이 실패합니다.

사용자 지정 리소스의 응답에 소요될 것으로 예상되는 시간에 따라 제한 시간 값을 조정할 수 있습니다. 예를 들어 5분 이내에 응답할 것으로 예상되는 Lambda 함수를 호출하는 사용자 지정 리소스를 프로비저닝하는 경우 `ServiceTimeout` 속성을 지정하여 스택 템플릿에서 시간 제한을 5분으로 설정할 수 있습니다. 자세한 내용은 [CloudFormation 사용자 지정 리소스 요청 및 응답 참조](crpg-ref.md) 섹션을 참조하세요. 이렇게 하면 Lambda 함수에서 오류가 발생하여 중단되는 경우 CloudFormation이 전체 시간 동안 기다리지 않고 5분 후에 스택 작업이 실패합니다.

하지만 시간 제한 값을 너무 작게 설정하지 않도록 주의하세요. 예상치 못한 시간 제한을 피하려면 사용자 지정 리소스에 필요한 작업을 수행하고 응답을 반환할 수 있는 충분한 시간이 있는지 확인하세요.

# CloudFormation 사용자 지정 리소스 요청 및 응답 참조
<a name="crpg-ref"></a>

CloudFormation은 사용자 지정 리소스 공급자와 통신하는 요청-응답 프로토콜을 통해 사용자 지정 리소스를 관리합니다. 각 요청에는 요청 유형(`Create`, `Update` 또는 `Delete`)이 포함되며 이 상위 수준 워크플로를 따릅니다.

1. 템플릿 개발자는 템플릿에서 `ServiceToken` 및 `ServiceTimeout`을 사용하여 사용자 지정 리소스를 정의하고 스택 작업을 시작합니다.

1. CloudFormation은 SNS 또는 Lambda를 통해 사용자 지정 리소스 공급자로 JSON 요청을 보냅니다.

1. 그러면 사용자 지정 리소스 공급자가 요청을 처리하고 제한 시간이 만료되기 전에 미리 서명된 Amazon S3 버킷 URL로 JSON 응답을 반환합니다.

1. CloudFormation은 응답을 읽고 스택 작업을 진행합니다. 제한 시간이 끝날 때까지 응답을 받지 못하면 요청이 실패로 간주되고 스택 작업에 실패합니다.

자세한 내용은 [사용자 지정 리소스가 작동하는 방식](template-custom-resources.md#how-custom-resources-work) 섹션을 참조하세요.

이 섹션에서는 각 요청 유형에 대한 구조, 파라미터 및 예상 응답을 설명합니다.

**참고**  
응답 본문의 총 크기는 4,096바이트를 초과할 수 없습니다.

## 템플릿 설정
<a name="crpg-ref-template-setup"></a>

템플릿에서 사용자 지정 리소스를 정의할 때 템플릿 개발자는 다음 속성과 함께 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html)를 사용합니다.

`ServiceToken`  
스택과 동일한 리전의 Amazon SNS 주제 ARN 또는 Lambda 함수 ARN.  
필수 항목 여부**: 예  
*유형*: 문자열

`ServiceTimeout`  
사용자 지정 리소스 작업의 제한 시간이 초과되기 전 최대 시간(초). 값은 1\$13,600이어야 합니다. 기본값: 3,600초(1시간).  
*필수 항목 여부*: 아니요  
*유형*: 문자열

추가 리소스 속성이 지원됩니다. 리소스 속성은 요청에 `ResourceProperties`로 포함됩니다. 사용자 지정 리소스 공급자가 유효한 속성과 허용 가능한 값을 결정해야 합니다.

## 요청 객체
<a name="crpg-ref-requesttypes"></a>

------
#### [ Create ]

템플릿 개발자가 사용자 지정 리소스를 포함하는 스택을 생성하면 CloudFormation에서 `RequestType`이 `Create`로 설정된 요청을 전송합니다.

생성 요청에는 다음과 같은 필드가 포함됩니다.

`RequestType`  
`Create`.  
필수 항목 여부**: 예  
*유형*: 문자열

`RequestId`  
요청에 대한 고유 ID입니다.  
`StackId`와 `RequestId`를 조합하여 만든 값으로 특정한 사용자 지정 리소스에 대한 요청을 고유하게 식별할 수 있습니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`StackId`  
사용자 지정 리소스가 들어 있는 스택을 나타내는 Amazon 리소스 이름(ARN).  
`StackId`와 `RequestId`를 조합하여 만든 값으로 특정한 사용자 지정 리소스에 대한 요청을 고유하게 식별할 수 있습니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`ResponseURL`  
응답 URL은 사용자 지정 리소스 공급자에서 CloudFormation에 보내는 응답을 수신할 미리 서명된 S3 버킷을 식별합니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`ResourceType`  
CloudFormation 템플릿에서 사용자 지정 리소스의 템플릿 개발자가 선택한 리소스 유형입니다. 사용자 지정 리소스 유형 이름은 최대 60자이고 영숫자 및 다음 문자를 포함할 수 있습니다. `_@-`   
필수 항목 여부**: 예  
*유형*: 문자열

`LogicalResourceId`  
CloudFormation 템플릿에 있는 사용자 지정 리소스의 템플릿 개발자 선택 이름(논리적 ID).  
필수 항목 여부**: 예  
*유형*: 문자열

`ResourceProperties`  
이 필드에는 템플릿 개발자가 보낸 `Properties` 객체의 내용이 들어 있습니다. 해당 콘텐츠는 사용자 지정 리소스 공급자에 의해 정의됩니다.  
*필수 항목 여부*: 아니요  
*유형*: JSON 객체

*예제*

```
{
   "RequestType" : "Create",
   "RequestId" : "unique-request-id",
   "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/id",
   "ResponseURL" : "pre-signed-url-for-create-response",
   "ResourceType" : "Custom::MyCustomResourceType",
   "LogicalResourceId" : "resource-logical-id",
   "ResourceProperties" : {
      "key1" : "string",
      "key2" : [ "list" ],
      "key3" : { "key4" : "map" }
   }
}
```

------
#### [ Update ]

템플릿 개발자가 템플릿 내 사용자 지정 리소스의 속성을 변경하고 스택을 업데이트하면 CloudFormation에서는 `RequestType`이 `Update`로 설정된 요청을 사용자 지정 리소스 공급자에게 전송합니다. 즉, 요청 유형이 `Update`인 경우 사용자 지정 리소스 코드에서 해당 속성이 변경되는 것을 알고 있으므로 변경 사항을 감지할 필요가 없습니다.

업데이트 요청에는 다음과 같은 필드가 포함됩니다.

`RequestType`  
`Update`.  
필수 항목 여부**: 예  
*유형*: 문자열

`RequestId`  
요청에 대한 고유 ID입니다.  
`StackId`와 `RequestId`를 조합하여 만든 값으로 특정한 사용자 지정 리소스에 대한 요청을 고유하게 식별할 수 있습니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`StackId`  
사용자 지정 리소스가 들어 있는 스택을 나타내는 Amazon 리소스 이름(ARN).  
`StackId`와 `RequestId`를 조합하여 만든 값으로 특정한 사용자 지정 리소스에 대한 요청을 고유하게 식별할 수 있습니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`ResponseURL`  
응답 URL은 사용자 지정 리소스 공급자에서 CloudFormation에 보내는 응답을 수신할 미리 서명된 S3 버킷을 식별합니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`ResourceType`  
CloudFormation 템플릿에서 사용자 지정 리소스의 템플릿 개발자가 선택한 리소스 유형입니다. 사용자 지정 리소스 유형 이름은 최대 60자이고 영숫자 및 다음 문자를 포함할 수 있습니다. `_@-` 업데이트 중에는 유형을 변경할 수 없습니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`LogicalResourceId`  
CloudFormation 템플릿에 있는 사용자 지정 리소스의 템플릿 개발자 선택 이름(논리적 ID).  
필수 항목 여부**: 예  
*유형*: 문자열

`PhysicalResourceId`  
사용자 지정 리소스 공급자가 제공하는 물리적 ID(해당 공급자에서 고유함).  
필수 항목 여부**: 예  
*유형*: 문자열

`ResourceProperties`  
이 필드에는 템플릿 개발자가 보낸 `Properties` 객체의 내용이 들어 있습니다. 해당 콘텐츠는 사용자 지정 리소스 공급자에 의해 정의됩니다.  
*필수 항목 여부*: 아니요  
*유형*: JSON 객체

`OldResourceProperties`  
`Update` 요청에만 사용됩니다. CloudFormation 템플릿에서 템플릿 개발자가 이전에 선언한 새 리소스 속성값입니다.  
*필수 항목 여부:* 예  
*유형*: JSON 객체

*예제*

```
{
   "RequestType" : "Update",
   "RequestId" : "unique-request-id",
   "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/id",
   "ResponseURL" : "pre-signed-url-for-update-response",
   "ResourceType" : "Custom::MyCustomResourceType",
   "LogicalResourceId" : "resource-logical-id",
   "PhysicalResourceId" : "provider-defined-physical-id",
   "ResourceProperties" : {
      "key1" : "new-string",
      "key2" : [ "new-list" ],
      "key3" : { "key4" : "new-map" }
   },
   "OldResourceProperties" : {
      "key1" : "string",
      "key2" : [ "list" ],
      "key3" : { "key4" : "map" }
   }
}
```

------
#### [ Delete ]

템플릿 개발자가 스택을 삭제하거나 스택에서 사용자 지정 리소스를 제거하면 CloudFormation에서 `RequestType`이 `Delete`로 설정된 요청을 전송합니다.

삭제 요청에는 다음과 같은 필드가 포함됩니다.

`RequestType`  
`Delete`.  
필수 항목 여부**: 예  
*유형*: 문자열

`RequestId`  
요청에 대한 고유 ID입니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`StackId`  
사용자 지정 리소스가 들어 있는 스택을 나타내는 Amazon 리소스 이름(ARN).  
필수 항목 여부**: 예  
*유형*: 문자열

`ResponseURL`  
응답 URL은 사용자 지정 리소스 공급자에서 CloudFormation에 보내는 응답을 수신할 미리 서명된 S3 버킷을 식별합니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`ResourceType`  
CloudFormation 템플릿에서 사용자 지정 리소스의 템플릿 개발자가 선택한 리소스 유형입니다. 사용자 지정 리소스 유형 이름은 최대 60자이고 영숫자 및 다음 문자를 포함할 수 있습니다. `_@-`   
필수 항목 여부**: 예  
*유형*: 문자열

`LogicalResourceId`  
CloudFormation 템플릿에 있는 사용자 지정 리소스의 템플릿 개발자 선택 이름(논리적 ID).  
필수 항목 여부**: 예  
*유형*: 문자열

`PhysicalResourceId`  
사용자 지정 리소스 공급자가 제공하는 물리적 ID(해당 공급자에서 고유함).  
필수 항목 여부**: 예  
*유형*: 문자열

`ResourceProperties`  
이 필드에는 템플릿 개발자가 보낸 `Properties` 객체의 내용이 들어 있습니다. 해당 콘텐츠는 사용자 지정 리소스 공급자에 의해 정의됩니다.  
*필수 항목 여부*: 아니요  
*유형*: JSON 객체

*예제*

```
{
   "RequestType" : "Delete",
   "RequestId" : "unique-request-id",
   "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/id",
   "ResponseURL" : "pre-signed-url-for-delete-response",
   "ResourceType" : "Custom::MyCustomResourceType",
   "LogicalResourceId" : "resource-logical-id",
   "PhysicalResourceId" : "provider-defined-physical-id",
   "ResourceProperties" : {
      "key1" : "string",
      "key2" : [ "list" ],
      "key3" : { "key4" : "map" }
   }
}
```

------

## 응답 객체
<a name="crpg-ref-responses"></a>

사용자 지정 리소스 공급자는 모든 요청 유형에 대해 미리 서명된 URL로 응답을 전송합니다. 사용자 지정 리소스 공급자가 응답을 전송하지 않으면 CloudFormation은 작업의 제한 시간이 초과될 때까지 기다립니다.

이 응답은 다음 필드를 포함하는 JSON 객체여야 합니다.

`Status`  
`SUCCESS` 또는 `FAILED`여야 합니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`RequestId`  
요청에 대한 고유 ID입니다. 이 값을 요청에 표시된 그대로 복사합니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`StackId`  
사용자 지정 리소스가 들어 있는 스택을 나타내는 Amazon 리소스 이름(ARN). 이 값을 요청에 표시된 그대로 복사합니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`LogicalResourceId`  
CloudFormation 템플릿에 있는 사용자 지정 리소스의 템플릿 개발자 선택 이름(논리적 ID). 이 값을 요청에 표시된 그대로 복사합니다.  
필수 항목 여부**: 예  
*유형*: 문자열

`PhysicalResourceId`  
이 값은 사용자 지정 리소스 공급업체 고유의 ID여야 하며, 크기는 최대 1KB까지 가능합니다. 값은 빈 문자열일 수 없으며, 동일한 리소스의 모든 응답에 대해 동일해야 합니다.  
사용자 지정 리소스를 업데이트할 때 `PhysicalResourceId`에 대해 반환되는 값에 따라 업데이트 동작이 결정됩니다. 값이 동일하게 유지되는 경우 CloudFormation은 이를 일반 업데이트로 간주합니다. 값이 변경되는 경우 CloudFormation은 업데이트를 교체로 이해하고 기존 리소스에 삭제 요청을 전송합니다. 자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html) 섹션을 참조하세요.  
필수 항목 여부**: 예  
*유형*: 문자열

`Reason`  
실패 응답의 이유를 설명합니다.  
`Status`이 `FAILED`인 경우 필수입니다. 그렇지 않은 경우 선택 사항입니다.  
*필수 항목 여부*: 조건부  
*유형*: 문자열

`NoEcho`  
`Fn::GetAtt` 함수를 사용하여 조회할 때 사용자 지정 리소스의 출력을 마스킹할지 여부를 나타냅니다. `true`로 설정하면 *템플릿의 `Metadata` 섹션에 저장된 값을 제외하고* 반환된 모든 값은 별표(\$1\$1\$1\$1\$1)로 마스킹됩니다. CloudFormation은 `Metadata` 섹션에 포함된 정보를 변환, 수정 또는 삭제하지 않습니다. 기본값은 `false`입니다.  
`NoEcho`를 사용하여 민감한 정보를 마스킹 처리하는 방법에 대한 자세한 내용은 [템플릿에 자격 증명을 포함하지 않음](security-best-practices.md#creds) 모범 사례를 참조하세요.  
`Create` 및 `Update` 응답에 대해서만 사용할 수 있습니다. `Delete` 응답에 대해서는 지원되지 않습니다.  
*필수 항목 여부*: 아니요  
*유형*: 부울

`Data`  
응답과 함께 보낼 사용자 지정 리소스 공급자 정의 이름-값 페어. `Fn::GetAtt`와 템플릿의 이름을 사용해 여기 제공된 값에 액세스할 수 있습니다.  
`Create` 및 `Update` 응답에 대해서만 사용할 수 있습니다. `Delete` 응답에 대해서는 지원되지 않습니다.  
이름-값 페어에 중요한 정보가 들어 있는 경우 `NoEcho` 필드를 사용하여 사용자 지정 리소스의 출력을 마스킹해야 합니다. 그러지 않으면 속성값(예: `DescribeStackEvents`)을 드러내는 API를 통해 값이 표시될 수 있습니다.
*필수 항목 여부*: 아니요  
*유형*: JSON 객체

### 성공 응답 예제
<a name="crpg-ref-success-response-examples"></a>

#### `Create` 및 `Update` 응답
<a name="crpg-ref-success-response-example-1"></a>

```
{
   "Status": "SUCCESS",
   "RequestId": "unique-request-id",
   "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/name/id",
   "LogicalResourceId": "resource-logical-id", 
   "PhysicalResourceId": "provider-defined-physical-id",
   "NoEcho": true,
   "Data": {
      "key1": "value1",
      "key2": "value2"
   }
}
```

#### `Delete` 응답
<a name="crpg-ref-success-response-example-2"></a>

```
{
   "Status": "SUCCESS",
   "RequestId": "unique-request-id",
   "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/name/id",
   "LogicalResourceId": "resource-logical-id", 
   "PhysicalResourceId": "provider-defined-physical-id"
}
```

### 실패 응답 예제
<a name="crpg-ref-failed-response-example"></a>

```
{
   "Status": "FAILED",
   "RequestId": "unique-request-id",
   "StackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/name/id",
   "LogicalResourceId": "resource-logical-id",
   "PhysicalResourceId": "provider-defined-physical-id",
   "Reason": "Required failure reason string"
}
```

# Amazon SNS 지원 사용자 지정 리소스
<a name="template-custom-resources-sns"></a>

다음 주제는 CloudFormation이 요청을 보내는 Amazon SNS 주제를 지정하는 서비스 토큰으로 사용자 지정 리소스를 구성하는 방법을 보여줍니다. 또한 사용자 지정 리소스 스택 생성, 업데이트 및 삭제의 결과로 전송 및 수신되는 이벤트 및 메시지 시퀀스를 학습합니다.

사용자 지정 리소스와 Amazon SNS를 사용하면 스택에 새로운 리소스를 추가하고 동적 데이터를 스택에 주입하는 것과 같은 시나리오를 활성화할 수 있습니다. 예를 들어, 스택을 생성할 때 CloudFormation은 Amazon EC2 인스턴스에서 실행 중인 애플리케이션이 모니터링하는 주제에 `Create` 요청을 전송할 수 있습니다. Amazon SNS 알림은 허용 목록에 있는 탄력적 IP 주소의 풀 가져오기와 같은 추가 프로비저닝 태스크를 수행하도록 애플리케이션을 트리거합니다. 완료된 후 애플리케이션은 CloudFormation에 스택 작업을 계속하도록 알리는 응답(및 출력 데이터)을 전송합니다.

Amazon SNS 주제를 사용자 지정 리소스의 대상으로 지정하면 CloudFormation은 사용자 지정 리소스와 연관된 스택 작업 도중 지정된 SNS 주제에 메시지를 전송합니다. 이러한 메시지를 처리하고 필요한 작업을 수행하려면 지원되는 엔드포인트에서 SNS 주제를 구독해야 합니다.

사용자 지정 리소스의 소개와 작동 방식은 [사용자 지정 리소스가 작동하는 방식](template-custom-resources.md#how-custom-resources-work) 섹션을 참조하세요. Amazon SNS와 작동 방식에 대한 자세한 설명은 [Amazon Simple Notification Service 개발자 안내서](https://docs.aws.amazon.com/sns/latest/dg/)를 참조하세요.

## Amazon SNS를 사용하여 사용자 지정 리소스 생성
<a name="walkthrough-custom-resources-sns-adding-nonaws-resource"></a>

**Topics**
+ [1단계: 스택 생성](#crpg-walkthrough-stack-creation)
+ [2단계: 스택 업데이트](#crpg-walkthrough-stack-updates)
+ [3단계: 스택 삭제](#crpg-walkthrough-stack-deletion)

### 1단계: 스택 생성
<a name="crpg-walkthrough-stack-creation"></a>

1. <a name="crpg-walkthrough-stack-creation-customer-template"></a>템플릿 개발자는 사용자 지정 리소스가 포함된 CloudFormation 스택을 생성합니다.

   아래 템플릿 예제에서는 논리적 ID가 `MySeleniumTest`인 사용자 지정 리소스에 대해 사용자 지정 리소스 이름 `Custom::SeleniumTester`를 사용합니다. 사용자 지정 리소스 유형 이름은 영숫자여야 하며 최대 60자 길이일 수 있습니다.

   사용자 지정 리소스 유형은 사용자 지정 리소스 공급자에서 정의되는 서비스 토큰, 선택적 공급자별 속성 및 선택적 [Fn::GetAtt](resources-section-structure.md#resource-properties-getatt) 속성을 사용하여 선언됩니다. 이러한 속성은 template developer에서 custom resource provider로 및 반대로 정보를 전달하는 데 사용할 수 있습니다. 서비스 토큰은 리소스 공급자가 구성한 Amazon SNS 주제를 지정합니다.

   ```
   {
      "AWSTemplateFormatVersion" : "2010-09-09",
      "Resources" : {
         "MySeleniumTest" : {
            "Type": "Custom::SeleniumTester",
            "Version" : "1.0",
            "Properties" : {
               "ServiceToken": "arn:aws:sns:us-west-2:123456789012:CRTest",
               "seleniumTester" : "SeleniumTest()",
               "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com" ],
               "frequencyOfTestsPerHour" : [ "3", "2", "4" ]
            }
         }
      },
      "Outputs" : {
         "topItem" : {
            "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "resultsPage"] }
         },
         "numRespondents" : {
            "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "lastUpdate"] }
         }
      }
   }
   ```
**참고**  
공급자가 CloudFormation에 응답하는 동안 사용자 지정 리소스 공급자는 `Fn::GetAtt`를 사용하여 액세스하는 데이터의 이름과 값을 반환합니다. custom resource provider가 타사인 경우 template developer는 custom resource provider에서 이러한 반환 값의 이름을 얻어야 합니다.

1. <a name="crpg-walkthrough-stack-creation-provider-request"></a>CloudFormation은 스택에 대한 정보, 스택 템플릿의 사용자 지정 리소스 속성 및 응답을 위한 S3 URL이 포함된 `"RequestType" : "Create"`을 사용하여 Amazon SNS 알림을 리소스 공급자에게 전송합니다.

   알림을 전송하는 데 사용되는 SNS 주제는 `ServiceToken` 속성의 템플릿에 포함됩니다. 하드 코딩된 값을 사용하지 않으려면 템플릿 개발자는 스택이 시작되는 시간에 값이 입력되도록 템플릿 파라미터를 사용할 수 있습니다.

   다음 예제에서는 `Create`의 `Custom::SeleniumTester`를 사용하여 생성된 사용자 지정 리소스 유형 이름인 `LogicalResourceId`가 포함되어 있는 사용자 지정 리소스 `MySeleniumTester` 요청을 보여 줍니다.

   ```
   {
      "RequestType" : "Create",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "ResponseURL" : "http://pre-signed-S3-url-for-response",
      "ResourceType" : "Custom::SeleniumTester",
      "LogicalResourceId" : "MySeleniumTester",
      "ResourceProperties" : {
         "seleniumTester" : "SeleniumTest()",
         "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com" ],
         "frequencyOfTestsPerHour" : [ "3", "2", "4" ]
      }
   }
   ```

   `Create` 요청에 대한 요청 객체에 관한 자세한 내용은 [요청 및 응답 참조](crpg-ref.md) 주제를 참조하세요.

1. <a name="crpg-walkthrough-stack-creation-provider-response"></a>custom resource provider는 template developer에서 전송된 데이터를 처리하고 `Create` 요청이 성공적이었는지 여부를 결정합니다. 그런 다음 리소스 공급자는 CloudFormation에서 전송된 S3 URL을 사용하여 `SUCCESS` 또는 `FAILED`의 응답을 전송합니다.

   응답 유형에 따라 다른 응답 필드가 CloudFormation에서 예상됩니다. 특정 요청 유형의 응답 필드에 대한 자세한 내용은 [요청 및 응답 참조](crpg-ref.md) 섹션에서 해당 요청 유형에 대한 설명서를 참조하세요.

   생성 또는 업데이트 요청에 응답하여 사용자 지정 리소스 공급자가 응답의 `Data` 필드에서 데이터 요소를 반환할 수 있습니다. 이러한 요소는 이름/값 페어이며, *이름*은 스택 템플릿에서 사용자 지정 리소스와 함께 사용된 `Fn::GetAtt` 속성에 해당합니다. *값*은 템플릿 개발자가 속성 이름을 사용하여 리소스에서 `Fn::GetAtt`를 호출할 때 반환되는 데이터입니다.

   다음은 사용자 지정 리소스 응답의 예입니다.

   ```
   {
      "Status" : "SUCCESS",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "LogicalResourceId" : "MySeleniumTester",
      "PhysicalResourceId" : "Tester1",
      "Data" : {
         "resultsPage" : "http://www.myexampledomain/test-results/guid",
         "lastUpdate" : "2012-11-14T03:30Z"
      }
   }
   ```

   `Create` 요청에 대한 응답 객체에 관한 자세한 내용은 [요청 및 응답 참조](crpg-ref.md) 주제를 참조하세요.

   요청의 `StackId`, `RequestId` 및 `LogicalResourceId` 필드를 정확히 복사해야 합니다.

1. <a name="crpg-walkthrough-stack-creation-stack-status"></a> CloudFormation은 스택 상태를 `CREATE_COMPLETE` 또는 `CREATE_FAILED`로 선언합니다. 스택이 성공적으로 생성된 경우 템플릿 개발자는 [Fn::GetAtt](resources-section-structure.md#resource-properties-getatt)를 통해 생성된 사용자 지정 리소스의 출력값에 액세스하여 해당 값을 사용할 수 있습니다.

   예를 들어, 그림에 사용된 사용자 지정 리소스 템플릿은 `Fn::GetAtt`를 사용하여 리소스 출력을 스택 출력에 복사했습니다.

   ```
   "Outputs" : {
      "topItem" : {
         "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "resultsPage"] }
      },
      "numRespondents" : {
         "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "lastUpdate"] }
      }
   }
   ```

### 2단계: 스택 업데이트
<a name="crpg-walkthrough-stack-updates"></a>

기존 스택을 업데이트하려면 아래 예제와 같이 스택에서 리소스의 속성에 대한 업데이트를 지정하는 템플릿을 제출해야 합니다. CloudFormation은 템플릿에 지정된 변경 사항이 있는 리소스만 업데이트합니다. 자세한 내용은 [스택 리소스의 업데이트 동작 이해](using-cfn-updating-stacks-update-behaviors.md) 섹션을 참조하세요.

기본 물리적 리소스를 교체해야 하는 사용자 지정 리소스를 업데이트할 수 있습니다. CloudFormation 템플릿에서 사용자 지정 리소스를 업데이트할 경우 CloudFormation은 해당 사용자 지정 리소스에 업데이트 요청을 전송합니다. 사용자 지정 리소스에 교체가 필요한 경우, 새 사용자 지정 리소스는 새 물리적 ID로 응답을 전송해야 합니다. 응답을 수신한 CloudFormation은 기존 및 신규 사용자 지정 리소스의 `PhysicalResourceId`를 비교합니다. [3단계: 스택 삭제](#crpg-walkthrough-stack-deletion)에서 설명한 바와 같이, 두 값이 다른 경우 CloudFormation은 업데이트를 교체로 인식하고 기존 리소스에 삭제 요청을 전송합니다.

**참고**  
사용자 지정 리소스에 변경 사항을 적용하지 않으면 CloudFormation은 스택 업데이트 중 해당 리소스에 요청을 전송하지 않습니다.

1. <a name="crpg-walkthrough-stack-updates-customer-template"></a>template developer는 사용자 지정 리소스가 포함된 스택에 대한 업데이트를 시작합니다. 업데이트 중 template developer는 스택 템플릿에서 새로운 속성을 지정할 수 있습니다.

   다음은 사용자 지정 리소스 유형을 사용하는 스택 템플릿에 대한 `Update`의 예입니다.

   ```
   {
      "AWSTemplateFormatVersion" : "2010-09-09",
      "Resources" : {
         "MySeleniumTest" : {
            "Type": "Custom::SeleniumTester",
            "Version" : "1.0",
            "Properties" : {
               "ServiceToken": "arn:aws:sns:us-west-2:123456789012:CRTest",
               "seleniumTester" : "SeleniumTest()",
               "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com",
                  "http://mynewsite.com" ],
               "frequencyOfTestsPerHour" : [ "3", "2", "4", "3" ]
            }
         }
      },
      "Outputs" : {
         "topItem" : {
            "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "resultsPage"] }
         },
         "numRespondents" : {
            "Value" : { "Fn::GetAtt" : ["MySeleniumTest", "lastUpdate"] }
         }
      }
   }
   ```

1. <a name="crpg-walkthrough-stack-updates-provider-request"></a>CloudFormation은 `OldResourceProperties` 필드에 기존 리소스 속성이 포함되고 ResourceProperties에 업데이트된(있는 경우) 리소스 속성이 포함된다는 점을 제외하고 `Create` 호출과 비슷한 정보가 포함되는 `"RequestType" : "Update"`를 사용하여 Amazon SNS 알림을 리소스 공급자에게 전송합니다.

   다음은 `Update` 요청의 예입니다.

   ```
   {
      "RequestType" : "Update",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "ResponseURL" : "http://pre-signed-S3-url-for-response",
      "ResourceType" : "Custom::SeleniumTester",
      "LogicalResourceId" : "MySeleniumTester",
      "PhysicalResourceId" : "Tester1",
      "ResourceProperties" : {
         "seleniumTester" : "SeleniumTest()",
         "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com",
            "http://mynewsite.com" ],
         "frequencyOfTestsPerHour" : [ "3", "2", "4", "3" ]
      },
      "OldResourceProperties" : {
         "seleniumTester" : "SeleniumTest()",
         "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com" ],
         "frequencyOfTestsPerHour" : [ "3", "2", "4" ]
      }
   }
   ```

   `Update` 요청에 대한 요청 객체에 관한 자세한 내용은 [요청 및 응답 참조](crpg-ref.md) 주제를 참조하세요.

1. <a name="crpg-walkthrough-stack-updates-provider-response"></a>사용자 지정 리소스 공급자는 CloudFormation에서 전송된 데이터를 처리합니다. 사용자 지정 리소스는 업데이트를 수행하고 `SUCCESS` 또는 `FAILED`의 응답을 S3 URL에 전송합니다. 그런 다음 CloudFormation은 기존 및 신규 사용자 지정 리소스의 `PhysicalResourceIDs`를 비교합니다. 값이 다른 경우 CloudFormation은 업데이트에 교체가 필요하다고 인식하고 기존 리소스에 삭제 요청을 전송합니다. 다음 예제에서는 `Update` 요청에 대한 custom resource provider 응답을 보여줍니다.

   ```
   {
      "Status" : "SUCCESS",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "LogicalResourceId" : "MySeleniumTester",
      "PhysicalResourceId" : "Tester2"
   }
   ```

   `Update` 요청에 대한 응답 객체에 관한 자세한 내용은 [요청 및 응답 참조](crpg-ref.md) 주제를 참조하세요.

   요청의 `StackId`, `RequestId` 및 `LogicalResourceId` 필드를 정확히 복사해야 합니다.

1. <a name="crpg-walkthrough-stack-updates-stack-status"></a>CloudFormation은 스택 상태를 `UPDATE_COMPLETE` 또는 `UPDATE_FAILED`로 선언합니다. 업데이트가 실패하면 스택은 롤백합니다. 스택이 성공적으로 업데이트된 경우 template developer는 `Fn::GetAtt`를 사용하여 생성된 사용자 지정 리소스의 새로운 출력값에 액세스할 수 있습니다.

### 3단계: 스택 삭제
<a name="crpg-walkthrough-stack-deletion"></a>

1. <a name="crpg-walkthrough-stack-deletion-customer-template"></a>템플릿 개발자는 사용자 지정 리소스가 포함된 스택을 삭제합니다. CloudFormation은 SNS 주제와 함께 스택 템플릿에 지정된 현재 속성을 가져오고, 사용자 지정 리소스 공급자에게 요청하기 위해 준비합니다.

1. <a name="crpg-walkthrough-stack-deletion-provider-request"></a>CloudFormation은 스택에 대한 정보, 스택 템플릿의 사용자 지정 리소스 속성 및 응답을 위한 S3 URL이 포함된 `"RequestType" : "Delete"`을 사용하여 Amazon SNS 알림을 리소스 공급자에게 전송합니다.

   스택을 삭제하거나 사용자 지정 리소스를 제거하거나 교체하는 업데이트를 수행할 때마다 CloudFormation은 기존 및 신규 사용자 지정 리소스 간에 `PhysicalResourceId`를 비교합니다. 값이 다른 경우 다음 `Delete` 요청 예제와 같이 CloudFormation은 업데이트를 교체로 인식하고 기존 리소스(`OldPhysicalResource`)에 대한 삭제 요청을 전송합니다.

   ```
   {
      "RequestType" : "Delete",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "ResponseURL" : "http://pre-signed-S3-url-for-response",
      "ResourceType" : "Custom::SeleniumTester",
      "LogicalResourceId" : "MySeleniumTester",
      "PhysicalResourceId" : "Tester1",
      "ResourceProperties" : {
         "seleniumTester" : "SeleniumTest()",
         "endpoints" : [ "http://mysite.com", "http://myecommercesite.com/", "http://search.mysite.com",
            "http://mynewsite.com" ],
         "frequencyOfTestsPerHour" : [ "3", "2", "4", "3" ]
      }
   }
   ```

   `Delete` 요청에 대한 요청 객체에 관한 자세한 내용은 [요청 및 응답 참조](crpg-ref.md) 주제를 참조하세요.

   `DescribeStackResource`, `DescribeStackResources` 및 `ListStackResources`는 지정된 경우 사용자 정의 이름을 표시합니다.

1. <a name="crpg-walkthrough-stack-deletion-provider-response"></a>사용자 지정 리소스 공급자는 CloudFormation에서 전송된 데이터를 처리하고 `Delete` 요청이 성공적이었는지 여부를 결정합니다. 그런 다음 리소스 공급자는 CloudFormation에서 전송된 S3 URL을 사용하여 `SUCCESS` 또는 `FAILED`의 응답을 전송합니다. 사용자 지정 리소스가 포함된 스택을 성공적으로 삭제하려면 custom resource provider에서 삭제 요청에 성공적으로 응답해야 합니다.

   다음은 `Delete` 요청에 대한 custom resource provider 응답의 예입니다.

   ```
   {
      "Status" : "SUCCESS",
      "RequestId" : "unique-request-id",
      "StackId" : "arn:aws:cloudformation:us-west-2:123456789012:stack/mystack/5b918d10-cd98-11ea-90d5-0a9cd3354c10",
      "LogicalResourceId" : "MySeleniumTester",
      "PhysicalResourceId" : "Tester1"
   }
   ```

   `Delete` 요청에 대한 응답 객체에 관한 자세한 내용은 [요청 및 응답 참조](crpg-ref.md) 주제를 참조하세요.

   요청의 `StackId`, `RequestId` 및 `LogicalResourceId` 필드를 정확히 복사해야 합니다.

1. <a name="crpg-walkthrough-stack-updates-stack-status-delete"></a>CloudFormation은 스택 상태를 `DELETE_COMPLETE` 또는 `DELETE_FAILED`로 선언합니다.

# Lambda 지원 사용자 지정 리소스
<a name="template-custom-resources-lambda"></a>

Lambda 함수를 사용자 지정 리소스와 연결하면 해당 사용자 지정 리소스가 생성, 업데이트 또는 삭제될 때마다 이 함수가 호출됩니다. CloudFormation은 Lambda API를 호출해 이러한 함수를 호출하고 모든 요청 데이터(예: 요청 유형 및 리소스 속성)를 이 함수로 전달합니다. CloudFormation과 함께 Lambda 함수의 이점 및 사용자 지정 가능성 덕분에 스택 생성 중 동적으로 AMI ID 조회 또는 유틸리티 함수(예: 문자열 반전 함수) 구현 및 사용과 같은 광범위한 시나리오를 처리할 수 있습니다.

사용자 지정 리소스의 소개와 작동 방식은 [사용자 지정 리소스가 작동하는 방식](template-custom-resources.md#how-custom-resources-work) 섹션을 참조하세요.

**Topics**
+ [연습: Lambda 지원 사용자 지정 리소스를 사용하여 지연 메커니즘 생성](walkthrough-lambda-backed-custom-resources.md)
+ [`cfn-response` 모듈](cfn-lambda-function-code-cfnresponsemodule.md)

# 연습: Lambda 지원 사용자 지정 리소스를 사용하여 지연 메커니즘 생성
<a name="walkthrough-lambda-backed-custom-resources"></a>

이 연습에서는 샘플 CloudFormation 템플릿을 사용하여 Lambda 지원 사용자 지정 리소스를 구성하고 시작하는 방법을 보여줍니다. 이 템플릿은 지정된 시간 동안 스택 배포를 일시 중지하는 지연 메커니즘을 생성합니다. 이는 종속 리소스가 생성되기 전에 리소스가 안정화될 때까지 기다리는 경우와 같이 리소스 프로비저닝 중에 의도적으로 지연시켜야 하는 경우에 유용할 수 있습니다.

**참고**  
이전에는 AMI ID를 검색하는 데 Lambda 지원 사용자 지정 리소스가 권장되었지만 이제 AWS Systems Manager 파라미터를 사용하는 것이 좋습니다. 이러한 접근 방식을 통해 더 쉽게 템플릿을 재사용하고 유지 관리할 수 있습니다. 자세한 내용은 [Systems Manager Parameter Store에서 일반 텍스트 값 가져오기](dynamic-references-ssm.md) 섹션을 참조하세요.

**Topics**
+ [개요](#walkthrough-lambda-backed-custom-resources-overview)
+ [샘플 템플릿](#walkthrough-lambda-backed-custom-resources-sample-template)
+ [샘플 템플릿 연습](#walkthrough-lambda-backed-custom-resources-sample-template-walkthrough)
+ [사전 조건](#walkthrough-lambda-backed-custom-resources-prerequisites)
+ [스택 시작](#walkthrough-lambda-backed-custom-resources-createfunction-createstack)
+ [리소스 정리](#walkthrough-lambda-backed-custom-resources-createfunction-cleanup)
+ [관련 정보](#w2aac11c45b9c24b9c23)

## 개요
<a name="walkthrough-lambda-backed-custom-resources-overview"></a>

이 연습에서 사용된 샘플 스택 템플릿은 Lambda 지원 사용자 지정 리소스를 생성합니다. 이 사용자 지정 리소스는 스택 생성 중에 구성 가능한 지연(기본값 60초)을 도입합니다. 지연은 사용자 지정 리소스의 속성이 수정되는 경우에만 스택 업데이트 중에 발생합니다.

템플릿은 다음 리소스를 프로비저닝합니다.
+ 사용자 지정 리소스,
+ Lambda 함수, 및
+ Lambda가 CloudWatch에 로그를 작성할 수 있도록 하는 IAM 역할.

이는 또한 다음 두 가지 출력도 정의합니다.
+ 함수가 대기한 실제 시간입니다.
+ Lambda 함수의 각 실행 동안 생성되는 고유 식별자입니다.



**참고**  
CloudFormation은 무료 서비스이지만 Lambda는 함수에 대한 요청 수 및 코드 실행 시간에 따라 요금을 부과합니다. Lambda 요금에 대한 자세한 내용은 [AWS Lambda 요금](https://aws.amazon.com/lambda/pricing/)을 참조하세요.

## 샘플 템플릿
<a name="walkthrough-lambda-backed-custom-resources-sample-template"></a>

아래 지연 메커니즘을 사용하여 Lambda 지원 사용자 지정 리소스 샘플 템플릿을 확인할 수 있습니다.

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-json"></a>

```
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "LambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [{
            "Effect": "Allow",
            "Principal": { "Service": ["lambda.amazonaws.com"] },
            "Action": ["sts:AssumeRole"]
          }]
        },
        "Path": "/",
        "Policies": [{
          "PolicyName": "AllowLogs",
          "PolicyDocument": {
            "Statement": [{
              "Effect": "Allow",
              "Action": ["logs:*"],
              "Resource": "*"
            }]
          }
        }]
      }
    },
    "CFNWaiter": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Handler": "index.handler",
        "Runtime": "python3.9",
        "Timeout": 900,
        "Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn"] },
        "Code": {
          "ZipFile": { "Fn::Join": ["\n", [
            "from time import sleep",
            "import json",
            "import cfnresponse",
            "import uuid",
            "",
            "def handler(event, context):",
            "  wait_seconds = 0",
            "  id = str(uuid.uuid1())",
            "  if event[\"RequestType\"] in [\"Create\", \"Update\"]:",
            "    wait_seconds = int(event[\"ResourceProperties\"].get(\"ServiceTimeout\", 0))",
            "    sleep(wait_seconds)",
            "  response = {",
            "    \"TimeWaited\": wait_seconds,",
            "    \"Id\": id ",
            "  }",
            "  cfnresponse.send(event, context, cfnresponse.SUCCESS, response, \"Waiter-\"+id)"
          ]]}
        }
      }
    },
    "CFNWaiterCustomResource": {
      "Type": "AWS::CloudFormation::CustomResource",
      "Properties": {
        "ServiceToken": { "Fn::GetAtt": ["CFNWaiter", "Arn"] },
        "ServiceTimeout": 60
      }
    }
  },
  "Outputs": {
    "TimeWaited": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "TimeWaited"] },
      "Export": { "Name": "TimeWaited" }
    },
    "WaiterId": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "Id"] },
      "Export": { "Name": "WaiterId" }
    }
  }
}
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-yaml"></a>

```
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      Policies:
        - PolicyName: "AllowLogs"
          PolicyDocument:
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:*"
                Resource: "*"
  CFNWaiter:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Runtime: python3.9 
      Timeout: 900
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile:
          !Sub |
          from time import sleep
          import json
          import cfnresponse
          import uuid
​
          def handler(event, context):
            wait_seconds = 0
            id = str(uuid.uuid1())
            if event["RequestType"] in ["Create", "Update"]:
              wait_seconds = int(event["ResourceProperties"].get("ServiceTimeout", 0))
              sleep(wait_seconds)
            response = {
              "TimeWaited": wait_seconds,
              "Id": id 
            }
            cfnresponse.send(event, context, cfnresponse.SUCCESS, response, "Waiter-"+id)
  CFNWaiterCustomResource:
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt CFNWaiter.Arn
      ServiceTimeout: 60
Outputs:
  TimeWaited:
    Value: !GetAtt CFNWaiterCustomResource.TimeWaited
    Export:
      Name: TimeWaited
  WaiterId:
    Value: !GetAtt CFNWaiterCustomResource.Id
    Export:
      Name: WaiterId
```

## 샘플 템플릿 연습
<a name="walkthrough-lambda-backed-custom-resources-sample-template-walkthrough"></a>

다음 코드 조각은 샘플 템플릿의 관련 부분을 설명하여 Lambda 함수를 사용자 지정 리소스와 연결하는 방법과 해당 출력을 이해하도록 도움이 됩니다.

[AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html) 리소스 `CFNWaiter`  
`AWS::Lambda::Function` 리소스는 함수의 소스 코드, 핸들러 이름, 런타임 환경 및 실행 역할 Amazon 리소스 이름(ARN)을 지정합니다.  
`Handler` 속성은 Python 소스 코드를 사용하기 때문에 `index.handler`로 설정됩니다. 인라인 함수 소스 코드를 사용할 때 허용되는 핸들러 식별자에 대한 자세한 내용은 [AWS::Lambda::Function Code](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-code.html#cfn-lambda-function-code-zipfile)를 참조하세요.  
`Runtime`은 소스 파일이 Python 코드이므로는 `python3.9`로 지정됩니다.  
`Timeout`은 900초로 설정됩니다.  
`Role` 속성은 `Fn::GetAtt` 함수를 사용하여 템플릿의 `AWS::IAM::Role` 리소스에 선언된 `LambdaExecutionRole` 실행 역할의 ARN을 가져옵니다.  
`Code` 속성은 Python 함수를 사용하여 함수 코드를 인라인으로 정의합니다. 샘플 템플릿의 Python 함수는 다음을 수행합니다.  
+ UUID를 사용하여 고유 ID 생성
+ 요청이 생성 요청인지 또는 업데이트 요청인지 확인
+ `Create` 또는 `Update` 요청 중 `ServiceTimeout`에 지정된 기간만큼 대기
+ 대기 시간 및 고유 ID 반환

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-lambda-resource-json"></a>

```
...
    "CFNWaiter": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Handler": "index.handler",
        "Runtime": "python3.9",
        "Timeout": 900,
        "Role": { "Fn::GetAtt": ["LambdaExecutionRole", "Arn"] },
        "Code": {
          "ZipFile": { "Fn::Join": ["\n", [
            "from time import sleep",
            "import json",
            "import cfnresponse",
            "import uuid",
            "",
            "def handler(event, context):",
            "  wait_seconds = 0",
            "  id = str(uuid.uuid1())",
            "  if event[\"RequestType\"] in [\"Create\", \"Update\"]:",
            "    wait_seconds = int(event[\"ResourceProperties\"].get(\"ServiceTimeout\", 0))",
            "    sleep(wait_seconds)",
            "  response = {",
            "    \"TimeWaited\": wait_seconds,",
            "    \"Id\": id ",
            "  }",
            "  cfnresponse.send(event, context, cfnresponse.SUCCESS, response, \"Waiter-\"+id)"
          ]]}
        }
      }
    },
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-lambda-resource-yaml"></a>

```
...
  CFNWaiter:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Runtime: python3.9 
      Timeout: 900
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile:
          !Sub |
          from time import sleep
          import json
          import cfnresponse
          import uuid
​
          def handler(event, context):
            wait_seconds = 0
            id = str(uuid.uuid1())
            if event["RequestType"] in ["Create", "Update"]:
              wait_seconds = int(event["ResourceProperties"].get("ServiceTimeout", 0))
              sleep(wait_seconds)
            response = {
              "TimeWaited": wait_seconds,
              "Id": id 
            }
            cfnresponse.send(event, context, cfnresponse.SUCCESS, response, "Waiter-"+id)
...
```

[AWS::IAM::Role](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-role.html) 리소스 `LambdaExecutionRole`  
`AWS::IAM:Role` 리소스는 Lambda 함수의 실행 역할을 생성합니다. 여기에는 Lambda가 이를 사용할 수 있도록 허용하는 수임 역할 정책이 포함됩니다. 또한 CloudWatch Logs 액세스를 허용하는 정책도 포함됩니다.

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-iam-role-json"></a>

```
...
    "LambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [{
            "Effect": "Allow",
            "Principal": { "Service": ["lambda.amazonaws.com"] },
            "Action": ["sts:AssumeRole"]
          }]
        },
        "Path": "/",
        "Policies": [{
          "PolicyName": "AllowLogs",
          "PolicyDocument": {
            "Statement": [{
              "Effect": "Allow",
              "Action": ["logs:*"],
              "Resource": "*"
            }]
          }
        }]
      }
    },
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-iam-role-yaml"></a>

```
...
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      Policies:
        - PolicyName: "AllowLogs"
          PolicyDocument:
            Statement:
              - Effect: "Allow"
                Action:
                  - "logs:*"
                Resource: "*"
...
```

[AWS::CloudFormation::CustomResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-customresource.html) 리소스 `CFNWaiterCustomResource`  
사용자 지정 리소스는 `!GetAtt CFNWaiter.Arn`을 사용하여 ARN으로 Lambda 함수에 연결됩니다. `ServiceTimeout`에 설정된 대로 생성 및 업데이트 작업에 대해 60초의 대기 시간을 구현합니다. 속성이 수정된 경우에만 업데이트 작업에 대해서만 리소스가 간접 호출됩니다.

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-custom-resource-json"></a>

```
...
    "CFNWaiterCustomResource": {
      "Type": "AWS::CloudFormation::CustomResource",
      "Properties": {
        "ServiceToken": { "Fn::GetAtt": ["CFNWaiter", "Arn"] },
        "ServiceTimeout": 60
      }
    }
  },
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-custom-resource-yaml"></a>

```
...
  CFNWaiterCustomResource:
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt CFNWaiter.Arn
      ServiceTimeout: 60
...
```

`Outputs`  
이 템플릿의 `Outputs`은 `TimeWaited` 및 `WaiterId`입니다. `TimeWaited` 값은 `Fn::GetAtt` 함수를 사용하여 대기자 리소스가 실제로 대기한 시간을 제공합니다. `WaiterId`는 `Fn::GetAtt` 함수를 사용하여 생성되고 실행과 연결된 고유 ID를 제공합니다.

### JSON
<a name="walkthrough-lambda-backed-custom-resources-sample-template-output-json"></a>

```
...
  "Outputs": {
    "TimeWaited": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "TimeWaited"] },
      "Export": { "Name": "TimeWaited" }
    },
    "WaiterId": {
      "Value": { "Fn::GetAtt": ["CFNWaiterCustomResource", "Id"] },
      "Export": { "Name": "WaiterId" }
    }
  }
}
...
```

### YAML
<a name="walkthrough-lambda-backed-custom-resources-sample-template-output-yaml"></a>

```
...
Outputs:
  TimeWaited:
    Value: !GetAtt CFNWaiterCustomResource.TimeWaited
    Export:
      Name: TimeWaited
  WaiterId:
    Value: !GetAtt CFNWaiterCustomResource.Id
    Export:
      Name: WaiterId
...
```

## 사전 조건
<a name="walkthrough-lambda-backed-custom-resources-prerequisites"></a>

해당하는 서비스(예: Lambda 및 CloudFormation)를 모두 사용하려면 IAM 권한도 있어야 합니다.

## 스택 시작
<a name="walkthrough-lambda-backed-custom-resources-createfunction-createstack"></a>

**스택을 생성하는 방법**

1. [샘플 템플릿](#walkthrough-lambda-backed-custom-resources-sample-template) 섹션에서 원하는 템플릿(YAML 또는 JSON)을 찾아 컴퓨터에 `samplelambdabackedcustomresource.template` 이름으로 저장하세요.

1. [https://console.aws.amazon.com/cloudformation/](https://console.aws.amazon.com/cloudformation/)에서 CloudFormation 콘솔을 엽니다.

1. **스택** 페이지의 오른쪽 상단에서 **스택 생성**을 선택하고 **새 리소스 사용(표준)**을 선택합니다.

1. **사전 조건 - 템플릿 준비**에서 **기존 템플릿 선택**을 선택합니다.

1. **템플릿 지정**에서 **템플릿 파일 업로드**를 선택한 다음 **파일 선택**을 선택하세요.

1. 이전에 저장한 `samplelambdabackedcustomresource.template` 템플릿 파일을 선택하세요.

1. **다음**을 선택합니다.

1. **스택 이름**에 **SampleCustomResourceStack**을 입력하고 **다음**을 선택하세요.

1. 이 연습에서는 태그를 추가하거나 고급 설정을 지정할 필요가 없으므로 **다음**을 선택합니다.

1. 스택 이름이 올바른지 확인한 다음 **업데이트**를 선택하세요.

CloudFormation에서 스택을 생성하는 데 몇 분 정도 걸릴 수 있습니다. 진행 상황을 모니터링하려면 스택 이벤트를 확인합니다. 자세한 내용은 [CloudFormation 콘솔에서 스택 정보 보기](cfn-console-view-stack-data-resources.md) 섹션을 참조하세요.

스택 생성에 성공하면 스택의 모든 리소스(예: Lambda 함수 및 사용자 지정 리소스)가 생성됩니다. Lambda 함수 및 사용자 지정 리소스를 성공적으로 사용했습니다.

Lambda 함수가 오류를 반환하면 CloudWatch Logs [콘솔](https://console.aws.amazon.com/cloudwatch/home#logs:)에서 함수 로그를 확인합니다. 로그 스트림의 이름은 사용자 지정 리소스의 물리적 ID로, 스택의 리소스를 보면 확인할 수 있습니다. 자세한 내용을 알아보려면 Amazon CloudWatch 사용 설명서의 [로그 데이터 보기](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html#ViewingLogData)를 참조하세요.**

## 리소스 정리
<a name="walkthrough-lambda-backed-custom-resources-createfunction-cleanup"></a>

스택을 삭제해 생성한 스택 리소스를 모두 정리하면 불필요한 리소스에 대해 비용이 청구되지 않습니다.

**스택을 삭제하려면**

1. CloudFormation 콘솔에서 **SampleCustomResourceStack** 스택을 선택하세요.

1. **작업**을 선택한 다음 **스택 삭제**를 선택합니다.

1. 확인 메시지에서 **예, 삭제**를 선택합니다.

생성한 리소스가 모두 삭제됩니다.

Lambda 지원 사용자 지정 리소스를 생성하고 사용하는 방법을 이해했으므로 이 연습의 샘플 템플릿과 코드를 사용하여 기타 스택 및 함수를 빌드하고 이를 사용해 실험할 수 있습니다.

## 관련 정보
<a name="w2aac11c45b9c24b9c23"></a>
+ [CloudFormation 사용자 지정 리소스 참조](crpg-ref.md)
+ [AWS::CloudFormation::CustomResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-customresource.html)

# `cfn-response` 모듈
<a name="cfn-lambda-function-code-cfnresponsemodule"></a>

CloudFormation 템플릿에서는 사용자 지정 리소스의 대상으로 Lambda 함수를 지정할 수 있습니다. `ZipFile` 속성을 사용하여 [함수](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html)의 소스 코드를 지정하는 경우 Lambda 함수에서 사용자 지정 리소스로 응답을 전송할 `cfn-response` 모듈을 로드할 수 있습니다. `cfn-response` 모듈은 Lambda 함수를 호출한 사용자 지정 리소스로의 응답 전송을 간소화하는 라이브러리입니다. 이 모듈에는 `send` 메서드가 있고, 이 메서드는 Amazon S3 미리 서명된 URL(`ResponseURL`)을 사용하여 [응답 객체](crpg-ref.md#crpg-ref-responses)를 사용자 지정 리소스로 전송합니다.

`cfn-response` 모듈은 `ZipFile` 속성을 사용하여 소스 코드를 작성할 때만 사용할 수 있습니다. Amazon S3 버킷에 저장된 소스 코드에 사용할 수 없습니다. 버킷 내 코드의 경우, 응답을 전송할 고유 함수를 작성해야 합니다.

**참고**  
`send` 메서드를 실행하고 나면 Lambda 함수가 종료하므로 해당 메서드 이후에 작성하는 모든 내용이 무시됩니다.

## `cfn-response` 모듈 로드
<a name="cfn-lambda-function-code-cfnresponsemodule-loading"></a>

Node.js 함수의 경우 `require()` 함수를 사용하여 `cfn-response` 모듈을 불러옵니다. 예를 들면 다음 코드 예제에서는 `cfn-response` 이름의 `response` 객체를 생성합니다.

```
var response = require('cfn-response');
```

Python의 경우 다음 예제에서와 같이 `import` 문을 사용하여 `cfnresponse` 모듈을 로드합니다.

**참고**  
이 정확한 가져오기 문을 사용합니다. 가져오기 문의 다양한 변형을 사용하는 경우 CloudFormation에서 응답 모듈을 포함하지 않습니다.

```
import cfnresponse
```

## `send` 메서드 파라미터
<a name="cfn-lambda-function-code-cfnresponsemodule-send-parameters"></a>

`send` 메서드와 함께 다음 파라미터를 사용할 수 있습니다.

`event`  
[사용자 지정 리소스 요청](crpg-ref.md#crpg-ref-requesttypes)의 필드입니다.

`context`  
함수 및 콜백이 Lambda 실행 환경 내에서 정보에 액세스했거나 실행을 완료한 경우를 지정하는 데 사용할 수 있는 Lambda 함수 관련 객체입니다. 자세한 내용은 *AWS Lambda 개발자 안내서*의 [Node.js를 사용하여 Lambda 함수 빌드](https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html)를 참조하세요.

`responseStatus`  
함수가 성공적으로 완료되었는지 여부를 나타냅니다. `cfnresponse` 모듈 제약을 사용하여 실행 성공에 대해 `SUCCESS`를 지정하고 실행 실패에 대해 `FAILED`를 지정합니다.

`responseData`  
사용자 지정 [응답 객체](crpg-ref.md#crpg-ref-responses)의 `Data` 필드입니다. 데이터는 이름-값 페어 목록입니다.

`physicalResourceId`  
선택 사항. 함수를 호출한 사용자 지정 리소스의 고유 식별자입니다. 기본적으로 이 모듈은 Lambda 함수와 연결된 Amazon CloudWatch Logs 로그 스트림의 이름을 사용합니다.  
`PhysicalResourceId`에 대해 반환된 값은 사용자 지정 리소스 업데이트 작업을 변경할 수 있습니다. 반환된 값이 같은 경우 일반 업데이트로 간주됩니다. 반환된 값이 다른 경우 CloudFormation은 업데이트를 교체로 인식하고 기존 리소스에 삭제 요청을 전송합니다. 자세한 내용은 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-customresource.html) 섹션을 참조하세요.

`noEcho`  
선택 사항. `Fn::GetAtt` 함수를 사용하여 조회할 때 사용자 지정 리소스의 출력을 마스킹할지 여부를 나타냅니다. `true`로 설정하면 아래 지정된 위치에 저장된 정보를 제외하고, 반환된 모든 값은 별표(\$1\$1\$1\$1\$1)로 마스킹됩니다. 기본적으로 이 값은 `false`입니다.  
`NoEcho` 속성을 사용해도 다음에 저장된 정보는 마스킹되지 않습니다.  
+ `Metadata` 템플릿 섹션. CloudFormation은 `Metadata` 섹션에 포함된 정보를 변환, 수정 또는 삭제하지 않습니다. 자세한 내용은 [메타데이터](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html)를 참조하십시오.
+ `Outputs` 템플릿 섹션. 자세한 내용은 [출력](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html)을 참조하십시오.
+ 리소스 정의의 `Metadata` 속성입니다. 자세한 내용은 [`Metadata` 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-metadata.html)을 참조하세요.
이러한 메커니즘을 사용하여 암호나 보안 정보와 같은 중요한 정보를 포함하지 않는 것이 좋습니다.
`NoEcho`를 사용하여 민감한 정보를 마스킹 처리하는 방법에 대한 자세한 내용은 [템플릿에 자격 증명을 포함하지 않음](security-best-practices.md#creds) 모범 사례를 참조하세요.

## 예제
<a name="cfn-lambda-function-code-cfnresponsemodule-examples"></a>

### Node.js
<a name="cfn-lambda-function-code-zipfile-examplenodejs"></a>

다음 Node.js 예제에서 인라인 Lambda 함수는 입력 값을 받아서 그 값에 5를 곱합니다. 인라인 함수를 사용하면 패키지를 생성하여 Amazon S3 버킷에 업로드하는 대신에 템플릿에서 소스 코드를 직접 지정할 수 있으므로 인라인 함수는 작은 함수에 특히 유용합니다. 이 함수는 `cfn-response` `send` 메서드를 사용하여 호출했던 사용자 지정 리소스로 결과를 다시 전송합니다.

#### JSON
<a name="cfn-lambda-function-code-zipfile-examplenodejs.json"></a>

```
"ZipFile": { "Fn::Join": ["", [
  "var response = require('cfn-response');",
  "exports.handler = function(event, context) {",
  "  var input = parseInt(event.ResourceProperties.Input);",
  "  var responseData = {Value: input * 5};",
  "  response.send(event, context, response.SUCCESS, responseData);",
  "};"
]]}
```

#### YAML
<a name="cfn-lambda-function-code-zipfile-examplenodejs-yaml"></a>

```
ZipFile: >
  var response = require('cfn-response');
  exports.handler = function(event, context) {
    var input = parseInt(event.ResourceProperties.Input);
    var responseData = {Value: input * 5};
    response.send(event, context, response.SUCCESS, responseData);
  };
```

### Python
<a name="cfn-lambda-function-code-zipfile-examplepython"></a>

다음 Python 예제에서 인라인 Lambda 함수는 정수 값을 받아서 그 값에 5를 곱합니다.

#### JSON
<a name="cfn-lambda-function-code-zipfile-examplepython.json"></a>

```
"ZipFile" : { "Fn::Join" : ["\n", [
  "import json",
  "import cfnresponse",
  "def handler(event, context):",
  "   responseValue = int(event['ResourceProperties']['Input']) * 5",
  "   responseData = {}",
  "   responseData['Data'] = responseValue",
  "   cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, \"CustomResourcePhysicalID\")"
]]}
```

#### YAML
<a name="cfn-lambda-function-code-zipfile-examplepython.yaml"></a>

```
ZipFile: |
  import json
  import cfnresponse
  def handler(event, context):
    responseValue = int(event['ResourceProperties']['Input']) * 5
    responseData = {}
    responseData['Data'] = responseValue
    cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
```

## 모듈 소스 코드
<a name="cfn-lambda-function-code-cfnresponsemodule-source"></a>

**Topics**
+ [비동기 Node.js 소스 코드](#cfn-lambda-function-code-cfnresponsemodule-source-nodejs-async)
+ [Node.js 소스 코드](#cfn-lambda-function-code-cfnresponsemodule-source-nodejs)
+ [Python 소스 코드](#cfn-lambda-function-code-cfnresponsemodule-source-python)

### 비동기 Node.js 소스 코드
<a name="cfn-lambda-function-code-cfnresponsemodule-source-nodejs-async"></a>

다음은 핸들러가 비동기식인 경우의 Node.js 함수에 대한 응답 모듈 소스 코드입니다. 이 코드를 검토하면 모듈의 기능을 이해할 수 있으며 고유의 응답 함수를 구현하는 데 도움이 됩니다.

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0

exports.SUCCESS = "SUCCESS";
exports.FAILED = "FAILED";

exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) {

    return new Promise((resolve, reject) => {
        var responseBody = JSON.stringify({
            Status: responseStatus,
            Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
            PhysicalResourceId: physicalResourceId || context.logStreamName,
            StackId: event.StackId,
            RequestId: event.RequestId,
            LogicalResourceId: event.LogicalResourceId,
            NoEcho: noEcho || false,
            Data: responseData
        });

        console.log("Response body:\n", responseBody);

        var https = require("https");
        var url = require("url");

        var parsedUrl = url.parse(event.ResponseURL);
        var options = {
            hostname: parsedUrl.hostname,
            port: 443,
            path: parsedUrl.path,
            method: "PUT",
            headers: {
                "content-type": "",
                "content-length": responseBody.length
            }
        };

        var request = https.request(options, function(response) {
            console.log("Status code: " + parseInt(response.statusCode));
            resolve(context.done());
        });

        request.on("error", function(error) {
            console.log("send(..) failed executing https.request(..): " + maskCredentialsAndSignature(error));
            reject(context.done(error));
        });

        request.write(responseBody);
        request.end();
    })
}
 
function maskCredentialsAndSignature(message) {
    return message.replace(/X-Amz-Credential=[^&\s]+/i, 'X-Amz-Credential=*****')
        .replace(/X-Amz-Signature=[^&\s]+/i, 'X-Amz-Signature=*****');
}
```

### Node.js 소스 코드
<a name="cfn-lambda-function-code-cfnresponsemodule-source-nodejs"></a>

다음은 핸들러가 비동기식이 아닌 경우의 Node.js 함수에 대한 응답 모듈 소스 코드입니다. 이 코드를 검토하면 모듈의 기능을 이해할 수 있으며 고유의 응답 함수를 구현하는 데 도움이 됩니다.

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
 
exports.SUCCESS = "SUCCESS";
exports.FAILED = "FAILED";

exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) {

    var responseBody = JSON.stringify({
        Status: responseStatus,
        Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
        PhysicalResourceId: physicalResourceId || context.logStreamName,
        StackId: event.StackId,
        RequestId: event.RequestId,
        LogicalResourceId: event.LogicalResourceId,
        NoEcho: noEcho || false,
        Data: responseData
    });

    console.log("Response body:\n", responseBody);

    var https = require("https");
    var url = require("url");

    var parsedUrl = url.parse(event.ResponseURL);
    var options = {
        hostname: parsedUrl.hostname,
        port: 443,
        path: parsedUrl.path,
        method: "PUT",
        headers: {
            "content-type": "",
            "content-length": responseBody.length
        }
    };

    var request = https.request(options, function(response) {
        console.log("Status code: " + parseInt(response.statusCode));
        context.done();
    });

    request.on("error", function(error) {
        console.log("send(..) failed executing https.request(..): " + maskCredentialsAndSignature(error));
        context.done();
    });

    request.write(responseBody);
    request.end();
}
```

### Python 소스 코드
<a name="cfn-lambda-function-code-cfnresponsemodule-source-python"></a>

다음은 Python 함수에 대한 응답 모듈 소스 코드입니다.

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
 
from __future__ import print_function
import urllib3
import json
import re

SUCCESS = "SUCCESS"
FAILED = "FAILED"

http = urllib3.PoolManager()


def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False, reason=None):
    responseUrl = event['ResponseURL']

    responseBody = {
        'Status' : responseStatus,
        'Reason' : reason or "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name),
        'PhysicalResourceId' : physicalResourceId or context.log_stream_name,
        'StackId' : event['StackId'],
        'RequestId' : event['RequestId'],
        'LogicalResourceId' : event['LogicalResourceId'],
        'NoEcho' : noEcho,
        'Data' : responseData
    }

    json_responseBody = json.dumps(responseBody)

    print("Response body:")
    print(json_responseBody)

    headers = {
        'content-type' : '',
        'content-length' : str(len(json_responseBody))
    }

    try:
        response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody)
        print("Status code:", response.status)


    except Exception as e:

        print("send(..) failed executing http.request(..):", mask_credentials_and_signature(e))
 
 
def mask_credentials_and_signature(message):
    message = re.sub(r'X-Amz-Credential=[^&\s]+', 'X-Amz-Credential=*****', message, flags=re.IGNORECASE)
    return re.sub(r'X-Amz-Signature=[^&\s]+', 'X-Amz-Signature=*****', message, flags=re.IGNORECASE)
```

# 템플릿 매크로를 사용하여 CloudFormation 템플릿에서 사용자 지정 처리 수행
<a name="template-macros"></a>

매크로를 사용하면 찾기 및 바꾸기 작업 같은 간단한 작업부터 전체 템플릿 변형과 같은 작업까지 템플릿에 대한 사용자 지정 처리를 수행할 수 있습니다.

가능성의 폭에 대한 아이디어를 얻으려면 `AWS::Include` 및 `AWS::Serverless` 변형을 고려하세요. CloudFormation에 의해 호스팅되는 매크로입니다.
+ [AWS::Include 변환](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/transform-aws-include.html)을 사용하면 보일러플레이트 템플릿 코드 조각을 템플릿에 삽입할 수 있습니다.
+ [AWS::Serverless 변환](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/transform-aws-serverless.html)에서는 AWS Serverless Application Model(AWS SAM) 구문에서 작성된 전체 템플릿을 가져온 다음 이를 변형 후 규정 준수 CloudFormation 템플릿으로 확장합니다. 서버리스 애플리케이션 및 AWS SAM에 대한 자세한 내용은 [AWS Serverless Application Model 개발자 안내서](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html)를 참조하세요.

**Topics**
+ [결제](#template-macros-billing)
+ [매크로 예제](#template-macros-examples-list)
+ [관련 리소스](#template-macros-related-resources)
+ [CloudFormation 매크로 개요](template-macros-overview.md)
+ [CloudFormation 매크로 정의 생성](template-macros-author.md)
+ [간단한 문자열 교체 매크로 예제](macros-example.md)
+ [처리된 템플릿 문제 해결](template-macros-troubleshoot-processed-template.md)

## 결제
<a name="template-macros-billing"></a>

매크로가 실행 중일 때 Lambda 함수의 소유자에게 해당 함수의 실행과 관련한 요금이 청구됩니다.

`AWS::Include` 및 `AWS::Serverless` 변환은 CloudFormation에서 호스팅하는 매크로입니다. 사용에 대해 부과되는 요금은 없습니다.

## 매크로 예제
<a name="template-macros-examples-list"></a>

이 섹션의 예제에 추가로 [GitHub 리포지토리](https://github.com/aws-cloudformation/aws-cloudformation-templates/tree/main/CloudFormation/MacrosExamples)에서 소스 코드 및 템플릿을 포함한 예제 매크로를 확인할 수 있습니다. 이러한 예제는 교육용으로 있는 그대로 제공됩니다.

## 관련 리소스
<a name="template-macros-related-resources"></a>
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-macro.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-macro.html)
+ [CloudFormation 템플릿 Transform 섹션](transform-section-structure.md)
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-transform.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-transform.html)
+ [AWS::Serverless 변환](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/transform-aws-serverless.html)
+ [AWS::Include 변환](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/transform-aws-include.html)

# CloudFormation 매크로 개요
<a name="template-macros-overview"></a>

매크로를 사용한 템플릿 처리에 대한 두 가지 주요 단계가 있습니다. 매크로 자체의 생성과 매크로 사용을 통한 템플릿의 처리 수행입니다.

매크로 정의를 생성하려면 다음을 생성해야 합니다.
+ 템플릿 처리를 수행하는 Lambda 함수. 이 Lambda 함수는 코드 조각 또는 전체 템플릿 및 정의하는 추가 파라미터를 수락합니다. 응답으로 처리된 템플릿 코드 조각 또는 전체 템플릿을 반환합니다.
+ [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-macro.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-macro.html) 유형의 리소스로, 이를 통해 사용자는 CloudFormation 템플릿 내부에서 Lambda 함수를 직접적으로 호출할 수 있습니다. 이 리소스는 Lambda 함수의 ARN을 지정하여 이 매크로를 호출하고, 추가 선택적 속성을 지정하여 디버깅을 지원합니다. 계정 내에서 이 리소스를 생성하려면 `AWS::CloudFormation::Macro` 리소스를 포함하는 템플릿을 작성한 다음 템플릿에서 자체 관리 권한이 있는 스택 또는 스택 세트를 생성합니다. CloudFormation StackSets는 현재 매크로를 참조하는 템플릿에서 서비스 관리형 권한으로 스택 세트를 생성하거나 업데이트하는 것을 지원하지 않습니다.

매크로를 사용하려면 템플릿에서 매크로를 참조합니다.
+ 템플릿의 섹션 또는 일부를 처리하려면 변환하려는 템플릿과 관련된 위치에 있는 `Fn::Transform` 함수의 매크로를 참조합니다. `Fn::Transform` 사용 시 필요한 지정된 파라미터를 전달할 수 있습니다.
+ 전체 템플릿을 처리하려면 템플릿의 [Transform](transform-section-structure.md) 섹션에 있는 매크로를 참조합니다.

그런 다음 변경 세트를 생성하고 실행하십시오. (매크로 처리 시 알지 못할 수도 있는 여러 리소스가 추가될 수 있습니다. 매크로가 수행하는 모든 변경을 인식하려면 변경 세트를 사용합니다.) CloudFormation은 추가로 지정된 파라미터와 함께 지정된 템플릿 콘텐츠를 매크로 리소스에 지정된 Lambda 함수에 전달합니다. Lambda 함수는 처리된 템플릿 콘텐츠를 반환하며, 이는 코드 조각 또는 전체 템플릿입니다.

템플릿의 모든 매크로가 직접적으로 호출된 이후 CloudFormation에서 처리된 템플릿 콘텐츠를 포함하는 변경 세트를 생성합니다. 변경 세트를 검토한 후 실행하여 해당 변경 내용을 적용합니다.

![\[Fn::Transform 내장 함수 또는 템플릿의 Transform 섹션을 사용하여 템플릿 콘텐츠 및 관련 파라미터를 매크로의 기본 Lambda 함수를 전달합니다. 여기서 처리된 템플릿 콘텐츠가 반환됩니다.\]](http://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/images/template-macro-use.png)


## 스택을 직접 생성하는 방법
<a name="template-macros-change-sets"></a>

매크로를 참조하는 템플릿을 사용하여 스택을 생성하거나 업데이트하려면 일반적으로 변경 세트를 생성하고 나서 실행하십시오. 변경 세트는 처리된 템플릿에 기초하여 CloudFormation에서 수행할 작업을 설명합니다. 매크로 처리 시 알지 못할 수도 있는 여러 리소스가 추가될 수 있습니다. 매크로가 수행하는 모든 변경을 항상 파악하려면 변경 세트를 사용합니다. 변경 세트를 검토한 후 실행하여 변경을 적용할 수 있습니다.

매크로는 IAM 리소스를 템플릿에 추가할 수 있습니다. 이러한 리소스의 경우 CloudFormation에서는 [해당 기능을 승인](control-access-with-iam.md#using-iam-capabilities)해야 합니다. 템플릿을 처리하기 전에는 CloudFormation에서 추가되는 리소스를 알 수 없으므로 참조되는 매크로가 IAM 리소스를 포함하는지 여부에 따라 변경 세트를 생성할 때 IAM 기능을 승인해야 할 수도 있습니다. 즉, 변경 세트를 실행할 경우 CloudFormation은 IAM 리소스 생성 시 필요한 기능을 갖추게 됩니다.

변경 세트에 제시된 변경을 먼저 검토하지 않고 처리된 템플릿에서 직접 스택을 생성하거나 업데이트하려면 `CreateStack` 또는 `UpdateStack` 요청 중 `CAPABILITY_AUTO_EXPAND` 기능을 지정합니다. 매크로가 수행하는 처리를 알고 있을 경우에만 매크로를 포함하는 스택 템플릿에서 직접 스택을 생성해야 합니다. 스택 세트 매크로에는 변경 세트를 사용할 수 없습니다. 스택 세트를 직접 업데이트해야 합니다.

자세한 내용은 *AWS CloudFormation API 참조*의 [https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html) 또는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_UpdateStack.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_UpdateStack.html) 섹션을 참조하세요.

**중요**  
스택 세트 템플릿에서 하나 이상의 매크로를 참조하는 경우 먼저 변경 세트의 결과 변경 사항을 먼저 검토하지 않고 처리된 템플릿에서 직접 스택 세트를 생성해야 합니다. 매크로 처리 시 알지 못할 수도 있는 여러 리소스가 추가될 수 있습니다. 매크로를 직접 참조하는 템플릿에서 스택 세트를 생성 또는 업데이트하기 전에 매크로가 수행하는 처리 작업을 알고 있어야 합니다.

매크로를 참조하는 템플릿에서 스택 시작에 필요한 단계 수를 줄이려면 `package` 및 `deploy` AWS CLI 명령을 사용합니다. 자세한 내용은 [AWS CLI를 사용하여 S3 버킷에 로컬 아티팩트 업로드](using-cfn-cli-package.md) 및 [변환이 포함된 스택 생성](service_code_examples.md#deploy-sdk)(을)를 참조하세요.

## 고려 사항
<a name="template-macros-considerations"></a>

매크로를 사용하는 경우 다음 고려 사항 및 제한 사항에 유의하세요.
+ 매크로는 Lambda 사용이 가능한 AWS 리전에서만 지원됩니다. Lambda를 사용할 수 있는 리전 목록을 알아보려면 [AWS Lambda 엔드포인트 및 할당량](https://docs.aws.amazon.com/general/latest/gr/lambda-service.html)을 참조하세요.
+ 처리된 템플릿 조각은 유효한 JSON이어야 합니다.
+ 모든 처리된 템플릿 조각은 스택 생성, 스택 업데이트, 스택 세트 생성 또는 스택 세트 업데이트 작업에 대한 검증 확인을 전달해야 합니다.
+ CloudFormation은 매크로를 먼저 확인하고 템플릿을 처리합니다. 결과 템플릿은 유효한 JSON 또는 이어야 하며 템플릿 크기 제한을 초과해서는 안 됩니다.
+ CloudFormation이 템플릿에서 요소를 처리하는 순서가 있기 때문에 매크로는 CloudFormation에 반환하는 처리된 템플릿 콘텐츠에 모듈을 포함할 수 없습니다. 자세한 내용은 [매크로 평가 순서](template-macros-author.md#template-macros-order) 섹션을 참조하세요.
+ 업데이트 롤백 기능을 사용하면 CloudFormation은 원본 템플릿의 사본을 사용합니다. 포함된 코드 조각이 변경된 경우에도 원본 템플릿으로 롤백됩니다.
+ 매크로는 재귀적으로 처리되지 않기 때문에 매크로 내에 매크로를 포함시키면 작동하지 않습니다.
+ 현재 매크로에서 `Fn::ImportValue` 내장 함수를 지원하지 않습니다.
+ 템플릿에 포함된 내장 함수는 모든 매크로 이후 평가됩니다. 따라서 매크로가 반환하는 처리된 템플릿 콘텐츠에는 내장 함수에 대한 호출이 포함될 수 있고, 이는 평소와 같이 평가됩니다.
+ StackSets는 현재 CloudFormation 매크로를 참조하는 템플릿에서 서비스 관리형 권한으로 스택 세트를 생성하거나 업데이트하는 것을 지원하지 않습니다.

## 매크로 계정 범위 및 권한
<a name="template-macros-permissions"></a>

리소스로 생성된 계정에서만 매크로를 사용할 수 있습니다. 매크로의 이름은 해당 계정 내에서 고유해야 합니다. 하지만 기본 Lambda 함수에서 교차 계정 액세스를 활성화하고 여러 계정에서 해당 함수를 참조하는 매크로 정의를 생성함으로써 여러 계정에서 동일한 기능을 사용할 수 있도록 할 수 있습니다. 아래 예제에서는 3개의 계정에 동일한 Lambda 함수를 가리키는 매크로 정의가 포함되어 있습니다.

![\[Lambda 함수에서 교차 계정 액세스를 허용함으로써 AWS에서 사용자가 해당 함수를 참조하는 여러 계정에서 매크로를 생성할 수 있도록 합니다.\]](http://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/images/template-macro-accounts.png)


매크로 정의를 생성하려면 사용자에게 지정된 계정 내에서 스택 또는 스택 세트를 생성할 수 있는 권한이 있어야 합니다.

CloudFormation에서 템플릿에 포함된 매크로를 실행하려면 사용자가 기본 Lambda 함수에 대해 `Invoke` 권한을 보유해야 합니다. 잠재적인 권한 상승을 방지하도록 CloudFormation에서는 매크로 실행 도중 사용자를 가장합니다.

자세한 내용은 *AWS Lambda 개발자 안내서*의 [AWS Lambda에서 권한 관리](https://docs.aws.amazon.com/lambda/latest/dg/lambda-permissions.html) 및 *서비스 승인 참조*의 [Actions, resources, and condition keys for AWS Lambda](https://docs.aws.amazon.com/service-authorization/latest/reference/list_awslambda.html)를 참조하세요.

# CloudFormation 매크로 정의 생성
<a name="template-macros-author"></a>

매크로 정의를 생성할 때 매크로 정의에서 지정된 계정의 기본 Lambda 함수를 사용할 수 있도록 하여 CloudFormation에서 이를 간접적으로 호출하고 템플릿을 처리합니다.

## 이벤트 매핑
<a name="template-macros-event-mapping"></a>

CloudFormation은 매크로의 Lambda 함수를 간접적으로 호출할 때 다음 구조의 JSON 형식으로 요청을 전송합니다.

```
{
    "region" : "us-east-1",
    "accountId" : "$ACCOUNT_ID",
    "fragment" : { ... },
    "transformId" : "$TRANSFORM_ID",
    "params" : { ... },
    "requestId" : "$REQUEST_ID",
    "templateParameterValues" : { ... }
}
```
+ `region`

  매크로가 상주하는 리전입니다.
+ `accountId`

  매크로가 Lambda 함수를 호출하는 계정의 계정 ID입니다.
+ `fragment`

  사용자 지정 처리 사용이 가능한 템플릿 콘텐츠로 JSON 형식입니다.
  + `Transform` 템플릿 섹션에 포함된 매크로의 경우 `Transform` 섹션을 제외한 전체 템플릿입니다.
  + `Fn::Transform` 내장 함수 호출에 포함된 매크로의 경우 템플릿 내에 있는 내장 함수의 위치를 기반으로 한 모든 형제(및 하위) 노드가 포함됩니다. 단, `Fn::Transform` 함수는 예외입니다. 자세한 내용은 [매크로 템플릿 범위](#template-macros-scope) 섹션을 참조하세요.
+ `transformId`

  이 함수를 호출하는 매크로의 이름입니다.
+ `params`

  `Fn::Transform` 함수 직접 호출의 경우 함수에 대한 지정된 파라미터입니다. CloudFormation은 이러한 파라미터를 함수에 전달하기 전에 평가하지 않습니다.

  `Transform` 템플릿 섹션에 포함된 매크로의 경우 이 섹션은 비어 있습니다.
+ `requestId`

  이 함수를 호출하는 요청의 ID입니다.
+ `templateParameterValues`

  템플릿의 [Parameters](parameters-section-structure.md) 섹션에 지정된 파라미터입니다. CloudFormation은 이러한 파라미터를 함수에 전달하기 전에 평가합니다.

## 응답 형식
<a name="template-macros-response-format"></a>

CloudFormation에서는 Lambda 함수가 다음 JSON 형식의 응답을 반환할 것으로 예상합니다.

```
{
    "requestId" : "$REQUEST_ID",
    "status" : "$STATUS",
    "fragment" : { ... },
    "errorMessage": "optional error message for failures"
}
```
+ `requestId`

  이 함수를 호출하는 요청의 ID입니다. 함수 호출 시 CloudFormation에서 제공하는 요청 ID와 일치해야 합니다.
+ `status`

  요청의 상태입니다(대/소문자를 구분하지 않음). `success`로 설정되어야 합니다. CloudFormation에서 다른 모든 응답을 실패로 처리합니다.
+ `fragment`

  형제 템플릿을 포함하여 처리된 템플릿에 포함할 CloudFormation의 처리된 템플릿 콘텐츠입니다. CloudFormation이 Lambda 함수에 전달된 템플릿 콘텐츠를 Lambda 응답에서 수신하는 템플릿 조각으로 대체합니다.

  처리된 템플릿 콘텐츠는 유효한 JSON이어야 하고, 처리된 템플릿에 포함된 사항은 유효한 템플릿이 되어야 합니다.

  함수가 CloudFormation에서 전달하는 템플릿 콘텐츠를 실제로 변경하지 않지만 이러한 콘텐츠를 처리된 템플릿에 포함해야 하는 경우 함수가 응답에서 해당 템플릿 콘텐츠를 CloudFormation으로 반환해야 합니다.
+ `errorMessage`

  변환이 실패한 이유를 설명하는 오류 메시지입니다. CloudFormation은 스택에 대한 **Stack details**(스택 세부 정보) 페이지의 **Events**(이벤트) 창에 이 오류 메시지를 표시합니다.

  예제:

  ```
  Error creating change set: Transform
                              AWS 계정 account
                              number::macro name failed with:
                              error message string.
  ```

## 매크로 정의 생성
<a name="create-a-macro-definition"></a>

**CloudFormation 매크로 정의를 생성하려면 다음을 수행하세요.**

1. 템플릿 콘텐츠 처리를 처리할 [Lambda 함수를 빌드](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html)합니다. 함수가 템플릿의 일부분부터 전체 템플릿까지 처리할 수 있습니다.

1. `AWS::CloudFormation::Macro` 리소스 유형이 포함된 CloudFormation 템플릿을 생성하고 `Name` 및 `FunctionName` 속성을 지정합니다. `FunctionName` 속성은 CloudFormation에서 매크로 실행 시 간접적으로 호출할 Lambda 함수의 ARN을 포함해야 합니다.

1. (선택 사항) 디버깅을 돕기 위해 매크로에 대한 `AWS::CloudFormation::Macro` 리소스 유형 생성 시 `LogGroupName` 및 `LogRoleArn` 속성을 지정할 수 있습니다. 이러한 속성을 통해 매크로의 기본 Lambda 함수를 간접적으로 호출할 때 CloudFormation에서 오류 로깅 정보를 전송하는 CloudWatch Logs 로그 그룹을 지정할 수 있으며, 로그 항목을 로그로 전송할 때 CloudFormation에서 수임해야 하는 역할을 지정할 수 있습니다.

1. 스택을 사용하려는 계정에서 매크로가 포함된 템플릿을 사용하여 [스택을 생성](cfn-console-create-stack.md)합니다. 또는 관리자 계정에서 매크로가 포함된 템플릿을 사용하여 [자체 관리형 권한으로 스택 세트를 생성](stacksets-getting-started-create-self-managed.md)한 다음 대상 계정에서 스택 인스턴스를 생성합니다.

1. CloudFormation에서 매크로 정의가 포함된 스택을 생성한 이후 매크로는 해당 계정 내에서 사용 가능합니다. 처리하고자 하는 템플릿 콘텐츠와 관련이 있는 적절한 위치에서 템플릿을 참조하여 매크로를 사용합니다.

## 매크로 템플릿 범위
<a name="template-macros-scope"></a>

템플릿의 `Transform` 섹션에서 참조되는 매크로는 해당 템플릿의 전체 콘텐츠를 처리할 수 있습니다.

`Fn::Transform` 함수에서 참조되는 매크로는 템플릿의 `Fn::Transform` 함수에 대한 형제 요소(하위 요소 포함)의 콘텐츠를 처리할 수 있습니다.

예를 들어 아래 템플릿 샘플에서 `AWS::Include`는 `Fn::Transform` 함수의 위치를 기준으로 `MyBucket` 속성을 모두 처리할 수 있습니다. `MyMacro`는 `Transform` 섹션에 포함되어 있으므로 전체 템플릿의 콘텐츠를 처리할 수 있습니다.

```
# Start of processable content for MyMacro
AWSTemplateFormatVersion: 2010-09-09 
 Transform: [MyMacro]
 Resources:
    WaitCondition:
      Type: AWS::CloudFormation::WaitCondition
    MyBucket:
      Type: AWS::S3::Bucket
      # Start of processable content for AWS::Include
      Properties:
        BucketName: amzn-s3-demo-bucket1
        Tags: [{"key":"value"}] 
        'Fn::Transform':
          - Name: 'AWS::Include'
              Parameters:
                Location: s3://amzn-s3-demo-bucket2/MyFileName.yaml
        CorsConfiguration: []
        # End of processable content for AWS::Include
    MyEc2Instance:
      Type: AWS::EC2::Instance
      Properties:
        ImageID: ami-1234567890abcdef0
# End of processable content for MyMacro
```

## 매크로 평가 순서
<a name="template-macros-order"></a>

[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/transform-aws-include.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/transform-aws-include.html) 및 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/transform-aws-serverless.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/transform-aws-serverless.html) 등과 같이 CloudFormation에서 호스팅되는 변형을 포함하여 해당 템플릿의 여러 매크로를 참조할 수 있습니다.

매크로는 템플릿에서의 위치를 기준으로 가장 깊이 중첩된 외부부터 가장 일반적인 순서로 평가됩니다. 템플릿의 동일한 위치에 있는 매크로는 나열된 순서를 기준으로 순차적으로 평가됩니다.

`AWS::Include` 및 `AWS::Transform`과 같은 변형은 작업 순서 및 범위 측면에서 다른 매크로와 동일하게 취급됩니다.

예를 들어, 아래의 템플릿 샘플에서 CloudFormation은 템플릿에서 가장 깊이 중첩된 매크로인 `PolicyAdder` 매크로를 먼저 평가합니다. 그런 다음 CloudFormation은 `Transform` 섹션에서 `AWS::Serverless`보다 먼저 나열되어 있기 때문에 `MyMacro`를 `AWS::Serverless`보다 먼저 평가합니다.

```
AWSTemplateFormatVersion: 2010-09-09
 Transform: [MyMacro, AWS::Serverless]
 Resources:
    WaitCondition:
      Type: AWS::CloudFormation::WaitCondition
    MyBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: amzn-s3-demo-bucket
        Tags: [{"key":"value"}]
        'Fn::Transform':
          - Name: PolicyAdder
        CorsConfiguration: []
    MyEc2Instance:
      Type: AWS::EC2::Instance
      Properties:
        ImageID: ami-1234567890abcdef0
```

# 간단한 문자열 교체 매크로 예제
<a name="macros-example"></a>

다음 예제는 템플릿에서 매크로를 정의하는 것부터 매크로에 대한 Lambda 함수를 생성하고 템플릿에 있는 매크로를 사용하는 것에 이르기까지 매크로 사용 프로세스를 연습합니다.

이 예제에서 지정된 문자열을 처리된 콘텐츠의 지정된 대상 콘텐츠를 대신하여 삽입하는 단순한 매크로를 생성합니다. 또한 이를 사용하여 처리된 템플릿의 지정된 위치에 빈 `WaitHandleCondition`을 삽입합니다.

## 매크로 생성
<a name="macros-example-definiton"></a>

매크로를 사용하기 전에 2가지를 완료해야 합니다. 원하는 템플릿 처리를 수행하는 Lambda 함수를 생성하고, 매크로 정의를 생성함으로써 CloudFormation에서 Lambda 함수를 사용할 수 있도록 합니다.

다음 샘플 템플릿에는 예제 매크로에 대한 정의가 포함되어 있습니다. 특정 AWS 계정에서 매크로를 사용할 수 있도록 하려면 템플릿에서 스택을 생성합니다. 매크로 정의는 매크로 이름, 간단한 설명을 지정하고, 이 매크로가 템플릿에서 사용될 때 CloudFormation에서 호출하는 Lambda 함수의 ARN을 참조합니다. (오류 로깅을 위해 `LogGroupName` 또는 `LogRoleARN` 속성을 포함하지 않았습니다.) 

이 예제에서는 이 템플릿에서 생성된 스택의 이름이 `JavaMacroFunc`라고 가정합니다. 매크로 `Name` 속성이 스택 이름으로 설정되었기 때문에 결과로 나오는 매크로 이름은 `JavaMacroFunc`입니다.

```
AWSTemplateFormatVersion: 2010-09-09
  Resources:
    Macro:
      Type: AWS::CloudFormation::Macro
      Properties:
        Name: !Sub '${AWS::StackName}'
        Description: Adds a blank WaitConditionHandle named WaitHandle
        FunctionName: 'arn:aws:lambda:us-east-1:012345678910:function:JavaMacroFunc'
```

## 매크로 사용
<a name="macros-example-usage"></a>

매크로를 사용하기 위해 `Fn::Transform` 내장 함수를 사용하여 이를 템플릿에 포함합니다.

아래 템플릿을 사용하여 스택을 생성할 때 CloudFormation에서 예제 매크로를 호출합니다. 기본 Lambda 함수는 지정된 문자열을 다른 지정된 문자열로 바꿉니다. 이 경우에는 결과적으로 빈 `AWS::CloudFormation::WaitConditionHandle`이 처리된 템플릿으로 삽입됩니다.

```
Parameters:
  ExampleParameter:
    Type: String
    Default: 'SampleMacro'

Resources:
  2a:
    Fn::Transform:
      Name: "JavaMacroFunc"
      Parameters:
        replacement: 'AWS::CloudFormation::WaitConditionHandle'
        target: '$$REPLACEMENT$$'
    Type: '$$REPLACEMENT$$'
```
+ 간접적으로 호출할 매크로는 이전 매크로 정의 예제에서 가져온 `JavaMacroFunc`로 지정됩니다.
+ 매크로는 전달되는 2개의 파라미터로, `target` 및 `replacement`입니다. 대상 문자열과 원하는 대체 값을 나타냅니다.
+ 매크로는 `Type` 노드의 콘텐츠를 처리할 수 있는데, `Type`이 매크로를 참조하는 `Fn::Transform` 함수의 형제이기 때문입니다.
+ 결과 `AWS::CloudFormation::WaitConditionHandle`의 이름은 `2a`입니다.
+ 템플릿에는 또한 템플릿 파라미터인 `ExampleParameter`가 포함되어 있습니다. 매크로에서 여기에 액세스할 수 있습니다(단, 이 경우 사용하지 않음).

## Lambda 입력 데이터
<a name="macros-example-request"></a>

CloudFormation에서 스택 생성 도중 예제 템플릿을 처리할 때 다음 이벤트 매핑을 `JavaMacroFunc` 매크로 정의에서 참조되는 Lambda 함수에 전달합니다.
+ `region` : `us-east-1`
+ `accountId` : `012345678910`
+ `fragment` :

  ```
  {
    "Type": "$$REPLACEMENT$$"
  }
  ```
+ `transformId` : `012345678910::JavaMacroFunc`
+ `params` : 

  ```
  {
      "replacement": "AWS::CloudFormation::WaitConditionHandle",
      "target": "$$REPLACEMENT$$"
  }
  ```
+ `requestId` : `5dba79b5-f117-4de0-9ce4-d40363bfb6ab`
+ `templateParameterValues` :

  ```
  {
      "ExampleParameter": "SampleMacro"
  }
  ```

`fragment`에는 매크로에서 처리할 수 있는 템플릿 조각을 나타내는 JSON이 포함되어 있습니다. 이 조각에는 `Fn::Transform` 함수 호출의 형제가 포함되어 있지만 함수 호출 자체가 포함되어 있지는 않습니다. 또한 `params`에는 매크로 파라미터를 나타내는 JSON이 포함되어 있습니다. 이 경우 대체 및 대상입니다. 비슷하게 `templateParameterValues`에는 전체적으로 템플릿에 지정된 파라미터를 나타내는 JSON이 포함되어 있습니다.

## Lambda 함수 코드
<a name="macros-example-function"></a>

다음은 기본 `JavaMacroFunc` 예제 매크로의 Lambda 함수에 대한 실제 코드입니다. 응답에 포함된 템플릿 조각(문자열, 목록 또는 맵 형식)을 반복하여 지정된 대상 문자열을 찾습니다. 지정된 대상 문자열을 찾으면 Lambda 함수에서 대상 문자열을 지정된 대체 문자열로 바꿉니다. 그렇지 않은 경우 함수에서 템플릿 조각을 변경하지 않은 채로 둡니다. 그런 다음 함수에서 아래 세부 정보에서 논의하는 예상 속성의 맵을 CloudFormation에 반환합니다.

```
package com.macroexample.lambda.demo;

import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class LambdaFunctionHandler implements RequestHandler<Map<String, Object>, Map<String, Object>> {

	private static final String REPLACEMENT = "replacement";
	private static final String TARGET = "target";
	private static final String PARAMS = "params";
	private static final String FRAGMENT = "fragment";
	private static final String REQUESTID = "requestId";
	private static final String STATUS = "status";
	private static final String SUCCESS = "SUCCESS";
	private static final String FAILURE = "FAILURE";
    @Override
    public Map<String, Object> handleRequest(Map<String, Object> event, Context context) {
        // TODO: implement your handler
    	final Map<String, Object> responseMap = new HashMap<String, Object>();
        responseMap.put(REQUESTID, event.get(REQUESTID));
        responseMap.put(STATUS, FAILURE);
    	try {
	        if (!event.containsKey(PARAMS)) {
	        	throw new RuntimeException("Params are required");
	        }
	    	
	        final Map<String, Object> params = (Map<String, Object>) event.get(PARAMS);
	        if (!params.containsKey(REPLACEMENT) || !params.containsKey(TARGET)) {
	        	throw new RuntimeException("replacement or target under Params are required");
	        }
	    	
	    	final String replacement = (String) params.get(REPLACEMENT);
	    	final String target = (String) params.get(TARGET);
	    	final Object fragment = event.getOrDefault(FRAGMENT, new HashMap<String, Object>());
	    	final Object retFragment;
	    	if (fragment instanceof String) {
	    		retFragment = iterateAndReplace(replacement, target, (String) fragment);
	    	} else if (fragment instanceof List) {
	    		retFragment = iterateAndReplace(replacement, target, (List<Object>) fragment);
	    	} else if (fragment instanceof Map) {
	    		retFragment = iterateAndReplace(replacement, target, (Map<String, Object>) fragment);
	    	} else {
	    		retFragment = fragment;
	    	}
	        responseMap.put(STATUS, SUCCESS);
	        responseMap.put(FRAGMENT, retFragment);
	        return responseMap;
    	} catch (Exception e) {
    		e.printStackTrace();
    		context.getLogger().log(e.getMessage());
    		return responseMap;
    	}
    }
    
    private Map<String, Object> iterateAndReplace(final String replacement, final String target, final Map<String, Object> fragment) {
    	final Map<String, Object> retFragment = new HashMap<String, Object>();
    	final List<String> replacementKeys = new ArrayList<>();
    	fragment.forEach((k, v) -> {
    		if (v instanceof String) {
    			retFragment.put(k, iterateAndReplace(replacement, target, (String)v));
    		} else if (v instanceof List) {
    			retFragment.put(k, iterateAndReplace(replacement, target, (List<Object>)v));
    		} else if (v instanceof Map ) {
    			retFragment.put(k, iterateAndReplace(replacement, target, (Map<String, Object>) v));
    		} else {
    			retFragment.put(k, v);
    		}
    	});
    	return retFragment;
    }

    private List<Object> iterateAndReplace(final String replacement, final String target, final List<Object> fragment) {
    	final List<Object> retFragment = new ArrayList<>();
    	fragment.forEach(o -> {
    		if (o instanceof String) {
    			retFragment.add(iterateAndReplace(replacement, target, (String) o));
    		} else if (o instanceof List) {
    			retFragment.add(iterateAndReplace(replacement, target, (List<Object>) o));
    		} else if (o instanceof Map) {
    			retFragment.add(iterateAndReplace(replacement, target, (Map<String, Object>) o));
    		} else {
    			retFragment.add(o);
    		}
    	});
    	return retFragment;
    }
    
    private String iterateAndReplace(final String replacement, final String target, final String fragment) {
    	System.out.println(replacement + " == " + target + " == " + fragment );
    	if (fragment != null AND_AND fragment.equals(target))
    		return replacement;
    	return fragment;
    }
}
```

## Lambda 함수 응답
<a name="macros-example-response"></a>

다음은 Lambda 함수에서 처리를 위해 CloudFormation으로 반환하는 매핑입니다.
+ `requestId` : `5dba79b5-f117-4de0-9ce4-d40363bfb6ab`
+ `status` : `SUCCESS`
+ `fragment` :

  ```
  {
    "Type": "AWS::CloudFormation::WaitConditionHandle"
  }
  ```

`requestId`가 CloudFormation에서 전송된 것과 일치하는 경우 `status`의 `SUCCESS`는 Lambda 함수가 요청에 포함된 템플릿 조각을 처리했음을 의미합니다. 이 응답에서 `fragment`에는 기존 템플릿 조각을 대신하여 처리된 템플릿에 삽입할 콘텐츠를 나타내는 JSON이 포함되어 있습니다.

## 처리된 템플릿 결과
<a name="macros-example-processed"></a>

CloudFormation에서 Lambda 함수로부터 성공적인 응답을 수신한 이후 반환된 템플릿 조각을 처리된 템플릿에 삽입합니다.

아래는 예제에 해당하는 처리된 템플릿 결과입니다. `JavaMacroFunc` 매크로를 참조하는 `Fn::Transform` 내장 함수 직접 호출은 더 이상 포함되지 않습니다. Lambda 함수에서 반환하는 템플릿 조각은 적절한 위치에 포함되며, 결과적으로 콘텐츠 `"Type": "$$REPLACEMENT$$"`는 `"Type": "AWS::CloudFormation::WaitConditionHandle"`로 변경되었습니다.

```
{
    "Parameters": {
        "ExampleParameter": {
            "Default": "SampleMacro",
            "Type": "String"
        }
    },
    "Resources": {
        "2a": {
            "Type": "AWS::CloudFormation::WaitConditionHandle"
        }
    }
}
```

# 처리된 템플릿 문제 해결
<a name="template-macros-troubleshoot-processed-template"></a>

매크로를 사용할 때 CloudFormation 콘솔에서 처리된 템플릿을 찾을 수 있습니다.

템플릿의 스테이지는 처리 상태를 나타냅니다.
+ `Original`: 사용자가 스택 또는 스택 세트를 생성하거나 업데이트하기 위해 최초로 제출한 템플릿입니다.
+ `Processed`: CloudFormation에서 참조된 매크로 처리 이후 스택 또는 스택 세트를 생성하거나 업데이트할 때 사용하는 템플릿입니다. 원본 템플릿이 YAML 형식인 경우에도 처리된 템플릿은 JSON 형식입니다.

문제 해결을 위해 처리된 템플릿을 사용합니다. 템플릿이 매크로를 참조하지 않는 경우 원본 템플릿과 처리된 템플릿이 동일합니다.

자세한 내용은 [CloudFormation 콘솔에서 스택 정보 보기](cfn-console-view-stack-data-resources.md) 섹션을 참조하세요.

AWS CLI를 사용하여 처리된 템플릿을 가져오려면 [get-template](service_code_examples.md#get-template-sdk) 명령을 사용합니다.

## 크기 제한
<a name="template-macros-size-limitation"></a>

`CreateStack`, `UpdateStack` 또는 `ValidateTemplate`으로 직접 전달될 경우 처리되는 스택 템플릿의 최대 크기는 51,200바이트이고, Amazon S3 템플릿 URL을 사용하여 S3 객체로 처리될 경우에는 1MB입니다. 그러나 처리 중 CloudFormation은 템플릿에 포함된 매크로를 연속적으로 처리할 때 템플릿의 임시 상태를 업데이트합니다. 이 때문에 처리 중 템플릿의 크기가 전체 처리된 템플릿의 허용 크기를 일시적으로 초과할 수 있습니다. CloudFormation은 이러한 프로세스 내 템플릿에 대한 일부 버퍼를 허용합니다. 그러나 처리되는 스택 템플릿의 최대 허용 크기를 고려하여 템플릿과 매크로를 설계해야 합니다.

템플릿을 처리할 때 CloudFormation이 `Transformation data limit exceeded` 오류를 반환할 경우, CloudFormation이 처리 중 허용하는 최대 템플릿 크기를 초과한 것입니다.

이 문제를 해결하려면 다음과 같이 해 보십시오.
+ 템플릿을 여러 개의 템플릿으로 재구성하여 처리 과정의 템플릿에 대한 최대 크기를 넘지 않도록 하십시오. 예제:
  + 중첩 스택 템플릿을 사용하여 템플릿의 부분을 캡슐화합니다. 자세한 내용은 [중첩 스택을 사용하여 템플릿을 재사용 가능한 조각으로 분할](using-cfn-nested-stacks.md) 섹션을 참조하세요.
  + 여러 개의 스택을 생성하고 교차 스택 참조를 사용하여 스택 간에 정보를 교환합니다. 자세한 내용은 [다른 CloudFormation 스택의 리소스 출력 참조](walkthrough-crossstackref.md) 섹션을 참조하세요.
+ 특정 매크로가 반환하는 템플릿 조각의 크기를 줄입니다. CloudFormation은 매크로가 반환한 조각의 내용을 변경하지 않습니다.

# 중첩 스택을 사용하여 템플릿을 재사용 가능한 조각으로 분할
<a name="using-cfn-nested-stacks"></a>

인프라가 증가함에 따라 여러 템플릿에서 동일한 리소스 구성을 반복적으로 생성할 수 있습니다. 이러한 중복성을 방지하려면 이러한 공통 구성을 전용 템플릿으로 분리할 수 있습니다. 그런 다음 다른 템플릿의 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-stack.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-stack.html) 리소스를 사용하여 이러한 전용 템플릿을 참조하여 중첩 스택을 생성할 수 있습니다.

예를 들어 대부분의 스택에 사용하는 로드 밸런서 구성이 있다고 가정합니다. 동일한 구성을 복사하여 템플릿에 붙여 넣는 대신 로드 밸런서 전용 템플릿을 생성할 수 있습니다. 그런 다음 동일한 로드 밸런서 구성이 필요한 다른 템플릿 내에서 이 템플릿을 참조할 수 있습니다.

중첩 스택에는 다른 중첩 스택이 포함될 수 있으며 아래 다이어그램에서와 같이 스택 계층 구조가 생성됩니다. *루트 스택*은 모든 중첩 스택이 궁극적으로 속하는 최상위 스택입니다. 각 중첩 스택에는 직속 상위 스택이 있습니다. 중첩 스택의 첫 레벨의 경우 루트 스택이 상위 스택이기도 합니다.
+ 스택 A는 계층 구조에 있는 다른 모든 중첩 스택의 루트 스택입니다.
+ 스택 B의 경우에는 스택 A가 상위 스택이자 루트 스택입니다.
+ 스택 C의 경우 스택 B가 상위 스택이고 스택 D의 상위 스택은 스택 C입니다.

![\[다른 스택의 일부로 생성된 중첩 스택에는 직속 상위 스택과 최상위 루트 스택이 있습니다.\]](http://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/images/cfn-console-nested-stacks.png)


**Topics**
+ [템플릿 분할 이전 및 이후 예](#create-nested-stack-template)
+ [중첩 스택 아키텍처의 예](#nested-stack-examples)
+ [중첩 스택에서 스택 작업 수행](#perform-stack-operations-on-nested-stacks)
+ [관련 정보](#nested-stacks-related-information)

## 템플릿 분할 이전 및 이후 예
<a name="create-nested-stack-template"></a>

이 예제에서는 어떻게 큰 CloudFormation 템플릿 하나를 가져와서 중첩 템플릿을 사용하여 더 정형화되고 재사용 가능한 설계로 재구성할 수 있는지 보여줍니다. 처음에 "스택 중첩 전" 템플릿에는 파일 하나에 정의된 모든 리소스가 표시됩니다. 리소스 수가 늘어날수록 이 과정이 복잡해지고 관리하기 어려워질 수 있습니다. '스택 중첩 후' 템플릿에서는 리소스를 더 작은 별도의 템플릿으로 분할합니다. 각 중첩 스택에서는 특정 관련 리소스 세트를 처리하므로 전체 구조가 더 체계적으로 구성되고 유지 관리가 더 쉬워집니다.


| 스택 중첩 전 | 스택 중첩 후 | 
| --- | --- | 
| <pre>AWSTemplateFormatVersion: 2010-09-09<br />Parameters:<br />  InstanceType:<br />    Type: String<br />    Default: t2.micro<br />    Description: The EC2 instance type<br />  <br />  Environment:<br />    Type: String<br />    Default: Production<br />    Description: The deployment environment<br /><br />Resources:<br />  MyEC2Instance:<br />    Type: AWS::EC2::Instance<br />    Properties:<br />      ImageId: ami-1234567890abcdef0<br />      InstanceType: !Ref InstanceType<br /><br />  MyS3Bucket:<br />    Type: AWS::S3::Bucket</pre> | <pre>AWSTemplateFormatVersion: 2010-09-09<br />Resources:<br />  MyFirstNestedStack:<br />    Type: AWS::CloudFormation::Stack<br />    Properties:<br />      TemplateURL: https://s3.amazonaws.com/amzn-s3-demo-bucket/first-nested-stack.yaml<br />      Parameters:<br />        # Pass parameters to the nested stack if needed<br />        InstanceType: t3.micro<br /><br />  MySecondNestedStack:<br />    Type: AWS::CloudFormation::Stack<br />    Properties:<br />      TemplateURL: https://s3.amazonaws.com/amzn-s3-demo-bucket/second-nested-stack.yaml<br />      Parameters:<br />        # Pass parameters to the nested stack if needed<br />        Environment: Testing<br />    DependsOn: MyFirstNestedStack</pre> | 

## 중첩 스택 아키텍처의 예
<a name="nested-stack-examples"></a>

이 섹션에서는 중첩 스택을 참조하는 최상위 스택으로 구성된 중첩 스택 아키텍처를 보여줍니다. 중첩 스택은 Node.js Lambda 함수를 배포하고, 최상위 스택에서 파라미터 값을 수신하며, 최상위 스택을 통해 노출된 출력을 반환합니다.

**Topics**
+ [1단계: 로컬 시스템의 중첩 스택에 대한 템플릿 생성](#create-a-nested-stack-template)
+ [2단계: 로컬 시스템의 최상위 스택에 대한 템플릿 생성](#create-a-nested-stack-parent-template)
+ [3단계: 템플릿 패키징 및 배포](#create-a-nested-stack-parent-template)

### 1단계: 로컬 시스템의 중첩 스택에 대한 템플릿 생성
<a name="create-a-nested-stack-template"></a>

다음 예제에서는 중첩 스택 템플릿의 형식을 보여줍니다.

#### YAML
<a name="nested-stack-child-example.yaml"></a>

```
 1. AWSTemplateFormatVersion: 2010-09-09
 2. Description: Nested stack template for Lambda function deployment
 3. Parameters:
 4.   MemorySize:
 5.     Type: Number
 6.     Default: 128
 7.     MinValue: 128
 8.     MaxValue: 10240
 9.     Description: Lambda function memory allocation (128-10240 MB)
10. Resources:
11.   LambdaFunction:
12.     Type: AWS::Lambda::Function
13.     Properties:
14.       FunctionName: !Sub "${AWS::StackName}-Function"
15.       Runtime: nodejs18.x
16.       Handler: index.handler
17.       Role: !GetAtt LambdaExecutionRole.Arn
18.       Code:
19.         ZipFile: |
20.           exports.handler = async (event) => {
21.             return {
22.               statusCode: 200,
23.               body: JSON.stringify('Hello from Lambda!')
24.             };
25.           };
26.       MemorySize: !Ref MemorySize
27.   LambdaExecutionRole:
28.     Type: AWS::IAM::Role
29.     Properties:
30.       AssumeRolePolicyDocument:
31.         Version: '2012-10-17'
32.         Statement:
33.           - Effect: Allow
34.             Principal:
35.               Service: lambda.amazonaws.com
36.             Action: sts:AssumeRole
37.       ManagedPolicyArns:
38.         - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
39. Outputs:
40.   LambdaArn:
41.     Description: ARN of the created Lambda function
42.     Value: !GetAtt LambdaFunction.Arn
```

### 2단계: 로컬 시스템의 최상위 스택에 대한 템플릿 생성
<a name="create-a-nested-stack-parent-template"></a>

다음 예제에서는 최상위 스택 템플릿의 형식과 이전 단계에서 생성한 스택을 참조하는 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-stack.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-stack.html) 리소스를 보여줍니다.

#### YAML
<a name="nested-stack-parent-example.yaml"></a>

```
 1. AWSTemplateFormatVersion: 2010-09-09
 2. Description: Top-level stack template that deploys a nested stack
 3. Resources:
 4.   NestedStack:
 5.     Type: AWS::CloudFormation::Stack
 6.     Properties:
 7.       TemplateURL: /path_to_template/nested-template.yaml
 8.       Parameters:
 9.         MemorySize: 256
10. Outputs:
11.   NestedStackLambdaArn:
12.     Description: ARN of the Lambda function from nested stack
13.     Value: !GetAtt NestedStack.Outputs.LambdaArn
```

### 3단계: 템플릿 패키징 및 배포
<a name="create-a-nested-stack-parent-template"></a>

**참고**  
로컬에서 템플릿으로 작업할 때 AWS CLI **package** 명령을 사용하면 배포를 위한 템플릿을 준비하는 데 도움이 될 수 있습니다. 이는 Amazon S3(`TemplateURL` 포함)에 대한 로컬 아티팩트 업로드를 자동으로 처리하고 이러한 S3 위치에 대한 업데이트된 참조가 있는 새 템플릿 파일을 생성합니다. 자세한 내용은 [AWS CLI를 사용하여 S3 버킷에 로컬 아티팩트 업로드](using-cfn-cli-package.md) 섹션을 참조하세요.

그런 다음 [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) 명령을 사용하여 중첩된 템플릿을 Amazon S3 버킷에 업로드할 수 있습니다.

```
aws cloudformation package \
  --s3-bucket amzn-s3-demo-bucket \
  --template /path_to_template/top-level-template.yaml \
  --output-template-file packaged-template.yaml \
  --output json
```

명령은 `--output-template-file`에 지정된 경로에서 새 템플릿을 생성합니다. 이는 아래와 같이 `TemplateURL` 참조를 Amazon S3 위치로 바꿉니다.

**결과 템플릿**

```
AWSTemplateFormatVersion: 2010-09-09
Description: Top-level stack template that deploys a nested stack
Resources:
  NestedStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: https://s3.us-west-2.amazonaws.com/amzn-s3-demo-bucket/8b3bb7aa7abfc6e37e2d06b869484bed.template
      Parameters:
        MemorySize: 256
Outputs:
  NestedStackLambdaArn:
    Description: ARN of the Lambda function from nested stack
    Value:
      Fn::GetAtt:
      - NestedStack
      - Outputs.LambdaArn
```

**package** 명령을 실행한 후 [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deploy/](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deploy/) 명령을 사용하여 처리된 템플릿을 배포할 수 있습니다. IAM 리소스를 포함하는 중첩 스택의 경우 `--capabilities` 옵션을 포함하여 IAM 기능을 승인해야 합니다.

```
aws cloudformation deploy \
  --template-file packaged-template.yaml \
  --stack-name stack-name \
  --capabilities CAPABILITY_NAMED_IAM
```

## 중첩 스택에서 스택 작업 수행
<a name="perform-stack-operations-on-nested-stacks"></a>

중첩 스택으로 작업할 때는 작업 중에 신중하게 처리해야 합니다. 스택 업데이트와 같은 특정 스택 작업은 중첩 스택에서 직접 수행하는 것이 아니라 루트 스택에서 시작해야 합니다. 루트 스택을 업데이트하면 템플릿 변경 사항이 있는 중첩 스택만 업데이트됩니다.

추가로 중첩 스택의 존재가 루트 스택의 작업에 영향을 미칠 수 있습니다. 예를 들어 중첩 스택 하나가 `UPDATE_ROLLBACK_IN_PROGRESS` 상태로 멈춘 경우 루트 스택은 해당 중첩 스택이 롤백을 완료할 때까지 기다렸다가 계속 진행합니다. 업데이트 작업을 진행하기 전에 롤백 시 스택 업데이트를 취소할 수 있는 IAM 권한이 있는지 확인합니다. 자세한 내용은 [AWS Identity and Access Management를 사용하여 CloudFormation 액세스 제어](control-access-with-iam.md) 섹션을 참조하세요.

다음 절차를 사용하여 루트 스택과 중첩 스택을 찾습니다.

**중첩 스택의 루트 스택을 보려면**

1. AWS Management Console에 로그인하여 [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/)에서 CloudFormation 콘솔을 엽니다.

1. **스택** 페이지에서 루트 스택을 확인하고자 하는 중첩 스택의 이름을 선택합니다.

   중첩 스택은 스택 이름 위에 **NESTED**가 표시됩니다.

1. **스택 정보** 탭에서 **개요** 섹션의 **루트 스택**으로 나열된 스택 이름을 선택합니다.

**루트 스택에 속한 중첩 스택을 보려면**

1. 중첩 스택을 보려는 루트 스택에서 **리소스** 탭을 선택합니다.

1. **유형** 열에 **AWS::CloudFormation::Stack** 유형의 리소스를 찾습니다.

## 관련 정보
<a name="nested-stacks-related-information"></a>
+ [기존 스택 중첩](resource-import-nested-stacks.md)
+ [스택 리소스의 업데이트 동작 이해](using-cfn-updating-stacks-update-behaviors.md)
+ [실패한 중첩 스택 업데이트에서 계속 롤백](using-cfn-updating-stacks-continueupdaterollback.md#nested-stacks)
+ [중첩 스택 롤백 실패](troubleshooting.md#troubleshooting-errors-nested-stacks-are-stuck)

# CloudFormation 템플릿에서 대기 조건 생성
<a name="using-cfn-waitcondition"></a>

이 주제에서는 템플릿에서 대기 조건을 생성하여 스택 리소스의 생성을 조정하고 구성 프로세스의 진행을 추적하는 방법을 설명합니다. 예를 들어, 애플리케이션 구성이 부분적으로 완료된 후 다른 리소스의 생성을 시작하거나, 설치 및 구성 프로세스 중 신호를 전송하여 진행을 추적할 수 있습니다.

CloudFormation에서 대기 조건이 포함된 스택을 생성하는 경우
+ 다른 리소스와 마찬가지로 대기 조건을 생성하고 대기 조건의 상태를 `CREATE_IN_PROGRESS`로 설정합니다.
+ CloudFormation은 필요한 수의 성공 신호를 수신하거나 대기 조건의 제한 기간이 만료될 때까지 기다립니다.
+ 제한 기간이 만료되기 전에 필요한 수의 성공 신호를 수신하는 경우
  + 대기 조건 상태가 `CREATE_COMPLETE`로 변경됨
  + 스택 생성이 계속됨
+ 제한 시간이 만료되거나 실패 신호가 수신되는 경우
  + 대기 조건 상태가 `CREATE_FAILED`로 변경됨
  + 스택 롤백

**중요**  
Amazon EC2 및 Auto Scaling 리소스의 경우 대기 조건 대신 CreationPolicy 속성을 사용하는 것이 좋습니다. 그러한 리소스에 CreationPolicy 속성을 추가하고 cfn-signal 헬퍼 스크립트를 사용하여 인스턴스 생성 프로세스가 완료되면 신호를 보내도록 합니다.  
자세한 내용은 [CreationPolicy 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-creationpolicy.html)을 참조하세요.

**참고**  
AWS PrivateLink를 사용하는 경우 대기 조건에 응답하는 VPC의 리소스는 CloudFormation의 Amazon Simple Storage Service(Amazon S3) 버킷에 대해 액세스 권한이 있어야 합니다. 리소스는 미리 서명된 Amazon S3 URL로 대기 조건 응답을 보내야 합니다. Amazon S3에 응답을 보내지 못하면 CloudFormation이 응답을 수신하지 않고 스택 작업이 실패합니다. 자세한 내용은 [인터페이스 엔드포인트를 사용하여 CloudFormation에 액세스(AWS PrivateLink)](vpc-interface-endpoints.md) 및 [버킷 정책을 사용하여 VPC 엔드포인트에서 액세스 제어](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies-vpc-endpoint.html)를 참조하세요.

**Topics**
+ [템플릿에서 대기 조건 생성](#creating-wait-condition)
+ [대기 조건 신호 구문](#wait-condition-signal-syntax)
+ [신호 데이터에 액세스](#wait-condition-access-signal-data)

## 템플릿에서 대기 조건 생성
<a name="creating-wait-condition"></a>

**1. 대기 조건 핸들**  
스택의 템플릿에서 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-waitconditionhandle.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-waitconditionhandle.html) 리소스를 정의하는 것으로 시작합니다. 이 리소스는 신호를 보내는 데 필요한 미리 서명된 URL을 생성합니다. 이를 사용하면 AWS 자격 증명을 제공할 필요 없이 신호를 전송할 수 있습니다. 예제: 

```
Resources:
  MyWaitHandle:
    Type: AWS::CloudFormation::WaitConditionHandle
```

**2. 대기 조건**  
다음으로, 스택의 템플릿에서 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-waitcondition.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-waitcondition.html) 리소스를 정의합니다. `AWS::CloudFormation::WaitCondition`의 기본 구조는 다음과 같습니다.

```
  MyWaitCondition:
    Type: AWS::CloudFormation::WaitCondition
    Properties:
      Handle: String
      Timeout: String
      Count: Integer
```

`AWS::CloudFormation::WaitCondition` 리소스에는 2개의 필수 속성과 1개의 선택적 속성이 있습니다.
+ `Handle`(필수) - 템플릿에 선언된 `WaitConditionHandle`에 대한 참조입니다.
+ `Timeout`(필수) - CloudFormation이 필요한 수의 신호를 수신할 때까지 대기하는 시간(초)입니다. `Timeout`은 최소 경계 속성이므로, 제한 시간은 지정한 시간이 되자마자 발생하지만 잠시 후에 발생할 수도 있습니다. 지정할 수 있는 최대 시간은 43,200초(12시간)입니다.
+ `Count`(선택 사항) - CloudFormation이 해당 대기 조건의 상태를 `CREATE_COMPLETE`로 설정하고 스택 생성을 재개하기 전에 수신해야 하는 성공 신호 수입니다. 지정하지 않은 경우 기본값은 1입니다.

일반적으로 특정 리소스가 생성된 직후에 대기 조건이 시작되기를 원합니다. `DependsOn` 속성을 대기 조건에 추가하여 이를 수행할 수 있습니다. 대기 조건에 `DependsOn` 속성을 추가하면 CloudFormation은 먼저 `DependsOn` 속성에 리소스를 생성한 다음 대기 조건을 생성합니다. 자세한 내용은 [DependsOn 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-dependson.html)을 참조하세요.

다음 예제는 다음과 같은 대기 조건을 보여줍니다.
+ `MyEC2Instance` 리소스가 성공적으로 생성된 후 시작
+ `WaitConditionHandle`로 `MyWaitHandle` 리소스 사용
+ 제한 시간 4,500초
+ 기본 `Count` 1(`Count` 속성이 지정되지 않았기 때문)

```
  MyWaitCondition:
    Type: AWS::CloudFormation::WaitCondition
    DependsOn: MyEC2Instance
    Properties:
      Handle: !Ref MyWaitHandle
      Timeout: '4500'
```

**3. 신호 전송**  
CloudFormation에 성공 또는 실패를 알리기 위해 일반적으로 일부 코드 또는 스크립트를 실행합니다. 예를 들어 EC2 인스턴스에서 실행되는 애플리케이션은 몇 가지 추가 구성 태스크를 수행한 다음 CloudFormation에 완료를 나타내는 신호를 전송할 수 있습니다.

대기 조건 핸들에 의해 생성된 미리 서명된 URL로 신호가 전송되어야 합니다. 미리 서명된 URL을 사용하여 성공 또는 실패를 알립니다.

**신호를 전송하려면 다음을 수행하세요.**

1. 템플릿 내에서 미리 서명된 URL을 검색하려면 대기 조건 핸들의 논리명과 함께 `Ref` 내장 함수를 사용합니다.

   다음 예제와 같이 템플릿은 Amazon EC2 `UserData` 속성을 사용하여 Amazon EC2 인스턴스를 선언하고 미리 서명된 URL을 Amazon EC2 인스턴스에 전달할 수 있습니다. 이를 통해 해당 인스턴스에서 실행되는 스크립트 또는 애플리케이션이 CloudFormation에 성공 또는 실패를 알릴 수 있습니다.

   ```
     MyEC2Instance:
       Type: AWS::EC2::Instance
       Properties:
       InstanceType: t2.micro  # Example instance type
       ImageId: ami-055e3d4f0bbeb5878  # Change this as needed (Amazon Linux 2023 in us-west-2)
       UserData:
         Fn::Base64: 
           Fn::Join: 
             - ""
             - - "SignalURL="
               - { "Ref": "MyWaitHandle" }
   ```

   결과로 다음과 유사한 `UserData` 출력이 반환됩니다.

   ```
   SignalURL=https://amzn-s3-demo-bucket.s3.amazonaws.com/....
   ```

   참고: AWS Management Console 및 명령줄 도구에서 미리 서명된 URL은 대기 조건 핸들 리소스의 물리적 ID로 표시됩니다.

1. (선택 사항) 스택이 대기 조건에 들어가는 시점을 감지하려면 다음 방법 중 하나를 사용합니다.
   + 알림이 활성화된 상태로 스택을 생성하면 CloudFormation은 모든 스택 이벤트에 대한 알림을 지정된 주제에 게시합니다. 사용자나 사용자의 애플리케이션이 해당 주제를 구독하는 경우 알림에서 대기 조건 핸들 행성 이벤트를 모니터링하고 알림 메시지에서 미리 서명된 URL을 가져올 수 있습니다.
   + AWS Management Console, AWS CLI 또는 SDK를 사용하여 스택의 이벤트를 모니터링할 수도 있습니다.

1. 신호를 전송하려면 미리 서명된 URL을 사용하여 HTTP 요청 메시지를 전송합니다. 요청 메서드는 `PUT`이어야 하며 `Content-Type` 헤더는 빈 문자열이거나 생략되어야 합니다. 요청 메시지는 [대기 조건 신호 구문](#wait-condition-signal-syntax)에 지정된 형식의 JSON 구조여야 합니다.

   CloudFormation에서 스택 생성을 계속하려면 `Count` 속성으로 지정된 수의 성공 신호를 전송해야 합니다. `Count`이(가) 1보다 큰 경우 특정 대기 조건에 전송된 모든 신호에서 각 신호의 `UniqueId` 값이 고유해야 합니다. `UniqueId`은(는) 임의의 영숫자 문자열입니다.

   `curl` 명령은 신호를 전송하는 한 가지 방법입니다. 다음 예에서는 대기 조건에 성공 신호를 전송하는 `curl` 명령줄을 보여 줍니다.

   ```
   $ curl -T /tmp/a \
     "https://amzn-s3-demo-bucket.s3.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-west-2%3A034017226601%3Astack%2Fstack-gosar-20110427004224-test-stack-with-WaitCondition--VEYW%2Fe498ce60-70a1-11e0-81a7-5081d0136786%2FmyWaitConditionHandle?Expires=1303976584&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Signature=ik1twT6hpS4cgNAw7wyOoRejVoo%3D"
   ```

   이때 *`/tmp/a`* 파일에는 다음과 같은 JSON 구조가 포함되어 있습니다.

   ```
   {
      "Status" : "SUCCESS",
      "Reason" : "Configuration Complete",
      "UniqueId" : "ID1234",
      "Data" : "Application has completed configuration."
   }
   ```

   이 예에서는 명령줄에서 JSON 구조를 파라미터로 전송하는 경우를 제외하고 동일한 성공 신호를 전송하는 `curl` 명령줄을 보여줍니다.

   ```
   $ curl -X PUT \
     -H 'Content-Type:' --data-binary '{"Status" : "SUCCESS","Reason" : "Configuration Complete","UniqueId" : "ID1234","Data" : "Application has completed configuration."}' \
     "https://amzn-s3-demo-bucket.s3.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-west-2%3A034017226601%3Astack%2Fstack-gosar-20110427004224-test-stack-with-WaitCondition--VEYW%2Fe498ce60-70a1-11e0-81a7-5081d0136786%2FmyWaitConditionHandle?Expires=1303976584&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Signature=ik1twT6hpS4cgNAw7wyOoRejVoo%3D"
   ```

## 대기 조건 신호 구문
<a name="wait-condition-signal-syntax"></a>

대기 조건 핸들에 의해 생성된 URL로 신호를 전송할 때는 다음 JSON 형식을 사용해야 합니다.

```
{
  "Status" : "StatusValue",
  "UniqueId" : "Some UniqueId",
  "Data" : "Some Data",
  "Reason" : "Some Reason"
}
```

### 속성
<a name="wait-condition-signal-properties"></a>

`Status` 필드는 다음 값 중 하나여야 합니다.
+ `SUCCESS`
+ `FAILURE`

`UniqueId` 필드는 CloudFormation에 대한 신호를 식별합니다. 대기 조건의 `Count` 속성이 1보다 큰 경우 `UniqueId` 값은 특정 대기 조건에 대해 전송된 모든 신호에서 고유해야 합니다. 그렇지 않으면 CloudFormation은 신호를 동일한 `UniqueId`로 이전에 전송된 신호를 재전송한 것으로 간주하고 무시합니다.

`Data` 필드에는 신호와 함께 다시 전송하려는 모든 정보가 포함될 수 있습니다. 템플릿 내에서 [Fn::GetAtt](resources-section-structure.md#resource-properties-getatt) 함수를 사용하여 `Data` 값에 액세스할 수 있습니다.

`Reason` 필드는 콘텐츠에 대해 JSON 규정 이외의 다른 제한 사항이 없는 문자열입니다.

## 신호 데이터에 액세스
<a name="wait-condition-access-signal-data"></a>

유효한 신호에서 전송된 데이터에 액세스하려면 CloudFormation 템플릿에서 대기 조건에 대한 출력 값을 생성할 수 있습니다. 예제:

```
Outputs:
  WaitConditionData:
    Description: The data passed back as part of signalling the WaitCondition
    Value: !GetAtt MyWaitCondition.Data
```

그런 다음 [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-stacks.html) 명령이나 CloudFormation 콘솔의 **출력** 탭을 사용하여 이 데이터를 볼 수 있습니다.

`Fn::GetAtt` 함수는 `UniqueId`와 `Data`를 JSON 구조 내 이름/값 페어로 반환합니다. 예제:

```
{"Signal1":"Application has completed configuration."}
```

# CloudFormation 모듈을 사용하여 템플릿 전체에 포함할 수 있는 재사용 가능한 리소스 구성 생성
<a name="modules"></a>

*모듈*을 사용하면 모든 스택 템플릿에 포함하기 위한 리소스 구성을 투명하고 관리가 편리하면서도 반복적으로 패키징할 수 있습니다. 모듈은 공통적 서비스 구성과 모범 사례를 모듈식 맞춤형 구성 요소로 캡슐화하고 스택 템플릿에 포함할 수 있습니다. 모듈을 사용하면 리소스 구성을 포함할 수 있습니다. 리소스 구현에 대한 복잡한 지식을 심층적으로 배우지 않더라도 리소스 구성을 통해 모범 사례, 전문가 영역 지식, 허용되는 가이드라인(보안, 규정 준수, 거버넌스, 산업 규정 등의 분야)을 템플릿에 포함할 수 있습니다.

예를 들어 네트워킹 영역 전문가는 기본 보안 그룹과 보안 가이드라인을 준수하는 수신/송신 규칙이 포함된 모듈을 만들 수 있습니다. 그런 다음, 템플릿에 모듈을 포함하여 스택에 보안 네트워킹 인프라를 프로비저닝할 수 있습니다. VPC, 서브넷, 보안 그룹, 게이트웨이의 작동 원리를 배우지 않아도 됩니다. 모듈에 버전이 지정되기 때문에 시간이 지나서 보안 가이드라인이 변경될 경우, 모듈 작성자는 이런 변경 사항을 통합하는 새 버전의 모듈을 만들 수 있습니다.

템플릿에서 모듈을 사용하는 방법의 특징은 다음과 같습니다.
+ **예측 가능성** - 모듈은 CloudFormation 레지스트리에 등록하는 스키마를 준수해야 합니다. 그래야 템플릿에 모듈을 포함한 후 어떤 리소스를 해석할 수 있는지 알 수 있습니다.
+ **재사용 가능성** - 여러 템플릿과 계정에서 동일한 모듈을 사용할 수 있습니다.
+ **추적 가능성** - CloudFormation은 모듈에서 스택의 어떤 리소스가 프로비저닝되었는지 알고 있으므로, 리소스 변경 사항의 소스를 쉽게 이해할 수 있습니다.
+ **관리 용이성** - 모듈에 등록하고 나면 버전 관리, 계정 및 리전 가용성을 포함하여 CloudFormation 레지스트리를 통해 모듈을 관리할 수 있습니다.

모듈에는 다음을 포함할 수 있습니다.
+ 모듈에서 프로비저닝되는 하나 이상의 리소스 및 관련 데이터(예: 출력, 조건).
+ 모듈 파라미터(모듈을 사용할 때마다 사용자 지정 값을 지정할 수 있게 됩니다).

모듈 개발에 대한 자세한 내용은 *CloudFormation CLI User Guide*의 [Developing modules](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/modules.html)를 참조하세요.

**Topics**
+ [모듈 사용 시 고려 사항](#module-considerations)
+ [모듈 버전 관리 이해](module-versioning.md)
+ [CloudFormation 프라이빗 레지스트리의 모듈 사용](modules-using.md)
+ [파라미터를 사용하여 모듈 값 지정](module-using-params.md)
+ [CloudFormation 템플릿의 모듈 리소스 참조](module-ref-resources.md)

## 모듈 사용 시 고려 사항
<a name="module-considerations"></a>
+ 모듈을 사용하더라도 추가 요금은 없습니다. 모듈이 스택에서 해석하는 리소스에 대해서만 요금을 지불합니다.
+ CloudFormation 할당량(스택에 허용되는 리소스의 최대 개수, 템플릿 본문의 최대 크기)을 처리된 템플릿에 적용합니다. 이는 해당 템플릿에 포함된 리소스가 모듈의 리소스인지 여부와는 관계가 없습니다. 자세한 내용은 [CloudFormation 할당량 이해](cloudformation-limits.md) 섹션을 참조하세요.
+ 스택 수준에서 지정하는 태그는 모듈에서 파생된 각 리소스에 할당됩니다.
+ CloudFormation이 템플릿을 처리할 때 모듈 수준에서 지정된 도우미 스크립트는 모듈에 포함된 개별 리소스로 전달되지 않습니다.
+ 모듈에 지정된 출력은 템플릿 수준의 출력에 전달됩니다.

  각 출력에는 모듈의 논리적 이름과 모듈에 정의된 출력 이름을 연결하는 논리적 ID가 할당됩니다. 자세한 내용은 [배포된 CloudFormation 스택에서 내보낸 출력 가져오기](using-cfn-stack-exports.md) 섹션을 참조하세요.
+ 모듈에 지정된 파라미터는 템플릿 수준의 파라미터에 전달되지 않습니다.

  그러나 모듈 수준 파라미터를 참조하는 템플릿 수준 파라미터를 생성할 수 있습니다. 자세한 내용은 [파라미터를 사용하여 모듈 값 지정](module-using-params.md) 섹션을 참조하세요.

# 모듈 버전 관리 이해
<a name="module-versioning"></a>

CloudFormation 레지스트리는 AWS 계정과 리전 내에서 사용할 모듈을 등록하고 관리할 수 있는 리포지토리 역할을 합니다. 계정과 리전 내에서 AWS, 서드 파티 게시자 및 사용자 지정 확장 프로그램을 포함한 다양한 소스의 모듈을 등록할 수 있습니다. 자세한 내용은 [CloudFormation 레지스트리를 통해 익스텐션 관리](registry.md) 섹션을 참조하세요.

모듈에는 여러 버전이 있을 수 있으므로 사용하려는 모듈의 버전을 지정할 수 있습니다. 이 버전 관리 기능은 모듈에 종속된 기존 스택을 손상시키지 않고 모듈을 업데이트하거나 수정해야 할 때 특히 유용합니다.

여러 버전의 모듈을 사용할 때는 다음 고려 사항에 유의하세요.
+ 스택 작업 중 CloudFormation은 현재 스택 작업이 수행되는 AWS 계정과 리전에 기본 버전으로 등록된 모듈 버전을 사용합니다. 여기에는 다른 모듈에 중첩된 모듈이 포함됩니다.

  따라서 다른 계정이나 리전에 동일한 모듈의 다른 버전이 기본 버전으로 등록되어 있는 경우 같은 템플릿을 사용하더라도 결과가 다를 수 있습니다.
+ 스택 작업 중에 CloudFormation은 현재 스택 작업이 수행되는 AWS 계정과 리전에 기본 버전으로 등록된 리소스 버전을 사용합니다. 여기에는 모듈을 포함하여 생성된 리소스가 포함됩니다.
+ 모듈의 기본 버전을 바꾸더라도 스택 업데이트 작업이 시작되지 않습니다. 그러나 다음에 해당 모듈을 포함하는 템플릿으로 스택 작업을 실행할 경우(예: 스택 업데이트) CloudFormation은 작업에 새 기본 버전을 사용합니다.

  한 가지 예외는 **이전 템플릿 사용** 옵션을 지정한 스택 업데이트입니다. 자세한 내용은 아래에 설명되어 있습니다.
+ 스택 업데이트 작업에서 **이전 템플릿 사용** 옵션을 지정할 경우, CloudFormation은 이전에 스택 업데이트에서 처리된 템플릿을 사용하고 변경 사항에 대해 모듈을 다시 처리하지 않습니다.
+ 일관된 결과를 보장하려면 스택 세트와 함께 사용할 스택 템플릿에 모듈을 포함할 경우 스택 인스턴스를 배포하고자 하는 모든 계정과 리전에서 동일한 모듈 버전을 기본 버전으로 설정해야 합니다. 여기에는 다른 모듈에 중첩된 모듈의 버전도 포함됩니다. 자세한 내용은 [StackSets를 사용하여 여러 계정 및 리전의 스택 관리](what-is-cfnstacksets.md) 섹션을 참조하세요.

## 서드 파티 퍼블릭 모듈 활성화를 위한 요구 사항
<a name="requirements-for-modules"></a>

계정 및 리전에서 서드 파티 퍼블릭 모듈을 성공적으로 활성화하려면 모듈에 포함된 각 서드 파티 공개 확장 프로그램(리소스 또는 모듈)에 대해 다음 조건이 충족되어야 합니다.
+ **확장 프로그램 활성화** - 확장 프로그램을 사용하려는 계정과 리전에서 확장 프로그램을 활성화해야 합니다. 자세한 내용은 [CloudFormation 레지스트리에서 서드 파티 공개 확장 프로그램 사용](registry-public.md) 섹션을 참조하세요.
+ **별칭 등록** - 모듈의 확장 프로그램이 유형 이름 별칭을 사용하는 경우 확장 프로그램은 동일한 유형 이름 별칭을 사용하여 계정과 리전에 등록되어야 합니다. 자세한 내용은 [별칭을 사용하여 확장 프로그램 참조](registry-public.md#registry-public-enable-alias) 섹션을 참조하세요.
+ **버전 호환성** - 현재 활성화된 확장 프로그램 버전은 모듈에 지정된 해당 확장 프로그램의 지원되는 메이저 버전 중 하나여야 합니다.

올바른 서드 파티 공개 확장 프로그램 및 확장 프로그램 버전을 활성화하지 않은 경우 CloudFormation은 모듈을 성공적으로 활성화하기 전에 활성화해야 하는 확장 프로그램과 버전을 나열하는 오류와 함께 작업에 실패합니다.

# CloudFormation 프라이빗 레지스트리의 모듈 사용
<a name="modules-using"></a>

이 주제에서는 CloudFormation 템플릿에서 모듈을 사용하는 방법을 설명합니다. 모듈은 템플릿에 추가할 수 있는 미리 만들어진 리소스 번들이라고 생각하면 됩니다.

모듈을 사용하려면 다음 단계를 수행하세요.
+ **모듈 등록** - CloudFormation 레지스트리에 모듈을 비공개 확장 프로그램으로 등록할 수 있습니다. 작업 중인 AWS 계정과 리전에 모듈이 등록되어 있는지 확인하세요. 자세한 내용은 [CloudFormation 레지스트리 개념](registry-concepts.md) 섹션을 참조하세요.
+ **템플릿에 포함** - 다른 리소스와 마찬가지로 CloudFormation 템플릿의 [Resources](resources-section-structure.md) 섹션에 모듈을 추가합니다. 모듈에 필요한 속성도 제공해야 합니다.
+ **스택 생성 또는 업데이트** - 스택 작업을 시작하면 CloudFormation이 처리된 템플릿을 생성합니다. 이 템플릿은 포함된 모듈을 적절한 리소스로 해석합니다.
+ **변경 사항 미리 보기** - 변경하기 전에 변경 세트를 사용하여 추가 또는 변경될 리소스를 확인할 수 있습니다. 자세한 내용은 [변경 세트를 사용하여 CloudFormation 스택 업데이트](using-cfn-updating-stacks-changesets.md) 섹션을 참조하세요.

리소스와 모듈을 모두 포함한 템플릿을 예시로 생각해 보세요. 템플릿에는 개별 리소스(`ResourceA`)와 모듈(`ModuleParent`)이 포함되어 있습니다. 이 모듈에는 `ResourceB` 및 `ResourceC` 리소스는 물론 중첩된 모듈인 `ModuleChild`가 포함되어 있습니다. `ModuleChild`에는 단일 리소스인 `ResourceD`가 포함되어 있습니다. 이 템플릿에서 스택을 생성하면 CloudFormation이 템플릿을 처리하고 모듈을 적절한 리소스로 해석합니다. 결과로 나오는 스택에는 `ResourceA`, `ResourceB`, `ResourceC`, `ResourceD`라는 4개의 리소스가 있습니다.

![\[스택 작업 중에 CloudFormation이 스택 템플릿에 포함된 모듈 2개를 적절한 리소스 4개로 해석합니다.\]](http://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/images/modules-resource-inclusion.png)


CloudFormation은 스택의 어떤 리소스가 모듈에서 생성되었는지 추적합니다. [**이벤트**], [**리소스**], [**드리프트**] 탭에서 지정된 스택에 대한 정보를 확인할 수 있으며, 이는 변경 세트 미리 보기에도 포함됩니다.

모듈은 템플릿의 리소스와 구별됩니다. 리소스는 일반적으로 세 부분으로 구성된 규칙을 준수하는 것과 달리, 모듈은 네 부분으로 구서된 이름 지정 규칙을 준수하기 때문입니다.

```
organization::service::use-case::MODULE
```

# 파라미터를 사용하여 모듈 값 지정
<a name="module-using-params"></a>

CloudFormation에서 템플릿 파라미터로 스택 생성 또는 업데이트 중 입력 값을 제공하여 스택을 사용자 지정할 수 있습니다. 이러한 파라미터를 사용하면 필요에 따라 스택의 특정 측면을 변경할 수 있습니다. 템플릿 파라미터 정의에 대한 자세한 내용은 [CloudFormation 템플릿 Parameters 구문](parameters-section-structure.md) 섹션을 참조하세요.

마찬가지로 모듈에도 파라미터가 있을 수 있습니다. 이러한 모듈 파라미터를 사용하면 해당 모듈을 사용하는 템플릿 또는 다른 모듈에서 모듈에 사용자 지정 값을 입력할 수 있습니다. 그런 다음 모듈은 이러한 사용자 지정 값을 사용하여 포함된 리소스의 속성 값을 설정할 수 있습니다.

또한 스택 작업 시 모듈에 전달되는 값을 입력할 수 있도록 모듈 속성을 설정하는 템플릿 파라미터를 정의할 수 있습니다.

모듈에 자체 모듈 파라미터가 있는 중첩 모듈이 있는 경우 다음 중 하나를 수행할 수 있습니다.
+ 중첩 모듈 파라미터에 대한 값을 상위 모듈에 직접 지정합니다.
+ 상위 모듈에서 해당 모듈 파라미터를 정의합니다. 상위 모듈이 포함된 템플릿(또는 모듈)에서 중첩 모듈 파라미터를 설정할 수 있습니다.

## 템플릿 파라미터를 사용하여 모듈 파라미터 값 지정
<a name="module-using-params-example-1"></a>

다음 예제는 값을 모듈에 전달하는 템플릿 파라미터를 정의하는 방법을 나타냅니다.

`My::S3::SampleBucket::MODULE`을 포함하는 이 템플릿은 사용자가 스택 작업 중 S3 버킷 이름을 지정할 수 있는 템플릿 파라미터인 `BucketName`을 정의합니다.

```
# Template containing My::S3::SampleBucket::MODULE
Parameters:
  BucketName:
    Description: Name for your sample bucket
    Type: String
Resources:
  MyBucket:
    Type: 'My::S3::SampleBucket::MODULE'
    Properties:
      BucketName: !Ref BucketName
```

## 상위 모듈에서 하위 모듈의 리소스에 대한 속성 지정
<a name="module-using-params-example-2"></a>

다음 예제는 다른 모듈 안에 중첩된 모듈에서 파라미터 값을 지정하는 방법을 나타냅니다.

이 첫 번째 모듈 `My::S3::SampleBucketPrivate::MODULE`이 하위 모듈이 됩니다. 이 하위 모듈이 파라미터 2개(`BucketName`과 `AccessControl`)를 정의합니다. 두 가지 파라미터에 지정된 값을 사용하여 모듈에 포함된 `AWS::S3::Bucket` 리소스의 `BucketName`과 `AccessControl`을 지정합니다. 다음의 `My::S3::SampleBucketPrivate::MODULE`에 대한 템플릿 프래그먼트입니다.

```
# My::S3::SampleBucketPrivate::MODULE
AWSTemplateFormatVersion: 2010-09-09
Description: A sample S3 Bucket with Versioning and DeletionPolicy.
Parameters:
  BucketName:
    Description: Name for the bucket
    Type: String
  AccessControl:
    Description: AccessControl for the bucket
    Type: String
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref BucketName
      AccessControl: !Ref AccessControl
      DeletionPolicy: Retain
      VersioningConfiguration:
        Status: Enabled
```

그 다음에는 이전 모듈이 상위 모듈 `My::S3::SampleBucket::MODULE`에 중첩됩니다. 상위 모듈 `My::S3::SampleBucket::MODULE`은 다음과 같은 방법으로 하위 모듈 파라미터를 설정합니다.
+ `My::S3::SampleBucketPrivate::MODULE`의 `AccessControl` 파라미터를 `Private`으로 설정합니다.
+ `BucketName`은 모듈 파라미터를 정의합니다. `My::S3::SampleBucket::MODULE`을 포함하는 템플릿(또는 모듈)에서 버킷 이름을 지정할 수 있게 됩니다.

```
# My::S3::SampleBucket::MODULE
AWSTemplateFormatVersion: 2010-09-09
Description: A sample S3 Bucket. With Private AccessControl.
Parameters:
  BucketName:
    Description: Name for your sample bucket
    Type: String
Resources:
  MyBucket:
    Type: 'My::S3::SampleBucketPrivate::MODULE'
    Properties:
      BucketName: !Ref BucketName
      AccessControl: Private
```

## 모듈 파라미터에 대한 제약 조건 지정
<a name="modules-using-parameters-constraints"></a>

모듈 파라미터는 제약 조건의 적용을 지원하지 않습니다. 모듈 파라미터에 대해 제약 조건 검사를 실행하려면 원하는 제약 조건으로 템플릿 파라미터를 생성합니다. 그런 다음 모듈 파라미터에서 템플릿 파라미터를 참조합니다. 템플릿 파라미터 정의에 대한 자세한 내용은 [CloudFormation 템플릿 Parameters 구문](parameters-section-structure.md) 섹션을 참조하세요.

# CloudFormation 템플릿의 모듈 리소스 참조
<a name="module-ref-resources"></a>

CloudFormation에서 다른 리소스의 이름이나 속성을 기반으로 한 리소스의 속성을 설정해야 하는 경우가 있습니다. 자세한 내용은 [참조 리소스](resources-section-structure.md#using-cross-resource-references) 섹션을 참조하세요.

CloudFormation 템플릿의 모듈에 포함된 리소스를 참조하려면 두 논리명을 결합해야 합니다.
+ 템플릿에 모듈을 포함할 때 모듈 자체에 지정한 논리명입니다.
+ 해당 모듈 내 특정 리소스의 논리명입니다.

이 두 논리명을 마침표(.)를 사용하거나 사용하지 않고 결합할 수 있습니다. 예를 들어, 모듈의 논리명이 `MyModule`이고 리소스의 논리명이 `MyBucket`인 경우 해당 리소스를 `MyModule.MyBucket` 또는 `MyModuleMyBucket`으로 참조할 수 있습니다.

모듈 내부 리소스의 논리명을 찾으려면 CloudFormation 레지스트리에서 사용할 수 있는 모듈 스키마를 참조하거나 [https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeType.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeType.html) 작업을 사용합니다. 스키마에는 모듈의 일부인 모든 리소스와 해당 논리명이 나열됩니다.

전체 논리명을 알면 `GetAtt` 및 `Ref`와 같은 CloudFormation 함수를 사용하여 모듈 리소스의 속성 값에 액세스할 수 있습니다.

예를 들어, 논리명이 `S3Bucket`인 `AWS::S3::Bucket` 리소스를 포함하는 `My::S3::SampleBucket::MODULE` 모듈이 있다고 가정해 보겠습니다. `Ref` 함수를 사용하여 이 버킷의 이름을 참조하려면 템플릿의 모듈 이름(`MyBucket`)과 모듈의 리소스 논리명(`S3Bucket`)을 결합합니다. 전체 논리명은 `MyBucket.S3Bucket` 또는 `MyBucketS3Bucket`입니다.

**예제 템플릿**  
다음 예 템플릿은 `My::S3::SampleBucket::MODULE` 모듈을 사용하여 S3 버킷을 생성합니다. 또한 Amazon SQS 대기열을 생성하고 해당 이름을 모듈의 버킷 이름과 동일하게 설정합니다. 생성된 S3 버킷의 Amazon 리소스 이름(ARN)도 출력합니다.

```
# Template that uses My::S3::SampleBucket::MODULE
Parameters:
  BucketName:
    Description: Name for your sample bucket
    Type: String
Resources:
  MyBucket:
    Type: My::S3::SampleBucket::MODULE
    Properties:
      BucketName: !Ref BucketName
  exampleQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: !Ref MyBucket.S3Bucket
Outputs:
  BucketArn:
    Value: !GetAtt MyBucket.S3Bucket.Arn
```