

# 스택 간 리소스 이동
<a name="refactor-stacks"></a>

`resource import` 기능을 사용하여 스택간에 리소스를 이동하거나 스택을 *리팩터링*할 수 있습니다. 소스 스택에서 제거한 후 대상 스택으로 가져오기를 할 때 리소스가 보존되도록 하려면 먼저 이동시키려는 리소스에 `Retain` 삭제 정책을 추가해야 합니다.

가져오기를 처음 사용하는 경우 먼저 [CloudFormation 스택에 AWS 리소스 가져오기](import-resources.md) 주제의 소개 정보를 검토하는 것이 좋습니다.

**중요**  
모든 리소스가 가져오기 작업을 지원하는 것은 아닙니다. 스택에서 리소스를 제거하기 전에 [가져오기 작업을 지원하는 리소스](resource-import-supported-resources.md)를 참조하세요. 스택에서 가져오기 작업을 지원하지 않는 리소스를 제거하면 리소스를 다른 스택으로 가져오거나 원본 스택으로 다시 가져올 수 없습니다.

## AWS Management Console을 사용하여 스택 리팩터링
<a name="refactor-stacks-console"></a>

1. 소스 템플릿에서 이동시킬 리소스에 대한 `Retain` [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-deletionpolicy.html)를 지정합니다.

   다음 예제 소스 템플릿에서 `Games`은 이 리팩터의 대상입니다.  
**Example JSON**  

   ```
   {
       "AWSTemplateFormatVersion": "2010-09-09",
       "Description": "Import test",
       "Resources": {
           "ServiceTable":{
              "Type":"AWS::DynamoDB::Table",
              "Properties":{
                 "TableName":"Service",
                 "AttributeDefinitions":[
                    {
                       "AttributeName":"key",
                       "AttributeType":"S"
                    }
                 ],
                 "KeySchema":[
                    {
                       "AttributeName":"key",
                       "KeyType":"HASH"
                    }
                 ],
                 "ProvisionedThroughput":{
                    "ReadCapacityUnits":5,
                    "WriteCapacityUnits":1
                 }
              }
           },
           "GamesTable": {
               "Type": "AWS::DynamoDB::Table",
               "DeletionPolicy": "Retain",
               "Properties": {
                   "TableName": "Games",
                   "AttributeDefinitions": [
                       {
                           "AttributeName": "key",
                           "AttributeType": "S"
                       }
                   ],
                   "KeySchema": [
                       {
                           "AttributeName": "key",
                           "KeyType": "HASH"
                       }
                   ],
                   "ProvisionedThroughput": {
                       "ReadCapacityUnits": 5,
                       "WriteCapacityUnits": 1
                   }
               }
           }
       }
   }
   ```

1. CloudFormation 콘솔을 열어 스택 업데이트를 수행하여 삭제 정책을 적용합니다.

   1. **스택(Stacks)** 페이지에서 스택을 선택하고 **업데이트(Update)**를 선택합니다.

   1. **Prepare template(템플릿 준비)**에서 **Replace current template(현재 템플릿 바꾸기)**을 선택합니다.

   1. **Specify template(템플릿 지정)**에서 `GamesTable`에 `DeletionPolicy` 속성이 설정된 업데이트된 소스 템플릿을 제공한 후, **다음**을 선택합니다.
      + **Amazon S3 URL**을 선택한 다음 텍스트 상자에 업데이트된 소스 템플릿의 URL을 지정합니다.
      + **템플릿 파일 업로드**를 선택한 다음 업데이트된 소스 템플릿 파일을 찾습니다.

   1. **Specify stack details(스택 세부 정보 지정)** 페이지에서 어떤 변경도 필요하지 않습니다. **다음**을 선택합니다.

   1. **Configure stack options(스택 옵션 구성)** 페이지에서 어떤 변경도 필요하지 않습니다. **다음**을 선택합니다.

   1. ***SourceStackName* 검토** 페이지에서 변경 사항을 검토합니다. 템플릿에 IAM 리소스가 포함되어 있는 경우 **이 템플릿이 IAM 리소스를 생성할 수 있음을 확인합니다**(I acknowledge that this template may create IAM resources)를 선택하여 템플릿에서 IAM 리소스를 사용하도록 지정합니다. 템플릿에서 IAM 리소스를 사용하는 방법에 대한 자세한 내용은 [AWS Identity and Access Management를 사용하여 CloudFormation 액세스 제어](control-access-with-iam.md) 단원을 참조하십시오. 그런 다음 변경 세트를 생성하여 소스 스택을 업데이트하거나 소스 스택을 직접 업데이트하십시오.

1. 소스 템플릿에서 리소스, 관련 파라미터 및 출력을 제거한 다음, 이들을 대상 템플릿에 추가합니다.

   이제 소스 템플릿이 다음과 같이 보입니다.  
**Example JSON**  

   ```
   {
       "AWSTemplateFormatVersion": "2010-09-09",
       "Description": "Import test",
       "Resources": {
           "ServiceTable":{
              "Type":"AWS::DynamoDB::Table",
              "Properties":{
                 "TableName":"Service",
                 "AttributeDefinitions":[
                    {
                       "AttributeName":"key",
                       "AttributeType":"S"
                    }
                 ],
                 "KeySchema":[
                    {
                       "AttributeName":"key",
                       "KeyType":"HASH"
                    }
                 ],
                 "ProvisionedThroughput":{
                    "ReadCapacityUnits":5,
                    "WriteCapacityUnits":1
                 }
              }
           }
       }
   }
   ```

   현재 다음과 같은 예제 대상 템플릿에는 `PlayersTable` 리소스가 있으며 `GamesTable`도 포함되어 있습니다.  
**Example JSON**  

   ```
   {
       "AWSTemplateFormatVersion": "2010-09-09",
       "Description": "Import test",
       "Resources": {
           "PlayersTable": {
               "Type": "AWS::DynamoDB::Table",
               "Properties": {
                   "TableName": "Players",
                   "AttributeDefinitions": [
                       {
                           "AttributeName": "key",
                           "AttributeType": "S"
                       }
                   ],
                   "KeySchema": [
                       {
                           "AttributeName": "key",
                           "KeyType": "HASH"
                       }
                   ],
                   "ProvisionedThroughput": {
                       "ReadCapacityUnits": 5,
                       "WriteCapacityUnits": 1
                   }
               }
           },
           "GamesTable": {
               "Type": "AWS::DynamoDB::Table",
               "DeletionPolicy": "Retain",
               "Properties": {
                   "TableName": "Games",
                   "AttributeDefinitions": [
                       {
                           "AttributeName": "key",
                           "AttributeType": "S"
                       }
                   ],
                   "KeySchema": [
                       {
                           "AttributeName": "key",
                           "KeyType": "HASH"
                       }
                   ],
                   "ProvisionedThroughput": {
                       "ReadCapacityUnits": 5,
                       "WriteCapacityUnits": 1
                   }
               }
           }
       }
   }
   ```

1. 2\$13단계를 반복하여 소스 스택을 다시 업데이트합니다. 이번에는 대상 리소스를 스택에서 삭제합니다.

1. 가져오기 작업을 수행하여 대상 스택에 `GamesTable`을 추가합니다.

   1. **스택** 페이지에서 상위 스택을 선택한 상태에서 **Stack actions(스택 작업)**를 선택한 다음 **Import resources into stack(스택으로 리소스 가져오기)**을 선택합니다.   
![\[콘솔의 스택으로 리소스 가져오기 옵션.\]](http://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/images/stack-actions-import.png)

   1. 이 작업 중에 제공해야 하는 항목 목록은 **Import overview(가져오기 개요)** 페이지를 참조하십시오. 그리고 **다음**을 선택합니다.

   1. **Specify template**(템플릿 지정) 페이지에서 다음 중 하나를 완료한 후 **Next**(다음)를 선택합니다.
      + **Amazon S3 URL**을 선택한 다음, 텍스트 상자에 URL을 지정합니다.
      + **템플릿 파일 업로드**를 선택한 다음 업로드할 파일을 찾습니다.

   1. **Identify resources(리소스 식별)** 페이지에서 이동 중인 리소스를 식별합니다(이 예제에서는 `GamesTable`). 자세한 내용은 [리소스 식별자](import-resources-manually.md#resource-import-identifiers-unique-ids) 섹션을 참조하세요.

      1. **Identifier property(식별자 속성)**에서 리소스 식별자의 유형을 선택합니다. 예를 들어 `AWS::DynamoDB::Table` 리소스는 `TableName` 속성을 사용하여 식별할 수 있습니다.

      1. **Identifier value(식별자 값)**에서 실제 속성값을 입력합니다. 예를 들어 `GamesTables`입니다.

      1. **다음**을 선택합니다.

   1. **Specify stack details(스택 세부 정보 지정)** 페이지에서 어떤 파라미터든 수정하고 **다음**을 선택합니다. 이렇게 하면 변경 세트가 자동으로 생성됩니다.
**중요**  
생성, 업데이트 또는 삭제 작업을 시작하는 기존 파라미터를 수정하면 가져오기 작업이 실패합니다.

   1. ***TargetStackName* 검토** 페이지에서 올바른 리소스를 가져오고 있는지 확인한 다음 **리소스 가져오기**를 선택합니다. 그러면 마지막 단계에서 생성된 변경 세트가 자동으로 시작됩니다. 이때 어떤 [스택 레벨 태그](cfn-console-create-stack.md#configure-stack-options)든 가져온 리소스에 적용됩니다.

   1. 상위 스택에 대한 **Stack details**(스택 세부 정보) 페이지의 **Events**(이벤트) 창이 표시됩니다.  
![\[콘솔의 이벤트 탭.\]](http://docs.aws.amazon.com/ko_kr/AWSCloudFormation/latest/UserGuide/images/import-events.png)
**참고**  
`AWS::CloudFormation::Stack` 리소스가 이미 CloudFormation에서 관리되기 때문에 이러한 가져오기 작업을 수행한 후에 상위 스택에서 드리프트 감지를 실행할 필요가 없습니다.

## AWS CLI을 사용하여 스택 리팩터링
<a name="refactor-stacks-cli"></a>

1. 소스 템플릿에서 이동시킬 리소스에 대한 `Retain` [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-attribute-deletionpolicy.html)를 지정합니다.

   다음 예제 소스 템플릿에서 `GamesTable`은 이 리팩터의 대상입니다.  
**Example JSON**  

   ```
   {
       "AWSTemplateFormatVersion": "2010-09-09",
       "Description": "Import test",
       "Resources": {
           "ServiceTable":{
              "Type":"AWS::DynamoDB::Table",
              "Properties":{
                 "TableName":"Service",
                 "AttributeDefinitions":[
                    {
                       "AttributeName":"key",
                       "AttributeType":"S"
                    }
                 ],
                 "KeySchema":[
                    {
                       "AttributeName":"key",
                       "KeyType":"HASH"
                    }
                 ],
                 "ProvisionedThroughput":{
                    "ReadCapacityUnits":5,
                    "WriteCapacityUnits":1
                 }
              }
           },
           "GamesTable": {
               "Type": "AWS::DynamoDB::Table",
               "DeletionPolicy": "Retain",
               "Properties": {
                   "TableName": "Games",
                   "AttributeDefinitions": [
                       {
                           "AttributeName": "key",
                           "AttributeType": "S"
                       }
                   ],
                   "KeySchema": [
                       {
                           "AttributeName": "key",
                           "KeyType": "HASH"
                       }
                   ],
                   "ProvisionedThroughput": {
                       "ReadCapacityUnits": 5,
                       "WriteCapacityUnits": 1
                   }
               }
           }
       }
   }
   ```

1. 소스 스택을 업데이트하여 삭제 정책을 리소스에 적용합니다.

   ```
   aws cloudformation update-stack --stack-name SourceStackName
   ```

1. 소스 템플릿에서 리소스, 관련 파라미터 및 출력을 제거한 다음, 이들을 대상 템플릿에 추가합니다.

   이제 소스 템플릿이 다음과 같이 보입니다.  
**Example JSON**  

   ```
   {
       "AWSTemplateFormatVersion": "2010-09-09",
       "Description": "Import test",
       "Resources": {
           "ServiceTable":{
              "Type":"AWS::DynamoDB::Table",
              "Properties":{
                 "TableName":"Service",
                 "AttributeDefinitions":[
                    {
                       "AttributeName":"key",
                       "AttributeType":"S"
                    }
                 ],
                 "KeySchema":[
                    {
                       "AttributeName":"key",
                       "KeyType":"HASH"
                    }
                 ],
                 "ProvisionedThroughput":{
                    "ReadCapacityUnits":5,
                    "WriteCapacityUnits":1
                 }
              }
           }
       }
   }
   ```

   현재 다음과 같은 예제 대상 템플릿에는 `PlayersTable` 리소스가 있으며 `GamesTable`도 포함되어 있습니다.  
**Example JSON**  

   ```
   {
       "AWSTemplateFormatVersion": "2010-09-09",
       "Description": "Import test",
       "Resources": {
           "PlayersTable": {
               "Type": "AWS::DynamoDB::Table",
               "Properties": {
                   "TableName": "Players",
                   "AttributeDefinitions": [
                       {
                           "AttributeName": "key",
                           "AttributeType": "S"
                       }
                   ],
                   "KeySchema": [
                       {
                           "AttributeName": "key",
                           "KeyType": "HASH"
                       }
                   ],
                   "ProvisionedThroughput": {
                       "ReadCapacityUnits": 5,
                       "WriteCapacityUnits": 1
                   }
               }
           },
           "GamesTable": {
               "Type": "AWS::DynamoDB::Table",
               "DeletionPolicy": "Retain",
               "Properties": {
                   "TableName": "Games",
                   "AttributeDefinitions": [
                       {
                           "AttributeName": "key",
                           "AttributeType": "S"
                       }
                   ],
                   "KeySchema": [
                       {
                           "AttributeName": "key",
                           "KeyType": "HASH"
                       }
                   ],
                   "ProvisionedThroughput": {
                       "ReadCapacityUnits": 5,
                       "WriteCapacityUnits": 1
                   }
               }
           }
       }
   }
   ```

1. 소스 스택을 업데이트하여 `GamesTable` 리소스 및 관련 파라미터와 출력을 스택에서 삭제합니다.

   ```
   aws cloudformation update-stack --stack-name SourceStackName
   ```

1. 가져올 실제 리소스 목록과 고유 식별자를 다음 JSON 문자열 형식으로 작성합니다. 자세한 내용은 [리소스 식별자](import-resources-manually.md#resource-import-identifiers-unique-ids) 섹션을 참조하세요.

   ```
   [{"ResourceType":"AWS::DynamoDB::Table","LogicalResourceId":"GamesTable","ResourceIdentifier":{"TableName":"Games"}}]
   ```

   또는 구성 파일에서 JSON 형식 파라미터를 지정할 수 있습니다.

   예를 들어 `GamesTable`을 가져오려면 다음 구성이 포함된 *ResourcesToImport.txt* 파일을 만들 수 있습니다.

   ```
   [
     {
         "ResourceType":"AWS::DynamoDB::Table",
         "LogicalResourceId":"GamesTable",
         "ResourceIdentifier": {
           "TableName":"Games"
         }
     }
   ]
   ```

1. 변경 세트를 생성하려면 다음 **create-change-set** 명령을 사용하고 자리 표시자 텍스트를 변경합니다. `--change-set-type` 옵션의 경우, **IMPORT**의 값을 지정합니다. `--resources-to-import` 옵션의 경우 샘플 JSON 문자열을 방금 생성한 실제 JSON 문자열로 바꿉니다.

   ```
   aws cloudformation create-change-set \
       --stack-name TargetStackName --change-set-name ImportChangeSet \
       --change-set-type IMPORT \
       --template-body file://TemplateToImport.json \
       --resources-to-import "'[{"ResourceType":"AWS::DynamoDB::Table","LogicalResourceId":"GamesTable","ResourceIdentifier":{"TableName":"Games"}}]'"
   ```
**참고**  
`--resources-to-import`에서는 인라인 YAML을 지원하지 않습니다. JSON 문자열의 인용 부호 요구 사항은 터미널에 따라 다릅니다. 자세한 내용은 **AWS Command Line Interface 사용 설명서의 [문자열 안에 따옴표 사용](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-parameters-quoting-strings.html#cli-usage-parameters-quoting-strings-containing)을 참조하세요.

   또는 다음 예제와 같이 `--resources-to-import` 옵션에 대한 입력으로 파일 URL을 사용할 수 있습니다.

   ```
   --resources-to-import file://ResourcesToImport.txt
   ```

1. 변경 세트를 검토하여 올바른 리소스를 대상 스택에 가져오고 있는지 확인합니다.

   ```
   aws cloudformation describe-change-set \
       --change-set-name ImportChangeSet
   ```

1. 변경 세트를 시작하고 리소스를 가져오려면 다음 **execute-change-set** 명령을 사용하고 자리 표시자 텍스트를 변경합니다. 이때 어떤 스택 레벨 태그든 가져온 리소스에 적용됩니다. 작업 `(IMPORT_COMPLETE)`가 성공적으로 완료되면 리소스가 성공적으로 가져오기 됩니다.

   ```
   aws cloudformation execute-change-set \
       --change-set-name ImportChangeSet --stack-name TargetStackName
   ```
**참고**  
리소스가 이미 CloudFormation에서 관리되기 때문에 이러한 가져오기 작업을 수행한 후에 대상 스택에서 드리프트 감지를 실행할 필요가 없습니다.