

 **이 페이지는 볼트와 2012년부터 원래 REST API를 사용하는 Amazon Glacier 서비스의 기존 고객만 사용할 수 있습니다.**

아카이브 스토리지 솔루션을 찾고 있다면 Amazon S3의 Amazon Glacier 스토리지 클래스, S3 Glacier Instant Retrieval, S3 Glacier Flexible Retrieval 및 S3 Glacier Deep Archive를 사용하는 것이 좋습니다. 이러한 스토리지 옵션에 대한 자세한 내용은 [Amazon Glacier 스토리지 클래스](https://aws.amazon.com/s3/storage-classes/glacier/)를 참조하세요.

Amazon Glacier(기존 독립 실행형 볼트 기반 서비스)는 더 이상 신규 고객을 받지 않습니다. Amazon Glacier는 데이터를 볼트에 저장하고 Amazon S3 및 Amazon S3 Glacier 스토리지 클래스와 구별되는 자체 API를 갖춘 독립 실행형 서비스입니다. 기존 데이터는 Amazon Glacier에서 무기한으로 안전하게 보관되며 액세스 가능합니다. 마이그레이션은 필요하지 않습니다. 저비용 장기 아카이브 스토리지의 경우는 [S3 버킷 기반 API, 전체 가용성, 저렴한 비용 및 서비스 통합을 통해 우수한 고객 경험을 제공하는 Amazon S3 Glacier 스토리지 클래스](https://aws.amazon.com/s3/storage-classes/glacier/)를 AWS 권장합니다. S3 APIs AWS 리전 AWS 향상된 기능을 원하는 경우 [Amazon Glacier 볼트에서 Amazon S3 Glacier 스토리지 클래스로 데이터를 전송하기 위한AWS 솔루션 지침](https://aws.amazon.com/solutions/guidance/data-transfer-from-amazon-s3-glacier-vaults-to-amazon-s3/)을 사용하여 Amazon S3 Glacier 스토리지 클래스로 마이그레이션하는 것이 좋습니다.

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Amazon Glacier의 아카이브 작업
<a name="working-with-archives"></a>

아카이브란 사진, 동영상, 문서 등 볼트에 저장되는 모든 객체를 말합니다. Amazon Glacier(Amazon Glacier)의 기본 스토리지 단위입니다. 각 아카이브는 고유 ID가 있으며 선택 사항으로 설명을 추가할 수 있습니다. 아카이브를 업로드하면 Amazon Glacier가 아카이브 ID가 포함된 응답을 반환합니다. 이 아카이브 ID는 아카이브가 저장된 AWS 리전에서 고유합니다. 다음은 아카이브 ID의 예제입니다.

```
TJgHcrOSfAkV6hdPqOATYfp_0ZaxL1pIBOc02iZ0gDPMr2ig-nhwd_PafstsdIf6HSrjHnP-3p6LCJClYytFT_CBhT9CwNxbRaM5MetS3I-GqwxI3Y8QtgbJbhEQPs0mJ3KExample
```

 아카이브 ID의 길이는 138바이트입니다. 또한 아카이브를 업로드할 때 옵션으로 설명까지 입력할 수 있습니다. 단, ID를 사용해 아카이브를 가져올 수 있지만 설명으로는 그렇게 하지 못합니다.

 

**중요**  
Amazon Glacier는 관리 콘솔을 제공합니다. 이 콘솔에서는 볼트를 생성하거나 삭제할 수 있습니다. 하지만 Amazon Glacier와의 다른 상호작용에서는 AWS Command Line Interface (CLI)를 사용하거나 코드를 작성해야 합니다. 예를 들어 사진, 비디오 및 기타 문서와 같은 데이터를 업로드하려면 AWS CLI 를 사용하거나 REST API를 직접 사용하거나 Amazon SDKs를 사용하여 요청 코드를 작성해야 합니다. 에서 Amazon Glacier를 사용하는 AWS CLI방법에 대한 자세한 내용은 [AWS CLI Amazon Glacier 참조를 참조하세요](https://docs.aws.amazon.com/cli/latest/reference/glacier/index.html). 를 설치하려면 로 AWS CLI이동합니다[AWS Command Line Interface](https://aws.amazon.com/cli/).

**Topics**
+ [Amazon Glacier에서 아카이브 작업](#archive-operations-quick-intro)
+ [클라이언트 측 아카이브 메타데이터 유지](#client-side-key-map-concept)
+ [Amazon Glacier에 아카이브 업로드](uploading-an-archive.md)
+ [Amazon Glacier에서 아카이브 다운로드](downloading-an-archive.md)
+ [Amazon Glacier에서 아카이브 삭제](deleting-an-archive.md)

## Amazon Glacier에서 아카이브 작업
<a name="archive-operations-quick-intro"></a>

Amazon Glacier는 업로드, 다운로드, 삭제 등 기본적인 아카이브 작업을 지원합니다. 아카이브 다운로드는 비동기식 작업입니다.

### Amazon Glacier에 아카이브 업로드
<a name="uploading-an-archive-quick-intro"></a>

아카이브는 단일 작업으로, 혹은 여러 파트로 나누어 업로드할 수 있습니다. 아카이브를 여러 파트로 나누어 업로드할 때 사용하는 API 호출을 멀티파트 업로드라고 부릅니다. 자세한 내용은 [Amazon Glacier에 아카이브 업로드](uploading-an-archive.md) 단원을 참조하십시오.

 

**중요**  
Amazon Glacier는 관리 콘솔을 제공합니다. 이 콘솔에서는 볼트를 생성하거나 삭제할 수 있습니다. 그러나 Amazon Glacier와의 다른 모든 상호 작용에서는 AWS Command Line Interface (CLI)를 사용하거나 코드를 작성해야 합니다. 예를 들어 사진, 비디오 및 기타 문서와 같은 데이터를 업로드하려면 AWS CLI 를 사용하거나 REST API를 직접 사용하거나 Amazon SDKs를 사용하여 요청 코드를 작성해야 합니다. 에서 Amazon Glacier를 사용하는 AWS CLI방법에 대한 자세한 내용은 [AWS CLI Amazon Glacier 참조를 참조하세요](https://docs.aws.amazon.com/cli/latest/reference/glacier/index.html). 를 설치하려면 로 AWS CLI이동합니다[AWS Command Line Interface](https://aws.amazon.com/cli/).

### Amazon Glacier에서 아카이브 ID 찾기
<a name="finding-an-archive-id-quick-intro"></a>

아카이브 ID는 해당 아카이브가 포함된 볼트에서 볼트 인벤토리를 다운로드하여 가져올 수 있습니다. 볼트 인벤토리 다운로드에 대한 자세한 내용은 [Amazon Glacier에서 볼트 인벤토리 다운로드](vault-inventory.md) 섹션을 참조하세요.

### Amazon Glacier에서 아카이브 다운로드
<a name="downloading-an-archive-quick-intro"></a>

아카이브 다운로드는 비동기식 작업입니다. 따라서 먼저 특정 아카이브를 다운로드하는 작업부터 시작해야 합니다. 작업 요청이 수신되면 Amazon Glacier는 아카이브를 다운로드할 수 있도록 준비합니다. 작업이 완료되면 아카이브 데이터를 다운로드할 수 있습니다. 작업이 비동기식으로 이루어지기 때문에 작업 완료 시 Amazon Simple Notification Service(Amazon SNS) 토픽에 알림 메시지를 전송하도록 Amazon Glacier에 요청할 수 있습니다. 각 작업 요청마다 SNS 토픽을 지정하거나, 혹은 특정 이벤트가 발생할 경우 알림 메시지를 전송할 수 있도록 볼트를 구성할 수 있습니다. 아카이브 다운로드에 대한 자세한 내용은 [Amazon Glacier에서 아카이브 다운로드](downloading-an-archive.md) 섹션을 참조하세요.

### Amazon Glacier에서 아카이브 삭제
<a name="deleting-an-archive-quick-intro"></a>

Amazon Glacier는 한 번에 하나의 아카이브를 삭제할 수 있는 API 직접 호출을 제공합니다. 자세한 내용은 [Amazon Glacier에서 아카이브 삭제](deleting-an-archive.md) 단원을 참조하십시오.

### Amazon Glacier에서 아카이브 업데이트
<a name="updating-an-archive-quick-intro"></a>

이미 업로드한 아카이브는 내용이나 설명을 업데이트할 수 없습니다. 아카이브 내용이나 설명을 업데이트하려면 먼저 해당 아카이브를 삭제한 후 다른 아카이브를 업로드하는 것이 유일한 방법입니다. 아카이브를 업로드할 때마다 Amazon Glacier가 고유한 아카이브 ID를 반환합니다.

## 클라이언트 측 아카이브 메타데이터 유지
<a name="client-side-key-map-concept"></a>

선택적인 아카이브 설명을 제외하고 Amazon Glacier는 아카이브에 대해 추가적인 메타데이터를 지원하지 않습니다. 아카이브를 업로드할 때 Amazon Glacier가 ID를 할당하지만 불분명한 문자열이기 때문에 아카이브의 의미를 추측할 수 없습니다. 아카이브 메타데이터는 클라이언트 측에서 유지할 수 있습니다. 메타데이터에는 아카이브 이름을 비롯해 아카이브에 대한 유의미한 정보가 포함됩니다.

**참고**  
Amazon Simple Storage Service(Amazon S3) 고객이라면 누구나 객체를 버킷에 업로드할 때 `MyDocument.txt` 또는 `SomePhoto.jpg` 같은 객체 키를 객체에 할당할 수 있습니다. Amazon Glacier에서는 업로드하는 아카이브에 객체 키를 할당할 수 없습니다.

클라이언트 측 아카이브 메타데이터를 유지할 때는 Amazon Glacier가 아카이브 ID와 아카이브 업로드 중 사용자가 입력한 설명을 포함하는 볼트 인벤토리를 유지한다는 점도 알고 있어야 합니다. 간혹 볼트 인벤토리를 다운로드하여 아카이브 메타데이터로 유지하고 있는 클라이언트 측 데이터베이스의 문제를 조정하는 데 사용할 수 있습니다. 그러나 Amazon Glacier는 대략 하루에 한 번씩 볼트 인벤토리를 작성합니다. 볼트 인벤토리를 요청하면 Amazon Glacier가 마지막으로 준비한 인벤토리, 즉 특정 시점의 스냅샷을 반환합니다.

# Amazon Glacier에 아카이브 업로드
<a name="uploading-an-archive"></a>

Amazon Glacier(Amazon Glacier)는 볼트 생성 및 삭제에 사용할 수 있는 관리 콘솔을 제공합니다. 하지만 관리 콘솔을 사용해서 아카이브를 Amazon Glacier에 업로드할 수는 없습니다. 사진, 동영상 및 기타 문서와 같은 데이터를 업로드하려면 REST API를 직접 AWS CLI 사용하거나 Amazon SDKs를 사용하여를 사용하거나 코드를 작성하여 요청해야 합니다.

에서 Amazon Glacier를 사용하는 AWS CLI방법에 대한 자세한 내용은 [AWS CLI Amazon Glacier 참조를 참조하세요](https://docs.aws.amazon.com/cli/latest/reference/glacier/index.html). 를 설치하려면 로 AWS CLI이동합니다[AWS Command Line Interface](https://aws.amazon.com/cli/). 다음의 **업로드** 토픽에서는 Amazon SDK for Java, Amazon SDK for .NET 및 REST API를 사용하여 아카이브를 Amazon Glacier에 업로드하는 방법을 설명합니다.

**Topics**
+ [Amazon Glacier에 아카이브를 업로드하기 위한 옵션](#uploading-an-archive-overview)
+ [아카이브의 단일 작업 업로드](uploading-archive-single-operation.md)
+ [대용량 아카이브를 여러 파트로 나누어 업로드(멀티파트 업로드)](uploading-archive-mpu.md)

## Amazon Glacier에 아카이브를 업로드하기 위한 옵션
<a name="uploading-an-archive-overview"></a>

Amazon Glacier는 업로드하는 데이터의 크기에 따라 다음과 같은 옵션을 제공합니다.
+ **아카이브의 단일 작업 업로드**: 크기가 1바이트에서 최대 4GB인 아카이브는 단일 작업으로 업로드할 수 있습니다. 하지만 Amazon Glacier 고객이 100MB가 넘는 대용량 아카이브를 업로드할 때는 멀티파트 업로드 기능을 사용할 것을 권장합니다. 자세한 내용은 [아카이브의 단일 작업 업로드](uploading-archive-single-operation.md) 단원을 참조하십시오.
+ **아카이브의 멀티파트 업로드**: 최대 40,000GB(10,000\$14GB)의 대용량 아카이브는 멀티파트 업로드 API를 사용하여 업로드할 수 있습니다.

  멀티파트 업로드 API 호출은 대용량 아카이브의 업로드 경험을 개선할 목적으로 설계되었습니다. 여기에서는 아카이브를 여러 파트로 나누어 업로드할 수 있습니다. 이러한 파트들은 순서에 상관없이 각각 병렬 방식으로 업로드됩니다. 멀티파트 업로드가 오류로 중단되더라도 전체 아카이브가 아니라 중단된 파트만 다시 업로드하면 됩니다. 멀티파트 업로드는 크기가 1바이트에서 약 40,000GB에 이르는 아카이브에 사용할 수 있습니다. 자세한 내용은 [대용량 아카이브를 여러 파트로 나누어 업로드(멀티파트 업로드)](uploading-archive-mpu.md) 단원을 참조하십시오.

**중요**  
Amazon Glacier 볼트 인벤토리는 하루 한 번 업데이트됩니다. 따라서 아카이브를 업로드한다고 해서 새로운 아카이브가 볼트에 바로 추가되어 콘솔이나 다운로드한 볼트 인벤토리 목록에 표시되지는 않습니다. 먼저 볼트 인벤토리가 업데이트되어야 합니다.

### AWS Snowball Edge 서비스 사용
<a name="using-import-export-service-for-glacier"></a>

AWS Snowball Edge 는 인터넷을 우회하여 Amazon 소유 디바이스를 AWS 사용하여 대량의 데이터를 송수신하는 속도를 높입니다. 자세한 내용은 [AWS Snowball Edge](https://aws.amazon.com/snowball) 세부 정보 페이지를 참조하세요.

기존 데이터를 Amazon Glacier(Amazon Glacier)에 업로드하려면 AWS Snowball Edge 디바이스 유형 중 하나를 사용해서 데이터를 Amazon S3로 가져온 다음, 수명 주기 규칙을 사용하여 아카이브용 Amazon Glacier 스토리지 클래스로 이동하는 것을 고려해 볼 수 있습니다. Amazon S3 객체를 Amazon Glacier 스토리지 클래스로 전환하면, Amazon S3가 내부적으로 Amazon Glacier를 사용하여 보다 저렴한 비용으로 내구성 있는 보관이 가능합니다. 객체가 Amazon Glacier에 저장되어 있지만 이들은 여전히 사용자가 Amazon S3에서 관리하는 Amazon S3 객체이며, 사용자가 Amazon Glacier를 통해 직접 액세스할 수는 없습니다.

Amazon S3 수명 주기 구성 및 Amazon Glacier 스토리지 클래스로의 객체 전환에 대한 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [객체 수명 주기 관리](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html) 및 [객체 전환](https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-transition-general-considerations.html)을 참조하세요.

# 아카이브의 단일 작업 업로드
<a name="uploading-archive-single-operation"></a>

[Amazon Glacier에 아카이브 업로드](uploading-an-archive.md) 섹션에서 설명한 것과 같이 더 작은 크기의 아카이브도 단일 작업으로 업로드할 수 있습니다. 하지만 Amazon Glacier(Amazon Glacier) 고객이 100MB가 넘는 대용량 아카이브를 업로드할 때는 멀티파트 업로드 기능을 사용하는 것이 권장됩니다.

**Topics**
+ [를 사용하여 아카이브를 단일 작업으로 업로드 AWS Command Line Interface](uploading-an-archive-single-op-using-cli.md)
+ [를 사용하여 아카이브를 단일 작업으로 업로드 AWS SDK for Java](uploading-an-archive-single-op-using-java.md)
+ [Amazon Glacier에서를 사용하여 아카이브를 단일 작업 AWS SDK for .NET 으로 업로드](uploading-an-archive-single-op-using-dotnet.md)
+ [REST API를 사용하여 아카이브의 단일 작업 업로드](uploading-an-archive-single-op-using-rest.md)

# 를 사용하여 아카이브를 단일 작업으로 업로드 AWS Command Line Interface
<a name="uploading-an-archive-single-op-using-cli"></a>

 AWS Command Line Interface ()를 사용하여 Amazon Glacier(Amazon Glacier)에 아카이브를 업로드할 수 있습니다AWS CLI.

**Topics**
+ [(사전 조건) 설정 AWS CLI](#Creating-Vaults-CLI-Setup)
+ [예:를 사용하여 아카이브 업로드 AWS CLI](#Uploading-Archives-CLI-Implementation)

## (사전 조건) 설정 AWS CLI
<a name="Creating-Vaults-CLI-Setup"></a>

1.  AWS CLI를 다운로드하고 구성합니다. 관련 지침은 *AWS Command Line Interface 사용 설명서*에서 다음 토픽을 참조하세요.

    [설치 AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/installing.html) 

   [구성 AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)

1. 명령 프롬프트에 다음 명령을 입력하여 AWS CLI 설정을 확인합니다. 이러한 명령은 명시적으로 자격 증명을 제공하지 않으므로 기본 프로파일의 자격 증명이 사용됩니다.
   + help 명령을 사용해 보십시오.

     ```
     aws help
     ```
   + 구성된 계정의 Amazon Glacier 볼트 목록을 가져오려면 `list-vaults` 명령을 사용합니다. *123456789012*을 AWS 계정 ID로 바꿉니다.

     ```
     aws glacier list-vaults --account-id 123456789012
     ```
   + 에 대한 현재 구성 데이터를 보려면 `aws configure list` 명령을 AWS CLI사용합니다.

     ```
     aws configure list
     ```

## 예:를 사용하여 아카이브 업로드 AWS CLI
<a name="Uploading-Archives-CLI-Implementation"></a>

아카이브를 업로드하려면 반드시 볼트를 생성해야 합니다. 볼트 생성에 대한 자세한 내용은 [Amazon Glacier에 볼트 생성](creating-vaults.md) 섹션을 참조하세요.

1. `upload-archive` 명령을 사용하여 기존 볼트에 아카이브를 추가합니다. 아래 예시에서는 `vault name` 및 `account ID`를 바꿉니다. `body` 파라미터에서 업로드하려는 파일의 경로를 지정합니다.

   ```
   aws glacier upload-archive --vault-name awsexamplevault --account-id 123456789012 --body archive.zip
   ```

1.  예상 결과:

   ```
   {
       "archiveId": "kKB7ymWJVpPSwhGP6ycSOAekp9ZYe_--zM_mw6k76ZFGEIWQX-ybtRDvc2VkPSDtfKmQrj0IRQLSGsNuDp-AJVlu2ccmDSyDUmZwKbwbpAdGATGDiB3hHO0bjbGehXTcApVud_wyDw",
       "checksum": "969fb39823836d81f0cc028195fcdbcbbe76cdde932d4646fa7de5f21e18aa67",
       "location": "/123456789012/vaults/awsexamplevault/archives/kKB7ymWJVpPSwhGP6ycSOAekp9ZYe_--zM_mw6k76ZFGEIWQX-ybtRDvc2VkPSDtfKmQrj0IRQLSGsNuDp-AJVlu2ccmDSyDUmZwKbwbpAdGATGDiB3hHO0bjbGehXTcApVud_wyDw"
   }
   ```

   완료되면 명령이 아카이브 ID, 체크섬 및 Amazon Glacier 내의 위치를 출력합니다. upload-archive 명령에 대한 자세한 내용은 *AWS CLI 명령 참조*의 [upload-archive](https://docs.aws.amazon.com/cli/latest/reference/glacier/upload-archive.html)를 참조하세요.

# 를 사용하여 아카이브를 단일 작업으로 업로드 AWS SDK for Java
<a name="uploading-an-archive-single-op-using-java"></a>

Amazon SDK for Java에서 제공하는 [하이레벨 및 로우레벨 API](using-aws-sdk.md) 둘 모두는 아카이브를 업로드하는 방법을 제공합니다.

**Topics**
+ [의 상위 수준 API를 사용하여 아카이브 업로드 AWS SDK for Java](#uploading-an-archive-single-op-high-level-using-java)
+ [의 하위 수준 API를 사용하여 단일 작업으로 아카이브 업로드 AWS SDK for Java](#uploading-an-archive-single-op-low-level-using-java)

## 의 상위 수준 API를 사용하여 아카이브 업로드 AWS SDK for Java
<a name="uploading-an-archive-single-op-high-level-using-java"></a>

하이레벨 API의 `ArchiveTransferManager` 클래스는 아카이브를 볼트에 업로드하는 데 사용할 수 있는 `upload` 메서드를 제공합니다.

 

**참고**  
`upload` 메서드는 작든 크든 상관없이 모든 아카이브를 업로드하는 데 사용됩니다. 이 메서드는 업로드하는 아카이브 크기에 따라 아카이브를 단일 작업으로 업로드할지, 혹은 멀티파트 업로드 API를 사용해 아카이브를 여러 파트로 나누어 업로드할지 결정합니다.

### 예:의 상위 수준 API를 사용하여 아카이브 업로드 AWS SDK for Java
<a name="upload-archive-high-level-java-example"></a>

다음은 미국 서부(오레곤) 리전(`us-west-2`)의 볼트(`examplevault`)에 아카이브를 업로드하는 Java 코드 예시입니다. 지원되는 AWS 리전 및 엔드포인트 목록은 섹션을 참조하세요[Amazon Glacier 액세스](amazon-glacier-accessing.md).

이 예제의 실행 방법에 대한 단계별 지침은 [Eclipse를 사용하여 Amazon Glacier의 Java 예 실행](using-aws-sdk-for-java.md#setting-up-and-testing-sdk-java) 섹션을 참조하세요. 아래와 같이 업로드할 볼트 이름과 파일 이름을 사용해 코드를 업데이트해야 합니다.

**Example**  

```
import java.io.File;
import java.io.IOException;
import java.util.Date;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.transfer.ArchiveTransferManager;
import com.amazonaws.services.glacier.transfer.UploadResult;


public class ArchiveUploadHighLevel {
    public static String vaultName = "*** provide vault name ***";
    public static String archiveToUpload = "*** provide name of file to upload ***";
    
    public static AmazonGlacierClient client;
    
    public static void main(String[] args) throws IOException {
        
        
    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();
    	
        client = new AmazonGlacierClient(credentials);
        client.setEndpoint("https://glacier.us-west-2.amazonaws.com/");

        try {
            ArchiveTransferManager atm = new ArchiveTransferManager(client, credentials);
            
            UploadResult result = atm.upload(vaultName, "my archive " + (new Date()), new File(archiveToUpload));
            System.out.println("Archive ID: " + result.getArchiveId());
            
        } catch (Exception e)
        {
            System.err.println(e);
        }
    }
}
```

## 의 하위 수준 API를 사용하여 단일 작업으로 아카이브 업로드 AWS SDK for Java
<a name="uploading-an-archive-single-op-low-level-using-java"></a>

로우레벨 API는 모든 아카이브 작업에 필요한 메서드를 제공합니다. 다음은 AWS SDK for Java를 사용하여 아카이브를 업로드하는 단계입니다.

 

1. `AmazonGlacierClient` 클래스(클라이언트)의 인스턴스를 만듭니다.

   아카이브를 업로드할 AWS 리전을 지정해야 합니다. 이 클라이언트를 사용하여 수행하는 모든 작업은 해당 AWS 리전에 적용됩니다.

1. `UploadArchiveRequest` 클래스 인스턴스를 생성하여 요청 정보를 입력합니다.

   업로드할 데이터 외에도 페이로드의 체크섬(SHA256 트리-해시), 볼트 이름, 데이터의 내용 길이, 계정 ID를 입력해야 합니다.

   계정 ID를 입력하지 않는 경우에는 요청 서명을 위해 입력하는 자격 증명과 연결되어 있는 계정 ID로 간주합니다. 자세한 내용은 [Amazon Glacier AWS SDK for Java 에서 사용](using-aws-sdk-for-java.md) 단원을 참조하십시오.

1. 요청 객체를 파라미터로 입력하여 `uploadArchive` 메서드를 실행합니다.

   그러면 Amazon Glacier(Amazon Glacier)가 응답으로 새롭게 업로드된 아카이브의 ID를 반환합니다.

다음은 위에서 설명한 단계를 나타내는 Java 코드 조각입니다.

```
AmazonGlacierClient client;

UploadArchiveRequest request = new UploadArchiveRequest()
    .withVaultName("*** provide vault name ***")
    .withChecksum(checksum)
    .withBody(new ByteArrayInputStream(body))
    .withContentLength((long)body.length);

UploadArchiveResult uploadArchiveResult = client.uploadArchive(request);

System.out.println("Location (includes ArchiveID): " + uploadArchiveResult.getLocation());
```

### 예:의 하위 수준 API를 사용하여 단일 작업으로 아카이브 업로드 AWS SDK for Java
<a name="uploding-single-archive-using-java-example"></a>

다음 Java 코드 예제에서는 AWS SDK for Java 를 사용하여 아카이브를 볼트()에 업로드합니다`examplevault`. 이 예제의 실행 방법에 대한 단계별 지침은 [Eclipse를 사용하여 Amazon Glacier의 Java 예 실행](using-aws-sdk-for-java.md#setting-up-and-testing-sdk-java) 섹션을 참조하세요. 아래와 같이 업로드할 볼트 이름과 파일 이름을 사용해 코드를 업데이트해야 합니다.

```
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.TreeHashGenerator;
import com.amazonaws.services.glacier.model.UploadArchiveRequest;
import com.amazonaws.services.glacier.model.UploadArchiveResult;
public class ArchiveUploadLowLevel {

    public static String vaultName = "*** provide vault name ****";
    public static String archiveFilePath = "*** provide to file upload ****";
    public static AmazonGlacierClient client;
    
    public static void main(String[] args) throws IOException {
    	
    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();

        client = new AmazonGlacierClient(credentials);
        client.setEndpoint("https://glacier.us-east-1.amazonaws.com/");

        try {
            // First open file and read.
            File file = new File(archiveFilePath);
            InputStream is = new FileInputStream(file); 
            byte[] body = new byte[(int) file.length()];
            is.read(body);
                                    
            // Send request.
            UploadArchiveRequest request = new UploadArchiveRequest()
                .withVaultName(vaultName)
                .withChecksum(TreeHashGenerator.calculateTreeHash(new File(archiveFilePath))) 
                .withBody(new ByteArrayInputStream(body))
                .withContentLength((long)body.length);
            
            UploadArchiveResult uploadArchiveResult = client.uploadArchive(request);
            
            System.out.println("ArchiveID: " + uploadArchiveResult.getArchiveId());
            
        } catch (Exception e)
        {
            System.err.println("Archive not uploaded.");
            System.err.println(e);
        }
    }
}
```

# Amazon Glacier에서를 사용하여 아카이브를 단일 작업 AWS SDK for .NET 으로 업로드
<a name="uploading-an-archive-single-op-using-dotnet"></a>

.NET용 Amazon SDK에서 제공하는 [하이레벨 및 로우레벨 API](using-aws-sdk.md) 둘 모두는 단일 작업으로 아카이브를 업로드하는 방법을 제공합니다.

**Topics**
+ [의 상위 수준 API를 사용하여 아카이브 업로드 AWS SDK for .NET](#uploading-an-archive-single-op-highlevel-using-dotnet)
+ [의 하위 수준 API를 사용하여 단일 작업으로 아카이브 업로드 AWS SDK for .NET](#uploading-an-archive-single-op-lowlevel-using-dotnet)

## 의 상위 수준 API를 사용하여 아카이브 업로드 AWS SDK for .NET
<a name="uploading-an-archive-single-op-highlevel-using-dotnet"></a>

하이레벨 API의 `ArchiveTransferManager` 클래스는 아카이브를 볼트에 업로드하는 데 사용할 수 있는 `Upload` 메서드를 제공합니다.

**참고**  
`Upload` 메서드는 작든 크든 상관없이 모든 파일을 업로드하는 데 사용됩니다. 이 메서드는 업로드하는 파일 크기에 따라 아카이브를 단일 작업으로 업로드할지, 혹은 멀티파트 업로드 API를 사용해 파일을 여러 파트로 나누어 업로드할지 결정합니다.

### 예:의 상위 수준 API를 사용하여 아카이브 업로드 AWS SDK for .NET
<a name="upload-archive-highlevel-any-size-dotnet"></a>

다음은 미국 서부(오레곤) 리전의 볼트(`examplevault`)에 아카이브를 업로드하는 C\$1 코드 예시입니다.

이 예제의 실행 방법에 대한 단계별 지침은 [코드 예제 실행](using-aws-sdk-for-dot-net.md#setting-up-and-testing-sdk-dotnet) 섹션을 참조하세요. 아래와 같이 업로드할 파일 이름을 사용해 코드를 업데이트해야 합니다.

**Example**  

```
using System;
using Amazon.Glacier;
using Amazon.Glacier.Transfer;
using Amazon.Runtime;

namespace glacier.amazon.com.rproxy.govskope.us.docsamples
{
  class ArchiveUploadHighLevel
  {
    static string vaultName = "examplevault"; 
    static string archiveToUpload = "*** Provide file name (with full path) to upload ***";

    public static void Main(string[] args)
    {
       try
      {
         var manager = new ArchiveTransferManager(Amazon.RegionEndpoint.USWest2);
         // Upload an archive.
         string archiveId = manager.Upload(vaultName, "upload archive test", archiveToUpload).ArchiveId;
         Console.WriteLine("Archive ID: (Copy and save this ID for use in other examples.) : {0}", archiveId);
         Console.WriteLine("To continue, press Enter"); 
         Console.ReadKey();
      }
      catch (AmazonGlacierException e) { Console.WriteLine(e.Message); }
      catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
      catch (Exception e) { Console.WriteLine(e.Message); }
      Console.WriteLine("To continue, press Enter");
      Console.ReadKey();
    }
  }
}
```

## 의 하위 수준 API를 사용하여 단일 작업으로 아카이브 업로드 AWS SDK for .NET
<a name="uploading-an-archive-single-op-lowlevel-using-dotnet"></a>

로우레벨 API는 모든 아카이브 작업에 필요한 메서드를 제공합니다. 다음은 AWS SDK for .NET를 사용하여 아카이브를 업로드하는 단계입니다.

 

1. `AmazonGlacierClient` 클래스(클라이언트)의 인스턴스를 만듭니다.

   아카이브를 업로드할 AWS 리전을 지정해야 합니다. 이 클라이언트를 사용하여 수행하는 모든 작업은 해당 AWS 리전에 적용됩니다.

1. `UploadArchiveRequest` 클래스 인스턴스를 생성하여 요청 정보를 입력합니다.

   업로드할 데이터 외에도 페이로드의 체크섬(SHA256 트리-해시), 볼트 이름, 계정 ID 등을 입력해야 합니다.

   계정 ID를 입력하지 않는 경우에는 요청 서명을 위해 입력하는 자격 증명과 연결되어 있는 계정 ID로 간주합니다. 자세한 내용은 [Amazon Glacier와 함께 AWS SDK for .NET 사용](using-aws-sdk-for-dot-net.md) 단원을 참조하십시오.

1. 요청 객체를 파라미터로 입력하여 `UploadArchive` 메서드를 실행합니다.

   Amazon Glacier가 응답으로 새롭게 업로드된 아카이브 ID를 반환합니다.

### 예:의 하위 수준 API를 사용하여 단일 작업으로 아카이브 업로드 AWS SDK for .NET
<a name="upload-archive-single-op-lowlevel-dotnet"></a>

다음 C\$1 코드 예제에서는 이전 단계를 설명합니다. 이 예제에서는 AWS SDK for .NET 를 사용하여 아카이브를 볼트()에 업로드합니다`examplevault`.

**참고**  
아카이브를 단일 작업으로 업로드하는 기본 REST API에 대한 자세한 내용은 [아카이브 업로드(POST archive)](api-archive-post.md) 섹션을 참조하세요.

이 예제의 실행 방법에 대한 단계별 지침은 [코드 예제 실행](using-aws-sdk-for-dot-net.md#setting-up-and-testing-sdk-dotnet) 섹션을 참조하세요. 아래와 같이 업로드할 파일 이름을 사용해 코드를 업데이트해야 합니다.

**Example**  

```
using System;
using System.IO;
using Amazon.Glacier;
using Amazon.Glacier.Model;
using Amazon.Runtime;

namespace glacier.amazon.com.rproxy.govskope.us.docsamples
{
  class ArchiveUploadSingleOpLowLevel
  {
    static string vaultName       = "examplevault";
    static string archiveToUpload = "*** Provide file name (with full path) to upload ***";

    public static void Main(string[] args)
    {
      AmazonGlacierClient client;
      try
      {
         using (client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2))
        {
          Console.WriteLine("Uploading an archive.");
          string archiveId = UploadAnArchive(client);
          Console.WriteLine("Archive ID: {0}", archiveId);
        }
      }
      catch (AmazonGlacierException e) { Console.WriteLine(e.Message); }
      catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
      catch (Exception e) { Console.WriteLine(e.Message); }
      Console.WriteLine("To continue, press Enter");
      Console.ReadKey();
    }

    static string UploadAnArchive(AmazonGlacierClient client)
    {
      using (FileStream fileStream = new FileStream(archiveToUpload, FileMode.Open, FileAccess.Read))
      {
        string treeHash = TreeHashGenerator.CalculateTreeHash(fileStream);
        UploadArchiveRequest request = new UploadArchiveRequest()
        {
          VaultName = vaultName,
          Body = fileStream,
          Checksum = treeHash
        };
        UploadArchiveResponse response = client.UploadArchive(request);
        string archiveID = response.ArchiveId;
        return archiveID;
      }
    }
  }
}
```

# REST API를 사용하여 아카이브의 단일 작업 업로드
<a name="uploading-an-archive-single-op-using-rest"></a>

아카이브 업로드 API 호출을 통해 아카이브를 단일 작업으로 업로드할 수 있습니다. 자세한 내용은 [아카이브 업로드(POST archive)](api-archive-post.md) 섹션을 참조하세요.

# 대용량 아카이브를 여러 파트로 나누어 업로드(멀티파트 업로드)
<a name="uploading-archive-mpu"></a>

**Topics**
+ [멀티파트 업로드 프로세스](#MPUprocess)
+ [주요 사양](#qfacts)
+ [를 사용하여 대용량 아카이브 업로드 AWS CLI](uploading-an-archive-mpu-using-cli.md)
+ [Amazon SDK for Java를 사용하여 대용량 아카이브를 파트로 나누어 업로드](uploading-an-archive-mpu-using-java.md)
+ [를 사용하여 대용량 아카이브 업로드 AWS SDK for .NET](uploading-an-archive-mpu-using-dotnet.md)
+ [REST API를 사용하는 대용량 아카이브의 멀티파트 업로드](uploading-an-archive-mpu-using-rest.md)

## 멀티파트 업로드 프로세스
<a name="MPUprocess"></a>

[Amazon Glacier에 아카이브 업로드](uploading-an-archive.md)에서 설명한 바와 같이 Amazon Glacier(Amazon Glacier) 고객이 100메비바이트(MiB)가 넘는 대용량 아카이브를 업로드할 때는 멀티파트 업로드 기능을 사용하는 것을 권장합니다.

1. **멀티파트 업로드 시작** 

   멀티파트 업로드 시작 요청을 전송하면 Amazon Glacier가 멀티파트 업로드를 위한 고유 식별자인 업로드 멀티파트 업로드 ID를 반환합니다. 이후로 멀티파트 업로드 작업을 이어가려면 이 ID가 필요합니다. 이 ID는 Amazon Glacier가 작업을 완료한 후 최소 24시간 동안 만료되지 않습니다.

   멀티파트 업로드를 시작하는 요청에서 파트 크기(바이트 수)를 지정합니다. 마지막 파트를 제외하고 업로드하는 파트는 각각 여기에서 지정하는 크기를 따라야 합니다.
**참고**  
멀티파트 업로드를 사용할 때 전체 아카이브 크기를 알 필요는 없습니다. 즉, 아카이브 업로드를 시작할 때 아카이브 크기를 모르더라도 멀티파트 업로드를 사용할 수 있습니다. 멀티파트 업로드를 시작할 때 파트 크기만 결정하면 됩니다.

   멀티파트 업로드 요청을 시작할 때 선택적으로 아카이브 설명을 입력할 수도 있습니다.

1. **파트 업로드**

   각 파트의 업로드 요청마다 1단계에서 얻은 멀티파트 업로드 ID를 추가해야 합니다. 요청에서 최종 아카이브의 파트 위치를 식별할 수 있도록 내용 범위를 바이트로 지정해야 합니다. Amazon Glacier는 추후에 콘텐츠 범위 정보를 사용하여 아카이브를 적절한 순서로 조립합니다. 업로드하는 파트마다 내용 범위를 입력하면 최종 아카이브 어셈블리에서 파트 위치를 결정하기 때문에 어떤 순서로든 파트를 업로드할 수 있습니다. 또한 병렬 방식으로 파트를 업로드하는 것도 가능합니다. 이전에 업로드한 파트와 동일한 내용 범위로 새로운 파트를 업로드할 경우에는 이전에 업로드한 파트를 덮어쓰게 됩니다.

1. **멀티파트 업로드 완료(또는 중단)**

   아카이브 파트를 모두 업로드한 후에는 완료 작업을 시작합니다. 반드시 요청에 업로드 ID를 지정해야 합니다. Amazon Glacier는 사용자가 제공한 콘텐츠 범위를 바탕으로 오름차순으로 각 부분을 연결하여 아카이브를 생성합니다. 멀티파트 업로드 완료 요청에 대한 Amazon Glacier 응답에는 새로 생성된 아카이브의 아카이브 ID가 포함됩니다. 멀티파트 업로드 시작 요청에서 선택적으로 아카이브 설명을 입력하였다면 Amazon Glacier가 어셈블링된 아카이브에 설명을 연결합니다. 멀티파트 업로드가 성공적으로 완료된 후에는 멀티파트 업로드 ID를 참조할 수 없습니다. 이 말은 멀티파트 업로드 ID로 연결된 파트에 액세스할 수 없다는 것을 의미합니다.

   멀티파트 업로드를 중단한 경우 해당 멀티파트 업로드 ID로는 더 이상 파트를 업로드할 수 없습니다. 중단된 멀티파트 업로드로 연결된 파트가 차지하는 스토리지는 모두 비워집니다. 파트 업로드가 진행 중일 때 진행 중인 파트 업로드는 성공적으로 완료되거나, 혹은 오류로 멈출 수도 있습니다.

### 추가 멀티파트 업로드 작업
<a name="additional-mpu-operations"></a>

Amazon Glacier(Amazon Glacier)는 다음과 같은 멀티파트 업로드 API 직접 호출을 추가적으로 제공합니다.

 
+ **파트 나열**: 이 작업을 사용하면 특정 멀티파트 업로드의 파트를 나열할 수 있습니다. 그러면 멀티파트 업로드로 업로드한 파트의 정보가 반환됩니다. 파트 나열 요청이 있을 때마다 Amazon Glacier는 최대 1,000개까지 파트 정보를 반환합니다. 멀티파트 업로드에 대해 목록을 조회할 파트가 더 있는 경우에는 결과에 페이지 번호가 매겨지고, 응답으로 목록을 계속 이어가는 마커가 반환됩니다. 이후 파트를 가져오려면 추가 요청을 보내야 합니다. 반환된 부분 목록에는 업로드가 완료되지 않은 부분은 포함되지 않습니다.
+ **멀티파트 업로드 나열**: 이 작업을 사용하여 진행 중인 멀티파트 업로드의 목록을 확인할 수 있습니다. 진행 중인 멀티파트 업로드는 시작했지만 아직 완료 또는 중단하지 않은 업로드입니다. 멀티파트 업로드 목록 조회 요청이 있을 때마다 Amazon Glacier는 최대 1,000개까지 멀티파트 업로드를 반환합니다. 목록을 조회할 멀티파트 업로드가 더 있는 경우에는 결과에 페이지 번호가 매겨지고, 응답으로 목록을 계속 이어가는 마커가 반환됩니다. 나머지 멀티파트 업로드를 가져오려면 추가 요청을 보내야 합니다.

## 주요 사양
<a name="qfacts"></a>

다음 표에 멀티파트 업로드의 주요 사양이 나와 있습니다.


| 항목 | 사양 | 
| --- | --- | 
| 최대 아카이브 크기 | 10,000x4기비바이트(GiB)  | 
| 업로드당 최대 파트 개수 | 10,000 | 
| 파트 크기 | 1MiB에서 4GiB까지, 마지막 파트는 1MiB 미만일 수도 있습니다. 크기 값은 바이트 단위로 지정합니다. 파트 크기는 2의 제곱이 곱해진 메비바이트(1024키비바이트[KiB]) 값이어야 합니다. 예를 들어 `1048576`(1MiB), `2097152`(2MiB), `4194304`(4MiB), `8388608`(8MiB)등과 같습니다.  | 
| 파트 목록 조회 요청에 대해 반환되는 최대 파트 개수 | 1,000  | 
| 멀티파트 업로드 나열 요청에서 반환되는 최대 멀티파트 업로드 개수 | 1,000  | 

# 를 사용하여 대용량 아카이브 업로드 AWS CLI
<a name="uploading-an-archive-mpu-using-cli"></a>

 AWS Command Line Interface ()를 사용하여 Amazon Glacier(Amazon Glacier)에 아카이브를 업로드할 수 있습니다AWS CLI. 대규모 아카이브의 업로드 환경을 개선하기 위해, Amazon Glacier는 멀티파트 업로드를 지원하는 여러 API 작업을 제공합니다. 이 API 작업을 사용하여 아카이브를 파트로 나누어 업로드할 수 있습니다. 이러한 파트들은 순서에 상관없이 각각 병렬 방식으로 업로드됩니다. 멀티파트 업로드에 실패하더라도 전체 아카이브가 아니라 실패한 파트만 다시 업로드하면 됩니다. 멀티파트 업로드는 크기가 1바이트에서 약 40,000기비바이트(GiB)에 이르는 아카이브에 사용할 수 있습니다.

Amazon Glacier 멀티파트 업로드에 대한 자세한 내용은 [대용량 아카이브를 여러 파트로 나누어 업로드(멀티파트 업로드)](uploading-archive-mpu.md) 섹션을 참조하세요.

**Topics**
+ [(사전 조건) 설정 AWS CLI](#Creating-Vaults-CLI-Setup)
+ [(요구 사항) Python 설치](#Uploading-Archives-mpu-CLI-Install-Python)
+ [(요구 사항) Amazon Glacier 볼트 생성](#Uploading-Archives-mpu-CLI-Create-Vault)
+ [예:를 사용하여 대용량 아카이브를 파트로 업로드 AWS CLI](#Uploading-Archives-mpu-CLI-Implementation)

## (사전 조건) 설정 AWS CLI
<a name="Creating-Vaults-CLI-Setup"></a>

1.  AWS CLI를 다운로드하고 구성합니다. 관련 지침은 *AWS Command Line Interface 사용 설명서*에서 다음 토픽을 참조하세요.

    [설치 AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/installing.html) 

   [구성 AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)

1. 명령 프롬프트에 다음 명령을 입력하여 AWS CLI 설정을 확인합니다. 이러한 명령은 명시적으로 자격 증명을 제공하지 않으므로 기본 프로파일의 자격 증명이 사용됩니다.
   + help 명령을 사용해 보십시오.

     ```
     aws help
     ```
   + 구성된 계정의 Amazon Glacier 볼트 목록을 가져오려면 `list-vaults` 명령을 사용합니다. *123456789012*을 AWS 계정 ID로 바꿉니다.

     ```
     aws glacier list-vaults --account-id 123456789012
     ```
   + 에 대한 현재 구성 데이터를 보려면 `aws configure list` 명령을 AWS CLI사용합니다.

     ```
     aws configure list
     ```

## (요구 사항) Python 설치
<a name="Uploading-Archives-mpu-CLI-Install-Python"></a>

멀티파트 업로드를 완료하려면 업로드 중인 아카이브의 SHA256 트리 해시를 반드시 계산해야 합니다. 이 작업은 업로드를 원하는 파일의 SHA256 트리 해시를 계산하는 것과 다릅니다. 업로드 중인 아카이브의 SHA256 트리 해시를 계산할 때 Java, C\$1(.NET와 함께) 또는 Python을 사용할 수 있습니다. 이 예시에서는 Python을 사용합니다. Java 또는 C\$1을 사용하는 방법 지침은 [체크섬 계산](checksum-calculations.md) 섹션을 참조하세요.

Python을 설치하는 방법에 대한 자세한 내용은 *Boto3 개발자 가이드*의 [Python 설치 또는 업데이트](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html#installation)를 참조하세요.

## (요구 사항) Amazon Glacier 볼트 생성
<a name="Uploading-Archives-mpu-CLI-Create-Vault"></a>

다음 예시를 사용하려면 적어도 하나 이상의 Amazon Glacier 볼트가 생성되어 있어야 합니다. 볼트 생성에 대한 자세한 내용은 [Amazon Glacier에 볼트 생성](creating-vaults.md) 섹션을 참조하세요.

## 예:를 사용하여 대용량 아카이브를 파트로 업로드 AWS CLI
<a name="Uploading-Archives-mpu-CLI-Implementation"></a>

이 예시에서는 파일을 생성하고 멀티파트 업로드 API 작업을 사용하여 이 파일을 여러 파트로 나누어 Amazon Glacier에 업로드합니다.
**중요**  
이 과정을 시작하기 전에 요구 사항 단계를 모두 수행했는지 확인합니다. 아카이브를 업로드하려면 반드시 볼트가 생성되어 있고 AWS CLI 가 구성되어 있어야 하며 Java, C\$1, 또는 Python을 사용하여 SHA256 트리 해시를 계산할 준비가 되어있어야 합니다.

다음 절차에서는 `initiate-multipart-upload`, `upload-multipart-part`및 `complete-multipart-upload` AWS CLI 명령을 사용합니다.

이 명령에 대한 자세한 내용은 **AWS CLI 명령 참조의 [https://docs.aws.amazon.com/cli/latest/reference/glacier/initiate-multipart-upload.html](https://docs.aws.amazon.com/cli/latest/reference/glacier/initiate-multipart-upload.html), [https://docs.aws.amazon.com/cli/latest/reference/glacier/upload-multipart-part.html](https://docs.aws.amazon.com/cli/latest/reference/glacier/upload-multipart-part.html), [https://docs.aws.amazon.com/cli/latest/reference/glacier/complete-multipart-upload.html](https://docs.aws.amazon.com/cli/latest/reference/glacier/complete-multipart-upload.html) 섹션을 참조하세요.

1. [https://docs.aws.amazon.com/cli/latest/reference/glacier/initiate-multipart-upload.html](https://docs.aws.amazon.com/cli/latest/reference/glacier/initiate-multipart-upload.html) 명령을 사용하여 멀티파트 업로드 리소스를 생성합니다. 요청에서 파트 크기를 바이트 수로 지정합니다. 마지막 파트를 제외하고 사용자가 업로드한 파트는 여기에서 지정하는 크기를 따라야 합니다. 멀티파트 업로드를 시작할 때 전체 아카이브 크기를 알 필요는 없습니다. 하지만 최종 단계에서 업로드를 완료할 때는 각 파트의 총 크기가 바이트로 필요합니다.

   다음 명령에서 `--vault-name` 및 `--account-ID` 파라미터의 값을 사용자의 정보로 바꿉니다. 이 명령은 파트 크기가 파일당 1메비바이트(MiB)(1024 x 1024바이트)인 아카이브를 업로드하도록 지정합니다. 필요한 경우 이 `--part-size` 파라미터 값을 바꾸세요.

   ```
   aws glacier initiate-multipart-upload --vault-name awsexamplevault --part-size 1048576 --account-id 123456789012
   ```

   예상 결과:

   ```
   {
   "location": "/123456789012/vaults/awsexamplevault/multipart-uploads/uploadId",
   "uploadId": "uploadId"
   }
   ```

   완료되면 이 명령은 멀티파트 업로드 리소스의 업로드 ID와 Amazon Glacier 내의 위치를 출력합니다. 이후 단계에서 이 업로드 ID를 사용합니다.

1. 이 예시에서는 다음 명령을 사용하여 4.4MiB 파일을 만들고 1MiB 청크로 분할한 다음 각 청크를 업로드할 수 있습니다. 자체 파일을 업로드하려면 데이터를 청크로 분할하고 각 파트를 업로드하는 비슷한 절차를 따를 수 있습니다.

   

**Linux 또는 macOS**  
다음 명령은 Linux 또는 macOS에서 `file_to_upload`로 이름이 지정된 4.4MiB 파일을 만듭니다.

   ```
   mkfile -n 9000b file_to_upload
   ```

**Windows**  
다음 명령은 Windows에서 `file_to_upload`로 이름이 지정된 4.4MiB 파일을 만듭니다.

   ```
   fsutil file createnew file_to_upload 4608000
   ```

1. 다음으로 이 파일을 1MiB 청크로 분할합니다.

   ```
   split -b 1048576 file_to_upload chunk
   ```

   이제 다음과 같은 다섯 개의 청크가 있습니다. 처음 네 개는 1MiB이고 마지막 한 개는 약 400키비바이트(KiB)입니다.

   ```
   chunkaa
   chunkab
   chunkac
   chunkad
   chunkae
   ```

1. [https://docs.aws.amazon.com/cli/latest/reference/glacier/upload-multipart-part.html](https://docs.aws.amazon.com/cli/latest/reference/glacier/upload-multipart-part.html) 명령을 사용하여 아카이브의 파트를 업로드합니다. 아카이브를 파트를 어떤 순서로든 업로드할 수 있습니다. 또한 병렬 방식으로 파트를 업로드할 수도 있습니다. 멀티파트 업로드에서 업로드할 수 있는 파트 수는 최대 10,000개입니다.

   다음 명령에서 `--vault-name`, `--account-ID`, 및 `--upload-id` 파라미터 값을 바꿉니다. 업로드 ID는 `initiate-multipart-upload` 명령 출력으로 제공된 ID와 일치해야 합니다. `--range` 파라미터는 크기가 1MiB(1024 x 1024바이트)인 파트를 업로드하도록 지정합니다. 이 크기는 `initiate-multipart-upload` 명령에서 지정한 크기와 일치해야 합니다. 필요한 경우 크기 값을 조정하세요. `--body` 파라미터는 업로드하는 파트의 이름을 지정합니다.

   ```
   aws glacier upload-multipart-part --body chunkaa --range='bytes 0-1048575/*' --vault-name awsexamplevault --account-id 123456789012 --upload-id upload_ID
   ```

   성공하면 명령에서 업로드된 파트의 체크섬이 포함된 출력이 생성됩니다.

1. `upload-multipart-part` 명령을 다시 실행하여 멀티파트 업로드의 나머지 파트를 업로드합니다. 업로드하는 부분과 일치하도록 각 명령의 `--range` 및 `–-body` 매개변수 값을 업데이트합니다.

   ```
   aws glacier upload-multipart-part --body chunkab --range='bytes 1048576-2097151/*' --vault-name awsexamplevault --account-id 123456789012 --upload-id upload_ID
   ```

   ```
   aws glacier upload-multipart-part --body chunkac --range='bytes 2097152-3145727/*' --vault-name awsexamplevault --account-id 123456789012 --upload-id upload_ID
   ```

   ```
   aws glacier upload-multipart-part --body chunkad --range='bytes 3145728-4194303/*' --vault-name awsexamplevault --account-id 123456789012 --upload-id upload_ID
   ```

   ```
   aws glacier upload-multipart-part --body chunkae --range='bytes 4194304-4607999/*' --vault-name awsexamplevault --account-id 123456789012 --upload-id upload_ID
   ```
**참고**  
업로드의 마지막 부분이 1MiB 미만이므로 최종 명령의 `--range` 파라미터 값은 그보다 더 작습니다. 성공하면 각 명령에서 업로드된 각 부분에 대한 체크섬이 포함된 출력을 생성합니다.

1. 다음으로 아카이브를 조합하고 업로드를 완료합니다. 아카이브의 전체 크기와 SHA256 트리 해시를 반드시 포함해야 합니다.

   아카이브의 SHA256 트리 해시를 계산하기 위해서 Java, C\$1 또는 Python을 사용할 수 있습니다. 이 예시에서는 Python을 사용합니다. Java 또는 C\$1을 사용하는 방법 지침은 [체크섬 계산](checksum-calculations.md) 섹션을 참조하세요.

   Python 파일 `checksum.py`를 생성하고 다음 코드를 추가합니다. 필요한 경우 원본 파일의 이름을 바꾸세요.

   ```
   from botocore.utils import calculate_tree_hash
   					
   checksum = calculate_tree_hash(open('file_to_upload', 'rb'))
   print(checksum)
   ```

1. `checksum.py`를 실행하여 SHA256 트리 해시를 계산합니다. 다음 해시는 출력과 일치하지 않을 수 있습니다.

   ```
   $ python3 checksum.py
   $ 3d760edb291bfc9d90d35809243de092aea4c47b308290ad12d084f69988ae0c
   ```

1. [https://docs.aws.amazon.com/cli/latest/reference/glacier/complete-multipart-upload.html](https://docs.aws.amazon.com/cli/latest/reference/glacier/complete-multipart-upload.html) 명령을 사용하여 아카이브 업로드를 완료합니다. `--vault-name`, `--account-ID`, `--upload-ID`, 및 `--checksum` 파라미터의 값을 바꿉니다. `--archive` 파라미터 값은 아카이브의 전체 크기를 바이트로 지정합니다. 이 값은 반드시 업로드한 개별 파트 크기의 총합이 되어야 합니다. 필요한 경우 이 값을 바꾸세요.

   ```
   aws glacier complete-multipart-upload --archive-size 4608000 --vault-name awsexamplevault --account-id 123456789012 --upload-id upload_ID --checksum checksum
   ```

   완료되면 명령이 아카이브의 ID, 체크섬 및 Amazon Glacier 내의 위치를 출력합니다.

# Amazon SDK for Java를 사용하여 대용량 아카이브를 파트로 나누어 업로드
<a name="uploading-an-archive-mpu-using-java"></a>

Amazon SDK for Java에서 제공하는 [하이레벨 및 로우레벨 API](using-aws-sdk.md) 둘 모두는 대규모 아카이브를 업로드하는 방법을 제공합니다([Amazon Glacier에 아카이브 업로드](uploading-an-archive.md) 섹션 참조).

 
+ 하이레벨 API는 모든 크기의 아카이브를 업로드하는 데 사용할 수 있는 방법을 제공합니다. 이 방법은 업로드하는 파일에 따라 아카이브를 단일 작업으로 업로드하거나, 혹은 Amazon Glacier(Amazon Glacier)에서 지원되는 멀티파트 업로드 기능을 사용해 아카이브를 여러 파트로 나누어 업로드합니다.
+ 로우레벨 API는 기본 REST 구현에 가깝게 매핑합니다. 따라서 더욱 작은 크기의 아카이브를 단일 작업으로 업로드하는 방법을 제공하거나, 혹은 대용량 아카이브의 경우 멀티파트 업로드를 지원하는 방법 그룹을 제공합니다. 이 섹션에서는 로우레벨 API를 사용하는 대용량 아카이브의 멀티파트 업로드에 대해서 설명합니다.

하이레벨 및 로우레벨 API에 대한 자세한 내용은 [Amazon Glacier AWS SDK for Java 에서 사용](using-aws-sdk-for-java.md) 섹션을 참조하세요.

**Topics**
+ [의 상위 수준 API를 사용하여 대용량 아카이브를 파트로 업로드 AWS SDK for Java](#uploading-an-archive-in-parts-highlevel-using-java)
+ [의 하위 수준 API를 사용하여 대용량 아카이브를 파트로 업로드 AWS SDK for Java](#uploading-an-archive-mpu-using-java-lowlevel)

## 의 상위 수준 API를 사용하여 대용량 아카이브를 파트로 업로드 AWS SDK for Java
<a name="uploading-an-archive-in-parts-highlevel-using-java"></a>

작든 크든 상관없이 하이레벨 API를 사용하여 아카이브를 업로드하는 방법은 동일합니다. 다만 하이레벨 API 방법은 아카이브 크기에 따라 아카이브를 단일 작업으로 업로드할지 아니면 Amazon Glacier에서 제공하는 멀티파트 업로드 API를 사용할지 결정합니다. 자세한 내용은 [의 상위 수준 API를 사용하여 아카이브 업로드 AWS SDK for Java](uploading-an-archive-single-op-using-java.md#uploading-an-archive-single-op-high-level-using-java) 단원을 참조하십시오.

## 의 하위 수준 API를 사용하여 대용량 아카이브를 파트로 업로드 AWS SDK for Java
<a name="uploading-an-archive-mpu-using-java-lowlevel"></a>

업로드를 세분화하여 제어할 때는 로우레벨 API를 사용하여 요청을 구성하고 응답을 처리할 수 있습니다. 다음은 AWS SDK for Java을 사용하여 대용량 아카이브를 여러 파트로 나누어 업로드하는 단계입니다.

 

1. `AmazonGlacierClient` 클래스(클라이언트)의 인스턴스를 만듭니다.

   아카이브를 저장할 AWS 리전을 지정해야 합니다. 이 클라이언트를 사용하여 수행하는 모든 작업은 해당 AWS 리전에 적용됩니다.

1. `initiateMultipartUpload` 메서드를 호출하여 멀티파트 업로드를 시작합니다.

   아카이브를 업로드할 볼트 이름과 아카이브를 여러 파트로 나누어 업로드하는 데 사용할 파트 크기, 그리고 설명(옵션)을 입력해야 합니다. `InitiateMultipartUploadRequest` 클래스의 인스턴스를 만들어 이 정보를 제공합니다. 그러면 Amazon Glacier가 응답으로 업로드 ID를 반환합니다.

1. `uploadMultipartPart` 메서드를 호출하여 각 파트를 업로드합니다.

   업로드하는 파트마다 볼트 이름, 현재 파트에서 업로드할 최종 아카이브의 바이트 범위, 파트 데이터의 체크섬, 그리고 업로드 ID를 입력해야 합니다.

1. `completeMultipartUpload` 메서드를 호출하여 멀티파트 업로드를 마칩니다.

   이때는 업로드 ID, 전체 아카이브의 체크섬, 아카이브 크기(업로드한 모든 파트의 총 크기), 그리고 볼트 이름을 입력해야 합니다. Amazon Glacier는 업로드된 파트부터 아카이브를 구성하여 아카이브 ID를 반환합니다.

### 예:를 사용하여 대용량 아카이브를 파트에 업로드 AWS SDK for Java
<a name="upload-archive-mpu-java-example"></a>

다음 Java 코드 예제에서는 AWS SDK for Java 를 사용하여 아카이브를 볼트()에 업로드합니다`examplevault`. 이 예제의 실행 방법에 대한 단계별 지침은 [Eclipse를 사용하여 Amazon Glacier의 Java 예 실행](using-aws-sdk-for-java.md#setting-up-and-testing-sdk-java) 섹션을 참조하세요. 아래와 같이 업로드할 파일 이름을 사용해 코드를 업데이트해야 합니다.

 

**참고**  
아래 예제는 파트 크기가 1MB\$11GB일 때 유효합니다. 하지만 Amazon Glacier는 최대 4GB 크기의 파트를 지원합니다.

**Example**  

```
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.TreeHashGenerator;
import com.amazonaws.services.glacier.model.CompleteMultipartUploadRequest;
import com.amazonaws.services.glacier.model.CompleteMultipartUploadResult;
import com.amazonaws.services.glacier.model.InitiateMultipartUploadRequest;
import com.amazonaws.services.glacier.model.InitiateMultipartUploadResult;
import com.amazonaws.services.glacier.model.UploadMultipartPartRequest;
import com.amazonaws.services.glacier.model.UploadMultipartPartResult;
import com.amazonaws.util.BinaryUtils;

public class ArchiveMPU {

    public static String vaultName = "examplevault";
    // This example works for part sizes up to 1 GB.
    public static String partSize = "1048576"; // 1 MB.
    public static String archiveFilePath = "*** provide archive file path ***";
    public static AmazonGlacierClient client;
    
    public static void main(String[] args) throws IOException {

    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();

        client = new AmazonGlacierClient(credentials);
        client.setEndpoint("https://glacier.us-west-2.amazonaws.com/");

        try {
            System.out.println("Uploading an archive.");
            String uploadId = initiateMultipartUpload();
            String checksum = uploadParts(uploadId);
            String archiveId = CompleteMultiPartUpload(uploadId, checksum);
            System.out.println("Completed an archive. ArchiveId: " + archiveId);
            
        } catch (Exception e) {
            System.err.println(e);
        }

    }
    
    private static String initiateMultipartUpload() {
        // Initiate
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest()
            .withVaultName(vaultName)
            .withArchiveDescription("my archive " + (new Date()))
            .withPartSize(partSize);            
        
        InitiateMultipartUploadResult result = client.initiateMultipartUpload(request);
        
        System.out.println("ArchiveID: " + result.getUploadId());
        return result.getUploadId();
    }

    private static String uploadParts(String uploadId) throws AmazonServiceException, NoSuchAlgorithmException, AmazonClientException, IOException {

        int filePosition = 0;
        long currentPosition = 0;
        byte[] buffer = new byte[Integer.valueOf(partSize)];
        List<byte[]> binaryChecksums = new LinkedList<byte[]>();
        
        File file = new File(archiveFilePath);
        FileInputStream fileToUpload = new FileInputStream(file);
        String contentRange;
        int read = 0;
        while (currentPosition < file.length())
        {
            read = fileToUpload.read(buffer, filePosition, buffer.length);
            if (read == -1) { break; }
            byte[] bytesRead = Arrays.copyOf(buffer, read);

            contentRange = String.format("bytes %s-%s/*", currentPosition, currentPosition + read - 1);
            String checksum = TreeHashGenerator.calculateTreeHash(new ByteArrayInputStream(bytesRead));
            byte[] binaryChecksum = BinaryUtils.fromHex(checksum);
            binaryChecksums.add(binaryChecksum);
            System.out.println(contentRange);
                        
            //Upload part.
            UploadMultipartPartRequest partRequest = new UploadMultipartPartRequest()
            .withVaultName(vaultName)
            .withBody(new ByteArrayInputStream(bytesRead))
            .withChecksum(checksum)
            .withRange(contentRange)
            .withUploadId(uploadId);               
        
            UploadMultipartPartResult partResult = client.uploadMultipartPart(partRequest);
            System.out.println("Part uploaded, checksum: " + partResult.getChecksum());
            
            currentPosition = currentPosition + read;
        }
        fileToUpload.close();
        String checksum = TreeHashGenerator.calculateTreeHash(binaryChecksums);
        return checksum;
    }

    private static String CompleteMultiPartUpload(String uploadId, String checksum) throws NoSuchAlgorithmException, IOException {
        
        File file = new File(archiveFilePath);

        CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest()
            .withVaultName(vaultName)
            .withUploadId(uploadId)
            .withChecksum(checksum)
            .withArchiveSize(String.valueOf(file.length()));
        
        CompleteMultipartUploadResult compResult = client.completeMultipartUpload(compRequest);
        return compResult.getLocation();
    }
}
```

# 를 사용하여 대용량 아카이브 업로드 AWS SDK for .NET
<a name="uploading-an-archive-mpu-using-dotnet"></a>

.NET용 Amazon SDK에서 제공하는 [하이레벨 및 로우레벨 API](using-aws-sdk.md) 둘 모두는 대규모 아카이브를 분할하여 업로드하는 방법을 제공합니다([Amazon Glacier에 아카이브 업로드](uploading-an-archive.md) 섹션 참조).

 
+ 하이레벨 API는 모든 크기의 아카이브를 업로드하는 데 사용할 수 있는 방법을 제공합니다. 이 방법은 업로드하는 파일에 따라 아카이브를 단일 작업으로 업로드하거나, 혹은 Amazon Glacier(Amazon Glacier)에서 지원되는 멀티파트 업로드 기능을 사용해 아카이브를 여러 파트로 나누어 업로드합니다.
+ 로우레벨 API는 기본 REST 구현에 가깝게 매핑합니다. 따라서 더욱 작은 크기의 아카이브를 단일 작업으로 업로드하는 방법을 제공하거나, 혹은 대용량 아카이브의 경우 멀티파트 업로드를 지원하는 방법 그룹을 제공합니다. 이 섹션에서는 로우레벨 API를 사용하는 대용량 아카이브의 멀티파트 업로드에 대해서 설명합니다.

하이레벨 및 로우레벨 API에 대한 자세한 내용은 [Amazon Glacier와 함께 AWS SDK for .NET 사용](using-aws-sdk-for-dot-net.md) 섹션을 참조하세요.

**Topics**
+ [의 상위 수준 API를 사용하여 대용량 아카이브를 파트로 업로드 AWS SDK for .NET](#uploading-an-archive-in-parts-highlevel-using-dotnet)
+ [의 하위 수준 API를 사용하여 대용량 아카이브를 파트로 업로드 AWS SDK for .NET](#uploading-an-archive-in-parts-lowlevel-using-dotnet)

## 의 상위 수준 API를 사용하여 대용량 아카이브를 파트로 업로드 AWS SDK for .NET
<a name="uploading-an-archive-in-parts-highlevel-using-dotnet"></a>

작든 크든 상관없이 하이레벨 API를 사용하여 아카이브를 업로드하는 방법은 동일합니다. 다만 하이레벨 API 방법은 아카이브 크기에 따라 아카이브를 단일 작업으로 업로드할지 아니면 Amazon Glacier에서 제공하는 멀티파트 업로드 API를 사용할지 결정합니다. 자세한 내용은 [의 상위 수준 API를 사용하여 아카이브 업로드 AWS SDK for .NET](uploading-an-archive-single-op-using-dotnet.md#uploading-an-archive-single-op-highlevel-using-dotnet) 단원을 참조하십시오.

## 의 하위 수준 API를 사용하여 대용량 아카이브를 파트로 업로드 AWS SDK for .NET
<a name="uploading-an-archive-in-parts-lowlevel-using-dotnet"></a>

업로드를 세분화하여 제어할 때는 로우레벨 API를 사용하여 요청을 구성하고 응답을 처리할 수 있습니다. 다음은 AWS SDK for .NET을 사용하여 대용량 아카이브를 여러 파트로 나누어 업로드하는 단계입니다.

 

1. `AmazonGlacierClient` 클래스(클라이언트)의 인스턴스를 만듭니다.

   아카이브를 저장할 AWS 리전을 지정해야 합니다. 이 클라이언트를 사용하여 수행하는 모든 작업은 해당 AWS 리전에 적용됩니다.

1. `InitiateMultipartUpload` 메서드를 호출하여 멀티파트 업로드를 시작합니다.

   아카이브를 업로드할 볼트 이름과 아카이브를 여러 파트로 나누어 업로드하는 데 사용할 파트 크기, 그리고 설명(옵션)을 입력해야 합니다. `InitiateMultipartUploadRequest` 클래스의 인스턴스를 만들어 이 정보를 제공합니다. 그러면 Amazon Glacier가 응답으로 업로드 ID를 반환합니다.

1. `UploadMultipartPart` 메서드를 호출하여 각 파트를 업로드합니다.

   업로드하는 파트마다 볼트 이름, 현재 파트에서 업로드할 최종 아카이브의 바이트 범위, 파트 데이터의 체크섬, 그리고 업로드 ID를 입력해야 합니다.

1. `CompleteMultipartUpload` 메서드를 호출하여 멀티파트 업로드를 마칩니다.

   업로드 ID, 전체 아카이브의 체크섬, 아카이브 크기(업로드한 모든 파트의 총 크기), 그리고 볼트 이름을 제공해야 합니다. Amazon Glacier는 업로드된 파트부터 아카이브를 구성하여 아카이브 ID를 반환합니다.

### 예: .NET용 Amazon SDK를 사용하여 대용량 아카이브를 파트로 나누어 업로드
<a name="upload-archive-mpu-dotnet-example"></a>

다음 C\$1 코드 예제에서는 AWS SDK for .NET 를 사용하여 아카이브를 볼트()에 업로드합니다`examplevault`. 이 예제의 실행 방법에 대한 단계별 지침은 [코드 예제 실행](using-aws-sdk-for-dot-net.md#setting-up-and-testing-sdk-dotnet) 섹션을 참조하세요. 아래와 같이 업로드할 파일 이름을 사용해 코드를 업데이트해야 합니다.

**Example**  

```
using System;
using System.Collections.Generic;
using System.IO;
using Amazon.Glacier;
using Amazon.Glacier.Model;
using Amazon.Runtime;

namespace glacier.amazon.com.rproxy.govskope.us.docsamples
{
  class ArchiveUploadMPU
  {
    static string vaultName       = "examplevault";
    static string archiveToUpload = "*** Provide file name (with full path) to upload ***";
    static long partSize          = 4194304; // 4 MB.

    public static void Main(string[] args)
    {
      AmazonGlacierClient client;
      List<string> partChecksumList = new List<string>();
      try
      {
         using (client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2)) 
        {
          Console.WriteLine("Uploading an archive.");
          string uploadId  = InitiateMultipartUpload(client);
          partChecksumList = UploadParts(uploadId, client);
          string archiveId = CompleteMPU(uploadId, client, partChecksumList);
          Console.WriteLine("Archive ID: {0}", archiveId);
        }
        Console.WriteLine("Operations successful. To continue, press Enter");
        Console.ReadKey();
      }
      catch (AmazonGlacierException e) { Console.WriteLine(e.Message); }
      catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
      catch (Exception e) { Console.WriteLine(e.Message); }
      Console.WriteLine("To continue, press Enter");
      Console.ReadKey();
    }

    static string InitiateMultipartUpload(AmazonGlacierClient client)
    {
      InitiateMultipartUploadRequest initiateMPUrequest = new InitiateMultipartUploadRequest()
      {

        VaultName = vaultName,
        PartSize = partSize,
        ArchiveDescription = "Test doc uploaded using MPU."
      };

      InitiateMultipartUploadResponse initiateMPUresponse = client.InitiateMultipartUpload(initiateMPUrequest);

      return initiateMPUresponse.UploadId;
    }

    static List<string> UploadParts(string uploadID, AmazonGlacierClient client)
    {
      List<string> partChecksumList = new List<string>();
      long currentPosition = 0;
      var buffer = new byte[Convert.ToInt32(partSize)];

      long fileLength = new FileInfo(archiveToUpload).Length;
      using (FileStream fileToUpload = new FileStream(archiveToUpload, FileMode.Open, FileAccess.Read))
      {
        while (fileToUpload.Position < fileLength)
        {
          Stream uploadPartStream = GlacierUtils.CreatePartStream(fileToUpload, partSize);
          string checksum = TreeHashGenerator.CalculateTreeHash(uploadPartStream);
          partChecksumList.Add(checksum);
          // Upload part.
          UploadMultipartPartRequest uploadMPUrequest = new UploadMultipartPartRequest()
          {

            VaultName = vaultName,
            Body = uploadPartStream,
            Checksum = checksum,
            UploadId = uploadID
          };
          uploadMPUrequest.SetRange(currentPosition, currentPosition + uploadPartStream.Length - 1);
          client.UploadMultipartPart(uploadMPUrequest);

          currentPosition = currentPosition + uploadPartStream.Length;
        }
      }
      return partChecksumList;
    }

    static string CompleteMPU(string uploadID, AmazonGlacierClient client, List<string> partChecksumList)
    {
      long fileLength = new FileInfo(archiveToUpload).Length;
      CompleteMultipartUploadRequest completeMPUrequest = new CompleteMultipartUploadRequest()
      {
        UploadId = uploadID,
        ArchiveSize = fileLength.ToString(),
        Checksum = TreeHashGenerator.CalculateTreeHash(partChecksumList),
        VaultName = vaultName
      };

      CompleteMultipartUploadResponse completeMPUresponse = client.CompleteMultipartUpload(completeMPUrequest);
      return completeMPUresponse.ArchiveId;
    }
  }
}
```

# REST API를 사용하는 대용량 아카이브의 멀티파트 업로드
<a name="uploading-an-archive-mpu-using-rest"></a>

[대용량 아카이브를 여러 파트로 나누어 업로드(멀티파트 업로드)](uploading-archive-mpu.md)에서 설명한 것과 같이 멀티파트 업로드는 아카이브를 여러 파트로 나누어 업로드하는 작업을 말하며 관련 작업을 수행합니다. 이러한 작업들에 대한 자세한 내용은 API 참조 항목을 참조하세요.

 
+ [멀티파트 업로드 시작(POST multipart-uploads)](api-multipart-initiate-upload.md)
+ [파트 업로드(PUT uploadID)](api-upload-part.md)
+ [멀티파트 업로드 완료(POST uploadID)](api-multipart-complete-upload.md)
+ [멀티파트 업로드 중단(DELETE uploadID)](api-multipart-abort-upload.md)
+ [파트 목록 조회(GET uploadID)](api-multipart-list-parts.md)
+ [멀티파트 업로드 목록 조회(GET multipart-uploads)](api-multipart-list-uploads.md)

# Amazon Glacier에서 아카이브 다운로드
<a name="downloading-an-archive"></a>

Amazon Glacier는 볼트 생성 및 삭제에 사용할 수 있는 관리 콘솔을 제공합니다. 하지만 관리 콘솔을 이용하여 Amazon Glacier에서 아카이브를 다운로드할 수는 없습니다. 사진, 비디오 및 기타 문서와 같은 데이터를 다운로드하려면 REST API를 직접 사용하거나 AWS SDKs를 사용하여 AWS Command Line Interface (AWS CLI)를 사용하거나 코드를 작성하여 요청해야 합니다.

에서 Amazon Glacier를 사용하는 방법에 대한 자세한 내용은 Amazon Glacier 참조를 AWS CLI참조하세요. [AWS CLI Amazon Glacier](https://docs.aws.amazon.com/cli/latest/reference/glacier/index.html) 를 설치하려면 단원을 AWS CLI참조하십시오[AWS Command Line Interface](https://aws.amazon.com/cli/). 다음 주제에서는 AWS SDK for Java AWS SDK for .NET, 및 Amazon Glacier REST API를 사용하여 Amazon Glacier에 아카이브를 다운로드하는 방법을 설명합니다.

**Topics**
+ [Amazon Glacier 아카이브 가져오기](downloading-an-archive-two-steps.md)
+ [를 사용하여 Amazon Glacier에서 아카이브 다운로드 AWS SDK for Java](downloading-an-archive-using-java.md)
+ [를 사용하여 Amazon Glacier에서 아카이브 다운로드 AWS SDK for .NET](downloading-an-archive-using-dotnet.md)
+ [Python을 통한 병렬 처리를 사용하여 대용량 아카이브 다운로드](downloading-large-archive-parallel-python.md)
+ [REST API를 사용하여 아카이브 다운로드](downloading-an-archive-using-rest.md)
+ [를 사용하여 Amazon Glacier에서 아카이브 다운로드 AWS CLI](downloading-an-archive-using-cli.md)

# Amazon Glacier 아카이브 가져오기
<a name="downloading-an-archive-two-steps"></a>

Amazon Glacier에서 아카이브를 가져오는 것은 비동기식 작업이기 때문에 먼저 작업을 시작하고 작업이 완료된 후에 출력을 다운로드합니다. 아카이브 가져오기 작업을 시작하려면 [작업 시작(POST jobs)](api-initiate-job-post.md) REST API 작업 또는 AWS CLI, 또는 AWS SDKs의 해당 작업을 사용합니다.

**Topics**
+ [아카이브 검색 옵션](#api-downloading-an-archive-two-steps-retrieval-options)
+ [범위가 지정된 아카이브 가져오기](#downloading-an-archive-range)

Amazon Glacier에서 아카이브를 가져오는 작업은 2단계 프로세스로 구성됩니다. 다음은 이 프로세스의 개요입니다.

**아카이브를 가져오려면**

1. 아카이브 가져오기 작업을 시작합니다.

   1. 원하는 아카이브의 ID를 가져옵니다. 아카이브 ID는 볼트 인벤토리에서 가져올 수 있습니다. REST API, AWS CLI또는 AWS SDKs. 자세한 내용은 [Amazon Glacier에서 볼트 인벤토리 다운로드](vault-inventory.md) 단원을 참조하십시오.

   1. [작업 시작(POST jobs)](api-initiate-job-post.md) 작업을 사용하여 Amazon Glacier에 후속 다운로드를 위해서 아카이브 전체 또는 일부분을 준비하도록 요청하는 작업을 시작합니다.

   작업을 시작하면 Amazon Glacier는 응답으로 작업 ID를 반환하고 비동기식으로 작업을 실행합니다. (2단계에서 설명된 것과 같이 작업이 끝날 때까지는 작업 출력을 다운로드할 수 없습니다.)
**중요**  
표준 검색에 한해서 데이터 검색 정책은 `PolicyEnforcedException` 예외에 따라 `Initiate Job` 요청이 실패하는 원인이 될 수 있습니다. 데이터 가져오기 정책에 대한 자세한 내용은 [Amazon Glacier 데이터 검색 정책](data-retrieval-policy.md) 섹션을 참조하세요. `PolicyEnforcedException` 예외에 대한 자세한 내용은 [오류 응답](api-error-responses.md) 섹션을 참조하세요.

   필요한 경우 Amazon Glacier에 저장된 대용량 데이터 세그먼트를 복원할 수 있습니다. Amazon Glacier 스토리지 클래스에서 데이터를 복원하는 방법에 대한 자세한 내용은 *Amazon Simple Storage Service 사용 설명서*의 [객체 아카이빙을 위한 스토리지 클래스]( https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html#sc-glacier)를 참조하세요.

1. 작업이 완료된 후 [작업 출력 가져오기(GET output)](api-job-output-get.md) 작업을 사용하여 바이트를 다운로드합니다.

   바이트 전체를 다운로드하거나, 혹은 바이트 범위를 지정하여 작업 출력의 일부만 다운로드할 수 있습니다. 출력 용량이 클수록 네트워크 장애 같은 다운로드 오류가 발생할 경우를 대비해 청크 단위로 다운로드하는 것이 효과적입니다. 단일 요청으로 작업을 출력하다가 네트워크 장애가 발생하면 출력을 처음부터 다시 다운로드해야 합니다. 하지만 청크 단위로 출력을 다운로드할 경우에는 장애가 발생하더라도 전체가 아닌 일부 출력만 다시 다운로드하면 됩니다.

Amazon Glacier에서는 출력을 다운로드하려면 작업을 먼저 마쳐야 합니다. 작업 완료 후 최소 24시간까지는 작업이 만료되지 않습니다. 이 말은 작업 완료 후 24시간까지는 출력을 다운로드할 수 있다는 것을 의미합니다. 복원은 작업 완료 후 24시간이 지나면 언제든지 만료될 수 있습니다. 작업 완료 여부를 알고 싶다면 다음 옵션 중 한 가지를 사용하여 상태를 확인합니다.
+ **작업 완료 알림 대기**: Amazon Glacier가 작업 완료 후에도 알림 메시지를 게시할 수 있도록 Amazon Simple Notification Service(Amazon SNS) 토픽을 지정합니다. Amazon Glacier는 작업이 완료된 후에만 알림을 보냅니다.

  Amazon SNS 토픽은 작업을 시작할 때 지정할 수 있습니다. 작업 요청 시 Amazon SNS 토픽을 지정하는 방법 외에 아카이브 가져오기 이벤트에 대한 알림이 볼트에 설정되어 있는 경우에도 Amazon Glacier가 알림 메시지를 해당하는 SNS 토픽에 게시합니다. 자세한 내용은 [Amazon Glacier의 볼트 알림 구성](configuring-notifications.md) 단원을 참조하십시오.
+ **명시적인 작업 정보 요청**: Amazon Glacier `Describe Job` API 작업([작업 설명(GET JobID)](api-describe-job-get.md))을 사용하여 작업 정보를 주기적으로 폴링할 수도 있습니다. 하지만 Amazon SNS 알림 메시지의 사용을 권장합니다.

**참고**  
Amazon SNS 알림을 사용하여 가져오는 정보는 `Describe Job` API 작업을 직접 호출하여 가져오는 정보와 동일합니다.

## 아카이브 검색 옵션
<a name="api-downloading-an-archive-two-steps-retrieval-options"></a>

아카이브 검색 작업을 시작할 때 액세스 시간과 비용 요건을 기준으로 다음 중 한 가지 검색 옵션을 지정할 수 있습니다. 검색 요금에 대한 자세한 내용은 [Amazon Glacier 요금](https://aws.amazon.com/s3/glacier/pricing/)을 참조하세요.
+ **신속**: 아카이브의 복원을 위한 임시 긴급 요청이 필요한 경우 신속 검색을 사용하면 S3 Glacier Flexible 검색 스토리지 클래스 또는 S3 Intelligent-Tiering 아카이브 액세스 티어에 저장된 데이터에 빠르게 액세스할 수 있습니다. 매우 큰 아카이브(250MB 이상)를 제외한 모든 경우, 신속 검색을 사용하여 액세스된 데이터는 일반적으로 1\$15분 안에 사용할 수 있습니다. 프로비저닝된 용량을 통해 필요할 때 신속 검색에 대한 검색 용량이 보장됩니다. 자세한 내용은 [프로비저닝된 용량](#api-downloading-an-archive-two-steps-retrieval-expedited-capacity) 단원을 참조하십시오.
+ **표준**: 표준 검색을 사용하면 몇 시간 내에 아카이브에 액세스할 수 있습니다. 표준 검색은 보통 3\$15시간 안에 완료됩니다. 검색 요청 시 검색 옵션을 지정하지 않을 경우 스탠다드가 기본 옵션이 됩니다.
+ **대량**: 대량 검색은 Amazon Glacier에서 가장 저렴한 검색 옵션으로 대용량 데이터, 심지어는 페타바이트 규모까지도 저렴한 비용으로 하루만에 검색할 수 있습니다. 대량 검색은 보통 5\$112시간 안에 완료됩니다.

다음 테이블에는 아카이브 검색 옵션이 요약되어 있습니다. 요금에 대한 자세한 정보는 [Amazon Glacier 요금](https://aws.amazon.com/s3/glacier/pricing/)을 참조하세요.


| 서비스 | 신속 | 표준 | 대량 | 
| --- | --- | --- | --- | 
|  Amazon Glacier  |  1\$15분  |  3\$15시간  |  5\$112시간  | 

`Expedited`, `Standard`또는 `Bulk` 검색을 수행하려면 [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOSTrestore.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOSTrestore.html) REST API 작업 요청의 `Tier` 요청 요소를 원하는 옵션 또는 AWS Command Line Interface (AWS CLI) 또는 AWS SDKs의 동등한 옵션으로 설정합니다. 프로비저닝된 용량을 구매하였다면, 사용자의 프로비저닝된 용량을 통해 모든 신속 검색이 자동으로 수행됩니다.

### 프로비저닝된 용량
<a name="api-downloading-an-archive-two-steps-retrieval-expedited-capacity"></a>

프로비저닝된 용량으로 필요시에 신속 검색을 위한 검색 용량을 보장합니다. 각 용량 단위로 초당 최대 150메가바이트(MBps)의 검색 처리량이 제공되고 매 5분마다 긴급 검색을 최소 3회 수행할 수 있습니다.

워크로드에 몇 분 내로 데이터의 서브셋에 대한 신뢰성 높고 예측 가능한 액세스가 필요한 경우 프로비저닝된 검색 용량을 구매를 권장합니다. 프로비저닝된 검색 용량이 없더라도 비정상적으로 수요가 높지 않은 경우를 제외하면 일반적으로 신속 검색은 허용됩니다. 하지만 모든 상황에서 신속 검색에 액세스해야 하는 경우 프로비저닝된 검색 용량을 구매해야 합니다.

#### 프로비저닝된 용량 구매
<a name="downloading-an-archive-purchase-provisioned-capacity"></a>

Amazon Glacier 콘솔, [프로비저닝된 용량 구매(POST provisioned-capacity)](api-PurchaseProvisionedCapacity.md) REST API 작업, AWS SDKs 또는를 사용하여 프로비저닝된 용량 단위를 구매할 수 있습니다 AWS CLI. 프로비저닝된 용량의 요금에 대한 자세한 내용은 [Amazon Glacier 요금](https://aws.amazon.com/s3/glacier/pricing/)을 참조하세요.

프로비저닝된 용량 단위는 구매한 날짜 및 시간으로부터 1개월간 지속됩니다.

시작 날짜가 31일인 경우에는 만료 날짜는 다음 달 말일이 됩니다. 예를 들어 시작 날짜가 8월 31일이라면 만료 날짜는 9월 30일입니다. 시작 날짜가 1월 31일이라면 만료 날짜는 2월 28일입니다.

**Amazon Glacier 콘솔을 사용하여 프로비저닝된 용량 구매**

1.  에 로그인 AWS Management Console 하고 [https://console.aws.amazon.com/glacier/home](https://console.aws.amazon.com/glacier/home) Amazon Glacier 콘솔을 엽니다.

1. 왼쪽의 탐색 창에서 **데이터 검색 설정**을 선택합니다.

1. **프로비저닝된 용량 단위(PCU)**에서 **PCU 구매**를 선택합니다. **PCU 구매** 대화 상자가 나타납니다.

1. 프로비저닝된 용량을 구매하려는 경우 **구매 확인** 상자에 **confirm**을 입력합니다.

1.  **PCU 구매**를 선택합니다.

## 범위가 지정된 아카이브 가져오기
<a name="downloading-an-archive-range"></a>

Amazon Glacier에서 아카이브를 검색할 때는 선택사항으로 검색할 아카이브의 범위 및 부분을 지정할 수 있습니다. 기본적으로는 아카이브 전체를 가져오도록 되어 있습니다. 바이트 범위 지정은 다음과 같은 경우에 유용합니다.
+ **데이터 다운로드 관리**: Amazon Glacier는 검색 요청 완료 후 24시간 동안 검색한 데이터를 다운로드할 수 있도록 합니다. 따라서 다운로드 기간 내에 다운로드 일정을 관리할 수 있도록 아카이브에서 일부 구간만 가져올 수도 있습니다.
+ **대용량 아카이브의 타게팅된 부분만 검색**: 예를 들어, 이전에 다수의 파일을 집계하여 단일 아카이브로 업로드하였지만 지금 그 파일 중 일부만 검색하려고 하는 경우입니다. 이때는 검색 요청 한 번으로 원하는 파일이 저장된 아카이브 범위를 지정할 수 있습니다. 그렇지 않으면 가져오기 요청을 여러 차례 시작하면서 매번 1개 이상의 파일 범위를 지정해야 합니다.

범위 가져오기를 사용하여 작업을 시작할 때는 메가바이트로 정렬된 범위를 입력해야 합니다. 다시 말해서 바이트 범위는 0부터 시작하거나(아카이브의 시작 부분) 혹은 1MB 간격으로(1MB, 2MB, 3MB 등) 시작할 수 있습니다.

범위의 끝은 아카이브의 끝이거나, 범위 시작보다 1MB 단위로 큰 모든 범위일 수 있습니다. 또한 데이터를 다운로드할 때(검색 작업 완료 후) 체크섬 값까지 원하는 경우에는 작업 시작 시 요청한 범위가 트리-해시로 정렬되어야 합니다. 체크섬은 전송 중에 데이터가 손상되지 않았는지 확인할 수 있는 방법입니다. 메가바이트 정렬 및 트리-해시 정렬에 대한 자세한 내용은 [데이터 다운로드 시 체크섬 수신](checksum-calculations-range.md) 섹션을 참조하세요.

# 를 사용하여 Amazon Glacier에서 아카이브 다운로드 AWS SDK for Java
<a name="downloading-an-archive-using-java"></a>

Amazon SDK for Java에서 제공하는 [하이레벨 및 로우레벨 API](using-aws-sdk.md) 둘 모두는 아카이브를 다운로드하는 방법을 제공합니다.

**Topics**
+ [의 상위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for Java](#downloading-an-archive-using-java-highlevel-api)
+ [의 하위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for Java](#downloading-an-archive-using-java-lowlevel-api)

## 의 상위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for Java
<a name="downloading-an-archive-using-java-highlevel-api"></a>

하이레벨 API의 `ArchiveTransferManager` 클래스는 아카이브를 다운로드하는 데 사용할 수 있는 `download` 메서드를 제공합니다.

**중요**  
`ArchiveTransferManager` 클래스는 Amazon Simple Notification Service(SNS) 토픽 및 해당 토픽을 구독하는 Amazon Simple Queue Service(Amazon SQS) 대기열을 생성합니다. 그런 다음 아카이브 가져오기 작업을 시작하고 아카이브를 사용할 수 있도록 대기열을 폴링합니다. 아카이브를 사용할 수 있게 되면 다운로드가 시작됩니다. 검색 시간에 대한 자세한 내용은 [아카이브 검색 옵션](downloading-an-archive-two-steps.md#api-downloading-an-archive-two-steps-retrieval-options) 섹션을 참조하세요.

### 예:의 상위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for Java
<a name="download-archives-java-highlevel-example"></a>

다음은 미국 서부(오레곤) 리전(`us-west-2`)의 볼트(`examplevault`)에서 아카이브를 다운로드하는 Java 코드 예시입니다.

이번 샘플 실행에 대한 단계별 지침은 [Eclipse를 사용하여 Amazon Glacier의 Java 예 실행](using-aws-sdk-for-java.md#setting-up-and-testing-sdk-java) 섹션을 참조하세요. 코드는 기존 아카이브 ID와 다운로드한 아카이브를 저장할 로컬 파일 경로를 사용해 아래와 같이 업데이트해야 합니다.

**Example**  

```
import java.io.File;
import java.io.IOException;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.transfer.ArchiveTransferManager;
import com.amazonaws.services.sns.AmazonSNSClient;
import com.amazonaws.services.sqs.AmazonSQSClient;


public class ArchiveDownloadHighLevel {
    public static String vaultName = "examplevault";
    public static String archiveId = "*** provide archive ID ***";
    public static String downloadFilePath  = "*** provide location to download archive ***";
    
    public static AmazonGlacierClient glacierClient;
    public static AmazonSQSClient sqsClient;
    public static AmazonSNSClient snsClient;
    
    public static void main(String[] args) throws IOException {
        
    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();
        
        glacierClient = new AmazonGlacierClient(credentials);
        
        sqsClient = new AmazonSQSClient(credentials);
        snsClient = new AmazonSNSClient(credentials);
        glacierClient.setEndpoint("glacier.us-west-2.amazonaws.com");
        sqsClient.setEndpoint("sqs.us-west-2.amazonaws.com");
        snsClient.setEndpoint("sns.us-west-2.amazonaws.com");

        try {
            ArchiveTransferManager atm = new ArchiveTransferManager(glacierClient, sqsClient, snsClient);
            
            atm.download(vaultName, archiveId, new File(downloadFilePath));
            System.out.println("Downloaded file to " + downloadFilePath);
            
        } catch (Exception e)
        {
            System.err.println(e);
        }
    }
}
```

## 의 하위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for Java
<a name="downloading-an-archive-using-java-lowlevel-api"></a>

다음은 AWS SDK for Java 로우레벨 API를 사용해 볼트 인벤토리를 가져오는 단계입니다.

 

1. `AmazonGlacierClient` 클래스(클라이언트)의 인스턴스를 만듭니다.

   아카이브를 다운로드할 AWS 리전을 지정해야 합니다. 이 클라이언트를 사용하여 수행하는 모든 작업은 해당 AWS 리전에 적용됩니다.

1. `initiateJob` 메서드를 실행하여 `archive-retrieval` 작업을 시작합니다.

   `InitiateJobRequest` 클래스 인스턴스를 생성하여 다운로드를 원하는 아카이브의 ID, Amazon Glacier(Amazon Glacier)가 작업 완료 메시지를 게시할 Amazon SNS 토픽(옵션) 등 작업 정보를 입력합니다. Amazon Glacier는 응답으로 작업 ID를 반환합니다. 이 응답은 `InitiateJobResult` 클래스 인스턴스에서 사용할 수 있습니다.

    

   ```
   JobParameters jobParameters = new JobParameters()
       .withArchiveId("*** provide an archive id ***")
       .withDescription("archive retrieval")
       .withRetrievalByteRange("*** provide a retrieval range***") // optional
       .withType("archive-retrieval");
   
   InitiateJobResult initiateJobResult = client.initiateJob(new InitiateJobRequest()
       .withJobParameters(jobParameters)
       .withVaultName(vaultName));  
             
   String jobId = initiateJobResult.getJobId();
   ```

   선택적으로 바이트 범위를 지정하여 Amazon Glacier가 아카이브의 일부만 준비하도록 요청할 수 있습니다. 예를 들어 다음 문을 요청에 추가하면 Amazon Glacier가 아카이브 중 1MB\$12MB만 준비하도록 요청하여 이전 요청을 업데이트할 수 있습니다.

    

   ```
   int ONE_MEG = 1048576;
   String retrievalByteRange = String.format("%s-%s", ONE_MEG, 2*ONE_MEG -1);
   
   JobParameters jobParameters = new JobParameters()
       .withType("archive-retrieval")
       .withArchiveId(archiveId)
       .withRetrievalByteRange(retrievalByteRange) 
       .withSNSTopic(snsTopicARN);
   
   InitiateJobResult initiateJobResult = client.initiateJob(new InitiateJobRequest()
       .withJobParameters(jobParameters)
       .withVaultName(vaultName));  
             
   String jobId = initiateJobResult.getJobId();
   ```

    

1.  작업이 완료될 때까지 기다립니다.

   작업 출력을 다운로드할 수 있을 때까지 기다려야 합니다. 볼트에서 Amazon Simple Notification Service(Amazon SNS) 토픽을 식별할 수 있도록 알림 구성을 설정했거나 작업을 시작할 때 Amazon SNS 토픽을 지정했다면 Amazon Glacier가 작업 완료 후 해당 토픽에 메시지를 보냅니다.

   `describeJob` 메서드를 직접 호출하여 Amazon Glacier를 폴링함으로써 작업 완료 상태를 확인하는 방법도 있습니다. 하지만 Amazon SNS 토픽의 알람을 사용해 식별하는 방법을 권장합니다.

1. `getJobOutput` 메서드를 실행하여 작업 출력(아카이브 데이터)을 다운로드합니다.

   `GetJobOutputRequest` 클래스 인스턴스를 생성하여 작업 ID, 볼트 이름 등 요청 정보를 입력합니다. Amazon Glacier가 반환하는 출력은 `GetJobOutputResult` 객체에서 사용할 수 있습니다.

    

   ```
   GetJobOutputRequest jobOutputRequest = new GetJobOutputRequest()
           .withJobId("*** provide a job ID ***")
           .withVaultName("*** provide a vault name ****");
   GetJobOutputResult jobOutputResult = client.getJobOutput(jobOutputRequest);
   
   // jobOutputResult.getBody() // Provides the input stream.
   ```

   위의 코드 조각은 전체 작업 출력을 다운로드합니다. 옵션으로 `GetJobOutputRequest`에서 바이트 범위를 지정하여 출력 일부만 가져오거나 전체 출력을 더 작은 청크 단위로 나누어 다운로드할 수 있습니다.

    

   ```
   GetJobOutputRequest jobOutputRequest = new GetJobOutputRequest()
           .withJobId("*** provide a job ID ***")
           .withRange("bytes=0-1048575")   // Download only the first 1 MB of the output.
           .withVaultName("*** provide a vault name ****");
   ```

   특정 조건이 충족된다면 Amazon Glacier가 `GetJobOutput` 직접 호출에 대한 응답으로 다운로드한 데이터 일부의 체크섬을 반환합니다. 자세한 내용은 [데이터 다운로드 시 체크섬 수신](checksum-calculations-range.md) 단원을 참조하십시오.

   다운로드에 오류가 없는지 확인하려면 클라이언트 측 체크섬을 계산한 뒤 Amazon Glacier가 응답으로 보내는 체크섬과 비교합니다.

   아카이브 가져오기 작업에서 옵션으로 범위를 지정한 경우에는 작업 설명에 가져오는 범위의 체크섬도 포함됩니다(SHA256TreeHash). 이 값은 나중에 다운로드하는 전체 바이트 범위의 정확성을 검증하는 데도 사용할 수 있습니다. 예를 들어 트리-해시로 정렬된 아카이브 범위를 가져오는 작업을 시작하면서 `GetJobOutput` 요청이 각각 체크섬을 반환할 수 있도록 청크 단위로 출력을 다운로드하는 경우에는 클라이언트 측에서 다운로드하는 개별 데이터의 체크섬을 계산하고 나서 트리 해시를 계산할 수 있습니다. Amazon Glacier가 작업 설명 요청에 대한 응답으로 반환하는 체크섬과 비교하여 사용자가 다운로드한 전체 바이트 범위가 Amazon Glacier에 저장된 바이트 범위와 일치하는지 확인할 수 있습니다.

    사용 가능한 예제는 [예제 2:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for Java- 청크 단위로 출력 다운로드](#downloading-an-archive-with-range-using-java-example) 섹션을 참조하세요.

### 예제 1:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for Java
<a name="downloading-an-archive-using-java-example"></a>

다음은 지정된 볼트에서 아카이브를 다운로드하는 Java 코드 예제입니다. 작업을 마치면 `getJobOutput` 호출 한 번으로 전체 출력을 다운로드합니다. 출력을 청크 단위로 다운로드하는 예제는 [예제 2:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for Java- 청크 단위로 출력 다운로드](#downloading-an-archive-with-range-using-java-example) 섹션을 참조하세요.

이 예에서는 다음과 같은 작업을 수행합니다.

 
+ Amazon Simple Notification Service(Amazon SNS) 토픽을 생성합니다.

  Amazon Glacier는 작업 완료 후 해당 토픽에 알림을 전송합니다.
+ Amazon Simple Queue Service(Amazon SQS) 대기열을 생성합니다.

  아래 예시는 Amazon SNS 토픽이 메시지를 대기열에 게시할 수 있도록 여기에서 해당 대기열에 정책을 연결합니다.
+ 지정된 아카이브의 다운로드 작업을 시작합니다.

  작업 요청에서 Amazon Glacier가 작업 완료 후 알림 메시지를 해당 토픽에 게시할 수 있도록 생성된 Amazon SNS 토픽이 지정됩니다.
+ 작업 ID가 포함된 메시지가 있는지 Amazon SQS 대기열을 주기적으로 확인합니다.

  메시지가 있으면 JSON 구문을 분석하여 작업이 성공적으로 완료되었는지 확인합니다. 성공적으로 완료되었으면 아카이브를 다운로드합니다.
+ Amazon SNS 토픽과 생성된 Amazon SQS 대기열을 삭제하여 정리합니다.

 

```
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.ObjectMapper;

import com.amazonaws.AmazonClientException;
import com.amazonaws.auth.policy.Policy;
import com.amazonaws.auth.policy.Principal;
import com.amazonaws.auth.policy.Resource;
import com.amazonaws.auth.policy.Statement;
import com.amazonaws.auth.policy.Statement.Effect;
import com.amazonaws.auth.policy.actions.SQSActions;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.model.GetJobOutputRequest;
import com.amazonaws.services.glacier.model.GetJobOutputResult;
import com.amazonaws.services.glacier.model.InitiateJobRequest;
import com.amazonaws.services.glacier.model.InitiateJobResult;
import com.amazonaws.services.glacier.model.JobParameters;
import com.amazonaws.services.sns.AmazonSNSClient;
import com.amazonaws.services.sns.model.CreateTopicRequest;
import com.amazonaws.services.sns.model.CreateTopicResult;
import com.amazonaws.services.sns.model.DeleteTopicRequest;
import com.amazonaws.services.sns.model.SubscribeRequest;
import com.amazonaws.services.sns.model.SubscribeResult;
import com.amazonaws.services.sns.model.UnsubscribeRequest;
import com.amazonaws.services.sqs.AmazonSQSClient;
import com.amazonaws.services.sqs.model.CreateQueueRequest;
import com.amazonaws.services.sqs.model.CreateQueueResult;
import com.amazonaws.services.sqs.model.DeleteQueueRequest;
import com.amazonaws.services.sqs.model.GetQueueAttributesRequest;
import com.amazonaws.services.sqs.model.GetQueueAttributesResult;
import com.amazonaws.services.sqs.model.Message;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.SetQueueAttributesRequest;


public class AmazonGlacierDownloadArchiveWithSQSPolling {
    
    public static String archiveId = "*** provide archive ID ****";
    public static String vaultName = "*** provide vault name ***";
    public static String snsTopicName = "*** provide topic name ***";
    public static String sqsQueueName = "*** provide queue name ***";
    public static String sqsQueueARN;
    public static String sqsQueueURL;
    public static String snsTopicARN;
    public static String snsSubscriptionARN;
    public static String fileName = "*** provide file name ***";
    public static String region = "*** region ***"; 
    public static long sleepTime = 600; 
    public static AmazonGlacierClient client;
    public static AmazonSQSClient sqsClient;
    public static AmazonSNSClient snsClient;
    
    public static void main(String[] args) throws IOException {
        
    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();

        client = new AmazonGlacierClient(credentials);
        client.setEndpoint("https://glacier." + region + ".amazonaws.com");
        sqsClient = new AmazonSQSClient(credentials);
        sqsClient.setEndpoint("https://sqs." + region + ".amazonaws.com");
        snsClient = new AmazonSNSClient(credentials);
        snsClient.setEndpoint("https://sns." + region + ".amazonaws.com");
                
        try {
            setupSQS();
            
            setupSNS();

            String jobId = initiateJobRequest();
            System.out.println("Jobid = " + jobId);
            
            Boolean success = waitForJobToComplete(jobId, sqsQueueURL);
            if (!success) { throw new Exception("Job did not complete successfully."); }
            
            downloadJobOutput(jobId);
            
            cleanUp();
            
        } catch (Exception e) {
            System.err.println("Archive retrieval failed.");
            System.err.println(e);
        }   
    }

    private static void setupSQS() {
        CreateQueueRequest request = new CreateQueueRequest()
            .withQueueName(sqsQueueName);
        CreateQueueResult result = sqsClient.createQueue(request);  
        sqsQueueURL = result.getQueueUrl();
                
        GetQueueAttributesRequest qRequest = new GetQueueAttributesRequest()
            .withQueueUrl(sqsQueueURL)
            .withAttributeNames("QueueArn");
        
        GetQueueAttributesResult qResult = sqsClient.getQueueAttributes(qRequest);
        sqsQueueARN = qResult.getAttributes().get("QueueArn");
        
        Policy sqsPolicy = 
            new Policy().withStatements(
                    new Statement(Effect.Allow)
                    .withPrincipals(Principal.AllUsers)
                    .withActions(SQSActions.SendMessage)
                    .withResources(new Resource(sqsQueueARN)));
        Map<String, String> queueAttributes = new HashMap<String, String>();
        queueAttributes.put("Policy", sqsPolicy.toJson());
        sqsClient.setQueueAttributes(new SetQueueAttributesRequest(sqsQueueURL, queueAttributes)); 

    }
    private static void setupSNS() {
        CreateTopicRequest request = new CreateTopicRequest()
            .withName(snsTopicName);
        CreateTopicResult result = snsClient.createTopic(request);
        snsTopicARN = result.getTopicArn();

        SubscribeRequest request2 = new SubscribeRequest()
            .withTopicArn(snsTopicARN)
            .withEndpoint(sqsQueueARN)
            .withProtocol("sqs");
        SubscribeResult result2 = snsClient.subscribe(request2);
                
        snsSubscriptionARN = result2.getSubscriptionArn();
    }
    private static String initiateJobRequest() {
        
        JobParameters jobParameters = new JobParameters()
            .withType("archive-retrieval")
            .withArchiveId(archiveId)
            .withSNSTopic(snsTopicARN);
        
        InitiateJobRequest request = new InitiateJobRequest()
            .withVaultName(vaultName)
            .withJobParameters(jobParameters);
        
        InitiateJobResult response = client.initiateJob(request);
        
        return response.getJobId();
    }
    
    private static Boolean waitForJobToComplete(String jobId, String sqsQueueUrl) throws InterruptedException, JsonParseException, IOException {
        
        Boolean messageFound = false;
        Boolean jobSuccessful = false;
        ObjectMapper mapper = new ObjectMapper();
        JsonFactory factory = mapper.getJsonFactory();
        
        while (!messageFound) {
            List<Message> msgs = sqsClient.receiveMessage(
               new ReceiveMessageRequest(sqsQueueUrl).withMaxNumberOfMessages(10)).getMessages();

            if (msgs.size() > 0) {
                for (Message m : msgs) {
                    JsonParser jpMessage = factory.createJsonParser(m.getBody());
                    JsonNode jobMessageNode = mapper.readTree(jpMessage);
                    String jobMessage = jobMessageNode.get("Message").getTextValue();
                    
                    JsonParser jpDesc = factory.createJsonParser(jobMessage);
                    JsonNode jobDescNode = mapper.readTree(jpDesc);
                    String retrievedJobId = jobDescNode.get("JobId").getTextValue();
                    String statusCode = jobDescNode.get("StatusCode").getTextValue();
                    if (retrievedJobId.equals(jobId)) {
                        messageFound = true;
                        if (statusCode.equals("Succeeded")) {
                            jobSuccessful = true;
                        }
                    }
                }
                
            } else {
              Thread.sleep(sleepTime * 1000); 
            }
          }
        return (messageFound && jobSuccessful);
    }
    
    private static void downloadJobOutput(String jobId) throws IOException {
        
        GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest()
            .withVaultName(vaultName)
            .withJobId(jobId);
        GetJobOutputResult getJobOutputResult = client.getJobOutput(getJobOutputRequest);
    
        InputStream input = new BufferedInputStream(getJobOutputResult.getBody());
        OutputStream output = null;
        try {
            output = new BufferedOutputStream(new FileOutputStream(fileName));

            byte[] buffer = new byte[1024 * 1024];

            int bytesRead = 0;
            do {
                bytesRead = input.read(buffer);
                if (bytesRead <= 0) break;
                output.write(buffer, 0, bytesRead);
            } while (bytesRead > 0);
        } catch (IOException e) {
            throw new AmazonClientException("Unable to save archive", e);
        } finally {
            try {input.close();}  catch (Exception e) {}
            try {output.close();} catch (Exception e) {}
        }
        System.out.println("Retrieved archive to " + fileName);
    }
    
    private static void cleanUp() {
        snsClient.unsubscribe(new UnsubscribeRequest(snsSubscriptionARN));
        snsClient.deleteTopic(new DeleteTopicRequest(snsTopicARN));
        sqsClient.deleteQueue(new DeleteQueueRequest(sqsQueueURL));
    }
}
```

### 예제 2:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for Java- 청크 단위로 출력 다운로드
<a name="downloading-an-archive-with-range-using-java-example"></a>

다음은 Amazon Glacier에서 아카이브를 검색하는 Java 코드 예입니다. 이 코드 예제는 `GetJobOutputRequest` 객체에서 바이트 범위를 지정하여 작업 출력을 청크 단위로 다운로드합니다.

 

```
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.amazonaws.auth.policy.Policy;
import com.amazonaws.auth.policy.Principal;
import com.amazonaws.auth.policy.Resource;
import com.amazonaws.auth.policy.Statement;
import com.amazonaws.auth.policy.Statement.Effect;
import com.amazonaws.auth.policy.actions.SQSActions;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.TreeHashGenerator;
import com.amazonaws.services.glacier.model.GetJobOutputRequest;
import com.amazonaws.services.glacier.model.GetJobOutputResult;
import com.amazonaws.services.glacier.model.InitiateJobRequest;
import com.amazonaws.services.glacier.model.InitiateJobResult;
import com.amazonaws.services.glacier.model.JobParameters;
import com.amazonaws.services.sns.AmazonSNSClient;
import com.amazonaws.services.sns.model.CreateTopicRequest;
import com.amazonaws.services.sns.model.CreateTopicResult;
import com.amazonaws.services.sns.model.DeleteTopicRequest;
import com.amazonaws.services.sns.model.SubscribeRequest;
import com.amazonaws.services.sns.model.SubscribeResult;
import com.amazonaws.services.sns.model.UnsubscribeRequest;
import com.amazonaws.services.sqs.AmazonSQSClient;
import com.amazonaws.services.sqs.model.CreateQueueRequest;
import com.amazonaws.services.sqs.model.CreateQueueResult;
import com.amazonaws.services.sqs.model.DeleteQueueRequest;
import com.amazonaws.services.sqs.model.GetQueueAttributesRequest;
import com.amazonaws.services.sqs.model.GetQueueAttributesResult;
import com.amazonaws.services.sqs.model.Message;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.SetQueueAttributesRequest;


public class ArchiveDownloadLowLevelWithRange {
    
    public static String vaultName = "*** provide vault name ***";
    public static String archiveId = "*** provide archive id ***";
    public static String snsTopicName = "glacier-temp-sns-topic";
    public static String sqsQueueName = "glacier-temp-sqs-queue";
    public static long downloadChunkSize = 4194304; // 4 MB  
    public static String sqsQueueARN;
    public static String sqsQueueURL;
    public static String snsTopicARN;
    public static String snsSubscriptionARN;
    public static String fileName = "*** provide file name to save archive to ***";
    public static String region   = "*** region ***";
    public static long sleepTime  = 600; 
    
    public static AmazonGlacierClient client;
    public static AmazonSQSClient sqsClient;
    public static AmazonSNSClient snsClient; 
    
    public static void main(String[] args) throws IOException {
        
    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();

        client = new AmazonGlacierClient(credentials);
        client.setEndpoint("https://glacier." + region + ".amazonaws.com");
        sqsClient = new AmazonSQSClient(credentials);
        sqsClient.setEndpoint("https://sqs." + region + ".amazonaws.com");
        snsClient = new AmazonSNSClient(credentials);
        snsClient.setEndpoint("https://sns." + region + ".amazonaws.com");
        
        try {
            setupSQS();
            
            setupSNS();

            String jobId = initiateJobRequest();
            System.out.println("Jobid = " + jobId);
            
            long archiveSizeInBytes = waitForJobToComplete(jobId, sqsQueueURL);
            if (archiveSizeInBytes==-1) { throw new Exception("Job did not complete successfully."); }
            
            downloadJobOutput(jobId, archiveSizeInBytes);
            
            cleanUp();
            
        } catch (Exception e) {
            System.err.println("Archive retrieval failed.");
            System.err.println(e);
        }   
    }

    private static void setupSQS() {
        CreateQueueRequest request = new CreateQueueRequest()
            .withQueueName(sqsQueueName);
        CreateQueueResult result = sqsClient.createQueue(request);  
        sqsQueueURL = result.getQueueUrl();
                
        GetQueueAttributesRequest qRequest = new GetQueueAttributesRequest()
            .withQueueUrl(sqsQueueURL)
            .withAttributeNames("QueueArn");
        
        GetQueueAttributesResult qResult = sqsClient.getQueueAttributes(qRequest);
        sqsQueueARN = qResult.getAttributes().get("QueueArn");
        
        Policy sqsPolicy = 
            new Policy().withStatements(
                    new Statement(Effect.Allow)
                    .withPrincipals(Principal.AllUsers)
                    .withActions(SQSActions.SendMessage)
                    .withResources(new Resource(sqsQueueARN)));
        Map<String, String> queueAttributes = new HashMap<String, String>();
        queueAttributes.put("Policy", sqsPolicy.toJson());
        sqsClient.setQueueAttributes(new SetQueueAttributesRequest(sqsQueueURL, queueAttributes)); 

    }
    private static void setupSNS() {
        CreateTopicRequest request = new CreateTopicRequest()
            .withName(snsTopicName);
        CreateTopicResult result = snsClient.createTopic(request);
        snsTopicARN = result.getTopicArn();

        SubscribeRequest request2 = new SubscribeRequest()
            .withTopicArn(snsTopicARN)
            .withEndpoint(sqsQueueARN)
            .withProtocol("sqs");
        SubscribeResult result2 = snsClient.subscribe(request2);
                
        snsSubscriptionARN = result2.getSubscriptionArn();
    }
    private static String initiateJobRequest() {
        
        JobParameters jobParameters = new JobParameters()
            .withType("archive-retrieval")
            .withArchiveId(archiveId)
            .withSNSTopic(snsTopicARN);
        
        InitiateJobRequest request = new InitiateJobRequest()
            .withVaultName(vaultName)
            .withJobParameters(jobParameters);
        
        InitiateJobResult response = client.initiateJob(request);
        
        return response.getJobId();
    }
    
    private static long waitForJobToComplete(String jobId, String sqsQueueUrl) throws InterruptedException, JsonParseException, IOException {
        
        Boolean messageFound = false;
        Boolean jobSuccessful = false;
        long archiveSizeInBytes = -1;
        ObjectMapper mapper = new ObjectMapper();
        JsonFactory factory = mapper.getFactory();
        
        while (!messageFound) {
            List<Message> msgs = sqsClient.receiveMessage(
               new ReceiveMessageRequest(sqsQueueUrl).withMaxNumberOfMessages(10)).getMessages();

            if (msgs.size() > 0) {
                for (Message m : msgs) {
                    JsonParser jpMessage = factory.createJsonParser(m.getBody());
                    JsonNode jobMessageNode = mapper.readTree(jpMessage);
                    String jobMessage = jobMessageNode.get("Message").textValue();
                    
                    JsonParser jpDesc = factory.createJsonParser(jobMessage);
                    JsonNode jobDescNode = mapper.readTree(jpDesc);
                    String retrievedJobId = jobDescNode.get("JobId").textValue();
                    String statusCode = jobDescNode.get("StatusCode").textValue();
                    archiveSizeInBytes = jobDescNode.get("ArchiveSizeInBytes").longValue();
                    if (retrievedJobId.equals(jobId)) {
                        messageFound = true;
                        if (statusCode.equals("Succeeded")) {
                            jobSuccessful = true;
                        }
                    }
                }
                
            } else {
              Thread.sleep(sleepTime * 1000); 
            }
          }
        return (messageFound && jobSuccessful) ? archiveSizeInBytes : -1;
    }
    
    private static void downloadJobOutput(String jobId, long archiveSizeInBytes) throws IOException {
        
        if (archiveSizeInBytes < 0) {
            System.err.println("Nothing to download.");
            return;
        }

        System.out.println("archiveSizeInBytes: " + archiveSizeInBytes);
        FileOutputStream fstream = new FileOutputStream(fileName);
        long startRange = 0;
        long endRange = (downloadChunkSize > archiveSizeInBytes) ? archiveSizeInBytes -1 : downloadChunkSize - 1;

        do {

            GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest()
                .withVaultName(vaultName)
                .withRange("bytes=" + startRange + "-" + endRange)
                .withJobId(jobId);
            GetJobOutputResult getJobOutputResult = client.getJobOutput(getJobOutputRequest);

            BufferedInputStream is = new BufferedInputStream(getJobOutputResult.getBody());     
            byte[] buffer = new byte[(int)(endRange - startRange + 1)];

            System.out.println("Checksum received: " + getJobOutputResult.getChecksum());
            System.out.println("Content range " + getJobOutputResult.getContentRange());

            
            int totalRead = 0;
            while (totalRead < buffer.length) {
                int bytesRemaining = buffer.length - totalRead;
                int read = is.read(buffer, totalRead, bytesRemaining);
                if (read > 0) {
                    totalRead = totalRead + read;                             
                } else {
                    break;
                }
                
            }
            System.out.println("Calculated checksum: " + TreeHashGenerator.calculateTreeHash(new ByteArrayInputStream(buffer)));
            System.out.println("read = " + totalRead);
            fstream.write(buffer);
            
            startRange = startRange + (long)totalRead;
            endRange = ((endRange + downloadChunkSize) >  archiveSizeInBytes) ? archiveSizeInBytes : (endRange + downloadChunkSize); 
            is.close();
        } while (endRange <= archiveSizeInBytes  && startRange < archiveSizeInBytes);
        
        fstream.close();
        System.out.println("Retrieved file to " + fileName);

    }
    
    private static void cleanUp() {
        snsClient.unsubscribe(new UnsubscribeRequest(snsSubscriptionARN));
        snsClient.deleteTopic(new DeleteTopicRequest(snsTopicARN));
        sqsClient.deleteQueue(new DeleteQueueRequest(sqsQueueURL));
    }
}
```

# 를 사용하여 Amazon Glacier에서 아카이브 다운로드 AWS SDK for .NET
<a name="downloading-an-archive-using-dotnet"></a>

Amazon SDK for .NET에서 제공하는 [하이레벨 및 로우레벨 API](using-aws-sdk.md) 둘 모두는 아카이브를 다운로드하는 방법을 제공합니다.

**Topics**
+ [의 상위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for .NET](#downloading-an-archive-using-dotnet-highlevel-api)
+ [의 하위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for .NET](#downloading-an-archive-using-dotnet-lowlevel-api)

## 의 상위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for .NET
<a name="downloading-an-archive-using-dotnet-highlevel-api"></a>

하이레벨 API의 `ArchiveTransferManager` 클래스는 아카이브를 다운로드하는 데 사용할 수 있는 `Download` 메서드를 제공합니다.

**중요**  
`ArchiveTransferManager` 클래스는 Amazon Simple Notification Service(SNS) 토픽 및 해당 토픽을 구독하는 Amazon Simple Queue Service(Amazon SQS) 대기열을 생성합니다. 그런 다음 아카이브 가져오기 작업을 시작하고 아카이브를 사용할 수 있도록 대기열을 폴링합니다. 아카이브를 사용할 수 있게 되면 다운로드가 시작됩니다. 검색 시간에 대한 자세한 내용은 [아카이브 검색 옵션](downloading-an-archive-two-steps.md#api-downloading-an-archive-two-steps-retrieval-options) 섹션을 참조하세요.

### 예:의 상위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for .NET
<a name="download-archives-dotnet-highlevel-example"></a>

다음은 미국 서부(오레곤) 리전의 볼트(`examplevault`)에서 아카이브를 다운로드하는 C\$1 코드 예시입니다.

이 예제의 실행 방법에 대한 단계별 지침은 [코드 예제 실행](using-aws-sdk-for-dot-net.md#setting-up-and-testing-sdk-dotnet) 섹션을 참조하세요. 코드는 기존 아카이브 ID와 다운로드한 아카이브를 저장할 로컬 파일 경로를 사용해 아래와 같이 업데이트해야 합니다.

```
using System;
using Amazon.Glacier;
using Amazon.Glacier.Transfer;
using Amazon.Runtime;

namespace glacier.amazon.com.rproxy.govskope.us.docsamples
{
  class ArchiveDownloadHighLevel
  {
    static string vaultName        = "examplevault";
    static string archiveId        = "*** Provide archive ID ***";
    static string downloadFilePath = "*** Provide the file name and path to where to store the download ***";

    public static void Main(string[] args)
    {
      try
      {
        var manager = new ArchiveTransferManager(Amazon.RegionEndpoint.USWest2);

        var options = new DownloadOptions();
        options.StreamTransferProgress += ArchiveDownloadHighLevel.progress;
        // Download an archive.
        Console.WriteLine("Intiating the archive retrieval job and then polling SQS queue for the archive to be available.");
        Console.WriteLine("Once the archive is available, downloading will begin.");
        manager.Download(vaultName, archiveId, downloadFilePath, options);
        Console.WriteLine("To continue, press Enter");
        Console.ReadKey();
      }
      catch (AmazonGlacierException e) { Console.WriteLine(e.Message); }
      catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
      catch (Exception e) { Console.WriteLine(e.Message); }
      Console.WriteLine("To continue, press Enter");
      Console.ReadKey();
    }

    static int currentPercentage = -1;
    static void progress(object sender, StreamTransferProgressArgs args)
    {
      if (args.PercentDone != currentPercentage)
      {
        currentPercentage = args.PercentDone;
        Console.WriteLine("Downloaded {0}%", args.PercentDone);
      }
    }
  }
}
```

## 의 하위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for .NET
<a name="downloading-an-archive-using-dotnet-lowlevel-api"></a>

다음은 AWS SDK for .NET의 로우레벨 API를 사용해 Amazon Glacier(Amazon Glacier) 아카이브를 다운로드하는 단계입니다.

1. `AmazonGlacierClient` 클래스(클라이언트)의 인스턴스를 만듭니다.

   아카이브를 다운로드할 AWS 리전을 지정해야 합니다. 이 클라이언트를 사용하여 수행하는 모든 작업은 해당 AWS 리전에 적용됩니다.

1. `InitiateJob` 메서드를 실행하여 `archive-retrieval` 작업을 시작합니다.

   `InitiateJobRequest` 클래스 인스턴스를 생성하여 다운로드를 원하는 아카이브의 ID, Amazon Glacier가 작업 완료 메시지를 게시할 Amazon SNS 토픽(옵션) 등 작업 정보를 제공합니다. Amazon Glacier는 응답으로 작업 ID를 반환합니다. 이 응답은 `InitiateJobResponse` 클래스 인스턴스에서 사용할 수 있습니다.

   ```
   AmazonGlacierClient client;
   client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2);
   
   InitiateJobRequest initJobRequest = new InitiateJobRequest()
   {
     VaultName = vaultName,
     JobParameters = new JobParameters()
     {
       Type      = "archive-retrieval",
       ArchiveId = "*** Provide archive id ***",
       SNSTopic  = "*** Provide Amazon SNS topic ARN ***",
     }
   };
   
   InitiateJobResponse initJobResponse = client.InitiateJob(initJobRequest);
   string jobId = initJobResponse.JobId;
   ```

   다음 요청과 같이 선택적으로 바이트 범위를 지정하여 Amazon Glacier에 아카이브의 일부만 준비하도록 요청할 수 있습니다. 그러면 Amazon Glacier는 요청이 지정한 바에 따라 아카이브에서 1\$12MB의 데이터만 준비합니다.

   ```
   AmazonGlacierClient client;
   client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2);
   
   
   InitiateJobRequest initJobRequest = new InitiateJobRequest()
   {
     VaultName = vaultName,
     JobParameters = new JobParameters()
     {
       Type      = "archive-retrieval",
       ArchiveId = "*** Provide archive id ***",
       SNSTopic  = "*** Provide Amazon SNS topic ARN ***",
     }
   };
   // Specify byte range.
   int ONE_MEG = 1048576;
   initJobRequest.JobParameters.RetrievalByteRange = string.Format("{0}-{1}", ONE_MEG, 2 * ONE_MEG -1);
   
   InitiateJobResponse initJobResponse = client.InitiateJob(initJobRequest);
   string jobId = initJobResponse.JobId;
   ```

1.  작업이 완료될 때까지 기다립니다.

   작업 출력을 다운로드할 수 있을 때까지 기다려야 합니다. 볼트에서 Amazon Simple Notification Service(Amazon SNS) 토픽을 식별할 수 있도록 알림 구성을 설정했거나 작업을 시작할 때 Amazon SNS 토픽을 지정했다면 Amazon Glacier가 작업 완료 후 해당 토픽에 메시지를 보냅니다. 다음 섹션에서 제공하는 코드 예시는 Amazon Glacier가 메시지를 게시할 수 있도록 Amazon SNS를 사용합니다.

   `DescribeJob` 메서드를 직접 호출하여 Amazon Glacier를 폴링함으로써 작업 완료 상태를 확인하는 방법도 있습니다. 하지만 Amazon SNS 토픽의 알림을 사용해 식별하는 방법이 권장됩니다.

1. `GetJobOutput` 메서드를 실행하여 작업 출력(아카이브 데이터)을 다운로드합니다.

   `GetJobOutputRequest` 클래스 인스턴스를 생성하여 작업 ID, 볼트 이름 등 요청 정보를 입력합니다. Amazon Glacier가 반환하는 출력은 `GetJobOutputResponse` 객체에서 사용할 수 있습니다.

   ```
   GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest()
   {
     JobId = jobId,
     VaultName = vaultName
   };
   
   GetJobOutputResponse getJobOutputResponse = client.GetJobOutput(getJobOutputRequest);
   using (Stream webStream = getJobOutputResponse.Body)
   {
     using (Stream fileToSave = File.OpenWrite(fileName))
     {
        CopyStream(webStream, fileToSave);
     }
   }
   ```

   위의 코드 조각은 전체 작업 출력을 다운로드합니다. 옵션으로 `GetJobOutputRequest`에서 바이트 범위를 지정하여 출력 일부만 가져오거나 전체 출력을 더 작은 청크 단위로 나누어 다운로드할 수 있습니다.

   ```
   GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest()
   {
     JobId = jobId,
     VaultName = vaultName
   };
   getJobOutputRequest.SetRange(0, 1048575); // Download only the first 1 MB chunk of the output.
   ```

   특정 조건이 충족된다면 Amazon Glacier가 `GetJobOutput` 직접 호출에 대한 응답으로 다운로드한 데이터 일부의 체크섬을 반환합니다. 자세한 내용은 [데이터 다운로드 시 체크섬 수신](checksum-calculations-range.md) 단원을 참조하십시오.

   다운로드에 오류가 없는지 확인하려면 클라이언트 측 체크섬을 계산한 뒤 Amazon Glacier가 응답으로 보내는 체크섬과 비교합니다.

   옵션으로 범위를 지정하여 아카이브를 가져오는 작업에서는 작업 설명을 다운로드할 때 가져오는 범위에 대한 체크섬(SHA256 트리-해시)도 포함됩니다. 이 체크섬 값은 나중에 다운로드하는 전체 바이트 범위의 정확성을 검증하는 데 사용할 수 있습니다. 예를 들어 트리-해시로 정렬된 아카이브 범위를 가져오는 작업을 시작하면서 `GetJobOutput` 요청이 각각 체크섬을 반환할 수 있도록 청크 단위로 출력을 다운로드하는 경우에는 클라이언트 측에서 다운로드하는 개별 데이터의 체크섬을 계산하고 나서 트리 해시를 계산할 수 있습니다. Amazon Glacier가 작업 설명 요청에 대한 응답으로 반환하는 체크섬과 비교하여 사용자가 다운로드한 전체 바이트 범위가 Amazon Glacier에 저장된 바이트 범위와 일치하는지 확인할 수 있습니다.

   

   사용 가능한 예제는 [예제 2:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for .NET- 청크 단위로 출력 다운로드](#creating-vaults-sdk-dotnet-example2) 섹션을 참조하세요.

### 예제 1:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for .NET
<a name="creating-vaults-sdk-dotnet-example-retrieve"></a>

다음은 지정된 볼트에서 아카이브를 다운로드하는 C\$1 코드 예제입니다. 작업을 마치면 `GetJobOutput` 호출 한 번으로 전체 출력을 다운로드합니다. 출력을 청크 단위로 다운로드하는 예제는 [예제 2:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for .NET- 청크 단위로 출력 다운로드](#creating-vaults-sdk-dotnet-example2) 섹션을 참조하세요.

이 예에서는 다음과 같은 작업을 수행합니다.
+ Amazon Simple Notification Service(Amazon SNS) 토픽 설정 

  Amazon Glacier는 작업 완료 후 해당 토픽에 알림을 전송합니다.
+ Amazon Simple Queue Service(Amazon SQS) 대기열을 설정합니다.

  아래 예시는 Amazon SNS 토픽이 메시지를 게시할 수 있도록 대기열에 정책을 연결합니다.
+ 지정된 아카이브의 다운로드 작업을 시작합니다.

  아래 예시는 Amazon Glacier가 작업 완료 후 메시지를 전송할 수 있도록 작업 요청에서 Amazon SNS 토픽을 지정합니다.
+ Amazon SQS 대기열의 메시지를 주기적으로 확인합니다.

  메시지가 있으면 JSON 구문을 분석하여 작업이 성공적으로 완료되었는지 확인합니다. 성공적으로 완료되었으면 아카이브를 다운로드합니다. 아래 코드 예제에서는 JSON.NET 라이브러리([JSON.NET](http://json.codeplex.com/) 참조)를 사용하여 JSON 구문을 분석합니다.
+ Amazon SNS 토픽과 토픽이 생성한 Amazon SQS 대기열을 삭제하여 정리합니다.

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Amazon.Glacier;
using Amazon.Glacier.Model;
using Amazon.Runtime;
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;
using Amazon.SQS;
using Amazon.SQS.Model;
using Newtonsoft.Json;

namespace glacier.amazon.com.rproxy.govskope.us.docsamples
{
  class ArchiveDownloadLowLevelUsingSNSSQS
  {
    static string topicArn;
    static string queueUrl;
    static string queueArn;
    static string vaultName = "*** Provide vault name ***";
    static string archiveID = "*** Provide archive ID ***";
    static string fileName  = "*** Provide the file name and path to where to store downloaded archive ***";
    static AmazonSimpleNotificationServiceClient snsClient;
    static AmazonSQSClient sqsClient;
    const string SQS_POLICY =
        "{" +
        "    \"Version\" : \"2012-10-17\",&TCX5-2025-waiver;" +
        "    \"Statement\" : [" +
        "        {" +
        "            \"Sid\" : \"sns-rule\"," +
        "            \"Effect\" : \"Allow\"," +
        "            \"Principal\" : {\"Service\" : \"sns.amazonaws.com\" }," +
        "            \"Action\"    : \"sqs:SendMessage\"," +
        "            \"Resource\"  : \"{QueueArn}\"," +
        "            \"Condition\" : {" +
        "                \"ArnLike\" : {" +
        "                    \"aws:SourceArn\" : \"{TopicArn}\"" +
        "                }" +
        "            }" +
        "        }" +
        "    ]" +
        "}";

    public static void Main(string[] args)
    {
      AmazonGlacierClient client;
      try
      {
        using (client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2))
        {
          Console.WriteLine("Setup SNS topic and SQS queue."); 
          SetupTopicAndQueue();
          Console.WriteLine("To continue, press Enter"); Console.ReadKey();
          Console.WriteLine("Retrieving...");
          RetrieveArchive(client);
        }
        Console.WriteLine("Operations successful. To continue, press Enter");
        Console.ReadKey();
      }
      catch (AmazonGlacierException e) { Console.WriteLine(e.Message); }
      catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
      catch (Exception e) { Console.WriteLine(e.Message); }
      finally
      {
        // Delete SNS topic and SQS queue.
        snsClient.DeleteTopic(new DeleteTopicRequest() { TopicArn = topicArn });
        sqsClient.DeleteQueue(new DeleteQueueRequest() { QueueUrl = queueUrl });
      }
    }

    static void SetupTopicAndQueue()
    {
      snsClient = new AmazonSimpleNotificationServiceClient(Amazon.RegionEndpoint.USWest2);
      sqsClient = new AmazonSQSClient(Amazon.RegionEndpoint.USWest2);

      long ticks = DateTime.Now.Ticks;
      topicArn = snsClient.CreateTopic(new CreateTopicRequest { Name = "GlacierDownload-" + ticks }).TopicArn;
      Console.Write("topicArn: "); Console.WriteLine(topicArn);

      CreateQueueRequest createQueueRequest = new CreateQueueRequest();
      createQueueRequest.QueueName = "GlacierDownload-" + ticks;
      CreateQueueResponse createQueueResponse = sqsClient.CreateQueue(createQueueRequest);
      queueUrl = createQueueResponse.QueueUrl;
      Console.Write("QueueURL: "); Console.WriteLine(queueUrl);

      GetQueueAttributesRequest getQueueAttributesRequest = new GetQueueAttributesRequest();
      getQueueAttributesRequest.AttributeNames = new List<string> { "QueueArn" };
      getQueueAttributesRequest.QueueUrl = queueUrl;
      GetQueueAttributesResponse response = sqsClient.GetQueueAttributes(getQueueAttributesRequest);
      queueArn = response.QueueARN;
      Console.Write("QueueArn: "); Console.WriteLine(queueArn);

      // Setup the Amazon SNS topic to publish to the SQS queue.
      snsClient.Subscribe(new SubscribeRequest()
      {
        Protocol = "sqs",
        Endpoint = queueArn,
        TopicArn = topicArn
      });

      // Add policy to the queue so SNS can send messages to the queue.
      var policy = SQS_POLICY.Replace("{TopicArn}", topicArn).Replace("{QueueArn}", queueArn);

      sqsClient.SetQueueAttributes(new SetQueueAttributesRequest()
      {
          QueueUrl = queueUrl,
          Attributes = new Dictionary<string, string>
          {
              { QueueAttributeName.Policy, policy }
          }
      });
    }

    static void RetrieveArchive(AmazonGlacierClient client)
    {
      // Initiate job.
      InitiateJobRequest initJobRequest = new InitiateJobRequest()
      {
        VaultName = vaultName,
        JobParameters = new JobParameters()
        {
          Type = "archive-retrieval", 
          ArchiveId = archiveID,
          Description = "This job is to download archive.",
          SNSTopic = topicArn,
        }
      };
      InitiateJobResponse initJobResponse = client.InitiateJob(initJobRequest);
      string jobId = initJobResponse.JobId;

      // Check queue for a message and if job completed successfully, download archive.
      ProcessQueue(jobId, client);
    }

    private static void ProcessQueue(string jobId, AmazonGlacierClient client)
    {
      ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest() { QueueUrl = queueUrl, MaxNumberOfMessages = 1 }; 
      bool jobDone = false;
      while (!jobDone)
      {
        Console.WriteLine("Poll SQS queue");
        ReceiveMessageResponse receiveMessageResponse = sqsClient.ReceiveMessage(receiveMessageRequest); 
        if (receiveMessageResponse.Messages.Count == 0)
        {
          Thread.Sleep(10000 * 60);
          continue;
        }
        Console.WriteLine("Got message");
        Message message = receiveMessageResponse.Messages[0];
        Dictionary<string, string> outerLayer = JsonConvert.DeserializeObject<Dictionary<string, string>>(message.Body);
        Dictionary<string, object> fields = JsonConvert.DeserializeObject<Dictionary<string, object>>(outerLayer["Message"]);
        string statusCode = fields["StatusCode"] as string;

        if (string.Equals(statusCode, GlacierUtils.JOB_STATUS_SUCCEEDED, StringComparison.InvariantCultureIgnoreCase))
        {
          Console.WriteLine("Downloading job output");
          DownloadOutput(jobId, client); // Save job output to the specified file location.
        }
        else if (string.Equals(statusCode, GlacierUtils.JOB_STATUS_FAILED, StringComparison.InvariantCultureIgnoreCase))
          Console.WriteLine("Job failed... cannot download the archive.");

        jobDone = true;
        sqsClient.DeleteMessage(new DeleteMessageRequest() { QueueUrl = queueUrl, ReceiptHandle = message.ReceiptHandle });
      }
    }

    private static void DownloadOutput(string jobId, AmazonGlacierClient client)
    {
      GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest()
      {
        JobId = jobId,
        VaultName = vaultName
      };
      
      GetJobOutputResponse getJobOutputResponse = client.GetJobOutput(getJobOutputRequest);
      using (Stream webStream = getJobOutputResponse.Body)
      {
          using (Stream fileToSave = File.OpenWrite(fileName))
          {
              CopyStream(webStream, fileToSave);
          }
      }
    }

    public static void CopyStream(Stream input, Stream output)
    {
      byte[] buffer = new byte[65536];
      int length;
      while ((length = input.Read(buffer, 0, buffer.Length)) > 0)
      {
        output.Write(buffer, 0, length);
      }
    }
  }
}
```

### 예제 2:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for .NET- 청크 단위로 출력 다운로드
<a name="creating-vaults-sdk-dotnet-example2"></a>

다음은 Amazon Glacier에서 아카이브를 검색하는 C\$1 코드 예입니다. 이 코드 예제는 `GetJobOutputRequest` 객체에서 바이트 범위를 지정하여 작업 출력을 청크 단위로 다운로드합니다.

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Amazon.Glacier;
using Amazon.Glacier.Model;
using Amazon.Glacier.Transfer;
using Amazon.Runtime;
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;
using Amazon.SQS;
using Amazon.SQS.Model;
using Newtonsoft.Json;
using System.Collections.Specialized;

namespace glacier.amazon.com.rproxy.govskope.us.docsamples
{
  class ArchiveDownloadLowLevelUsingSQLSNSOutputUsingRange
  {
    static string topicArn;
    static string queueUrl;
    static string queueArn;
    static string vaultName = "*** Provide vault name ***";
    static string archiveId = "*** Provide archive ID ***";
    static string fileName  = "*** Provide the file name and path to where to store downloaded archive ***";
    static AmazonSimpleNotificationServiceClient snsClient;
    static AmazonSQSClient sqsClient;
    const string SQS_POLICY =
        "{" +
        "    \"Version\" : \"2012-10-17\",&TCX5-2025-waiver;" +
        "    \"Statement\" : [" +
        "        {" +
        "            \"Sid\" : \"sns-rule\"," +
        "            \"Effect\" : \"Allow\"," +
        "            \"Principal\" : {\"AWS\" : \"arn:aws:iam::123456789012:root\" }," +
        "            \"Action\"  : \"sqs:SendMessage\"," +
        "            \"Resource\"  : \"{QuernArn}\"," +
        "            \"Condition\" : {" +
        "                \"ArnLike\" : {" +
        "                    \"aws:SourceArn\" : \"{TopicArn}\"" +
        "                }" +
        "            }" +
        "        }" +
        "    ]" +
        "}";

    public static void Main(string[] args)
    {
      AmazonGlacierClient client;

      try
      {
          using (client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2))
          {
              Console.WriteLine("Setup SNS topic and SQS queue.");
              SetupTopicAndQueue();
              Console.WriteLine("To continue, press Enter"); Console.ReadKey();

              Console.WriteLine("Download archive");
              DownloadAnArchive(archiveId, client);
        }
        Console.WriteLine("Operations successful. To continue, press Enter");
        Console.ReadKey();
      }
      catch (AmazonGlacierException e) { Console.WriteLine(e.Message); }
      catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
      catch (Exception e) { Console.WriteLine(e.Message); }
      finally
      {
        // Delete SNS topic and SQS queue.
        snsClient.DeleteTopic(new DeleteTopicRequest() { TopicArn = topicArn });
        sqsClient.DeleteQueue(new DeleteQueueRequest() { QueueUrl = queueUrl });
      }
    }

       static void SetupTopicAndQueue()
    {
      long ticks = DateTime.Now.Ticks;
      
      // Setup SNS topic.
      snsClient = new AmazonSimpleNotificationServiceClient(Amazon.RegionEndpoint.USWest2);
      sqsClient = new AmazonSQSClient(Amazon.RegionEndpoint.USWest2);

      topicArn = snsClient.CreateTopic(new CreateTopicRequest { Name = "GlacierDownload-" + ticks }).TopicArn;
      Console.Write("topicArn: "); Console.WriteLine(topicArn);

      CreateQueueRequest createQueueRequest = new CreateQueueRequest();
      createQueueRequest.QueueName = "GlacierDownload-" + ticks;
      CreateQueueResponse createQueueResponse = sqsClient.CreateQueue(createQueueRequest);
      queueUrl = createQueueResponse.QueueUrl;
      Console.Write("QueueURL: "); Console.WriteLine(queueUrl);

      GetQueueAttributesRequest getQueueAttributesRequest = new GetQueueAttributesRequest();
      getQueueAttributesRequest.AttributeNames = new List<string> { "QueueArn" };
      getQueueAttributesRequest.QueueUrl = queueUrl;
      GetQueueAttributesResponse response = sqsClient.GetQueueAttributes(getQueueAttributesRequest);
      queueArn = response.QueueARN;
      Console.Write("QueueArn: "); Console.WriteLine(queueArn);

      // Setup the Amazon SNS topic to publish to the SQS queue.
      snsClient.Subscribe(new SubscribeRequest()
      {
        Protocol = "sqs",
        Endpoint = queueArn,
        TopicArn = topicArn
      });

      // Add the policy to the queue so SNS can send messages to the queue.
      var policy = SQS_POLICY.Replace("{TopicArn}", topicArn).Replace("{QuernArn}", queueArn);

      sqsClient.SetQueueAttributes(new SetQueueAttributesRequest()
      {
          QueueUrl = queueUrl,
          Attributes = new Dictionary<string, string>
          {
              { QueueAttributeName.Policy, policy }
          }
      });
    }

    static void DownloadAnArchive(string archiveId, AmazonGlacierClient client)
    {
      // Initiate job.
      InitiateJobRequest initJobRequest = new InitiateJobRequest()
      {

        VaultName = vaultName,
        JobParameters = new JobParameters()
        {
          Type = "archive-retrieval",
          ArchiveId = archiveId,
          Description = "This job is to download the archive.",
          SNSTopic = topicArn,
        }
      };
      InitiateJobResponse initJobResponse = client.InitiateJob(initJobRequest);
      string jobId = initJobResponse.JobId;

      // Check queue for a message and if job completed successfully, download archive.
      ProcessQueue(jobId, client);
    }

    private static void ProcessQueue(string jobId, AmazonGlacierClient client)
    {
        var receiveMessageRequest = new ReceiveMessageRequest() { QueueUrl = queueUrl, MaxNumberOfMessages = 1 };
        bool jobDone = false;
        while (!jobDone)
        {
            Console.WriteLine("Poll SQS queue");
            ReceiveMessageResponse receiveMessageResponse = sqsClient.ReceiveMessage(receiveMessageRequest);
            if (receiveMessageResponse.Messages.Count == 0)
            {
                Thread.Sleep(10000 * 60);
                continue;
            }
            Console.WriteLine("Got message");
            Message message = receiveMessageResponse.Messages[0];
            Dictionary<string, string> outerLayer = JsonConvert.DeserializeObject<Dictionary<string, string>>(message.Body);
            Dictionary<string, object> fields = JsonConvert.DeserializeObject<Dictionary<string, object>>(outerLayer["Message"]);
            string statusCode = fields["StatusCode"] as string;
            if (string.Equals(statusCode, GlacierUtils.JOB_STATUS_SUCCEEDED, StringComparison.InvariantCultureIgnoreCase))
            {
                long archiveSize = Convert.ToInt64(fields["ArchiveSizeInBytes"]);
                Console.WriteLine("Downloading job output");
                DownloadOutput(jobId, archiveSize, client); // This where we save job output to the specified file location.
            }
            else if (string.Equals(statusCode, GlacierUtils.JOB_STATUS_FAILED, StringComparison.InvariantCultureIgnoreCase))
                Console.WriteLine("Job failed... cannot download the archive.");
            jobDone = true;
            sqsClient.DeleteMessage(new DeleteMessageRequest() { QueueUrl = queueUrl, ReceiptHandle = message.ReceiptHandle });
        }
    }               

    private static void DownloadOutput(string jobId, long archiveSize, AmazonGlacierClient client)
    {
      long partSize = 4 * (long)Math.Pow(2, 20);  // 4 MB.
      using (Stream fileToSave = new FileStream(fileName, FileMode.Create, FileAccess.Write))
      {

        long currentPosition = 0;
        do
        {
          GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest()
          {
            JobId = jobId,
            VaultName = vaultName
          };

          long endPosition = currentPosition + partSize - 1;
          if (endPosition > archiveSize)
            endPosition = archiveSize;

          getJobOutputRequest.SetRange(currentPosition, endPosition);
          GetJobOutputResponse getJobOutputResponse = client.GetJobOutput(getJobOutputRequest);

          using (Stream webStream = getJobOutputResponse.Body)
          {
            CopyStream(webStream, fileToSave);
          }
          currentPosition += partSize;
        } while (currentPosition < archiveSize);
      }
    }

    public static void CopyStream(Stream input, Stream output)
    {
      byte[] buffer = new byte[65536];
      int length;
      while ((length = input.Read(buffer, 0, buffer.Length)) > 0)
      {
        output.Write(buffer, 0, length);
      }
    }
  }
}
```

# Python을 통한 병렬 처리를 사용하여 대용량 아카이브 다운로드
<a name="downloading-large-archive-parallel-python"></a>

이 주제에서는 Python을 통한 병렬 처리를 사용하여 Amazon S3 Glacier(S3 Glacier)에서 대용량 아카이브를 다운로드하는 방법을 설명합니다. 이 접근 방식을 사용하면 아카이브를 독립적으로 처리할 수 있는 작은 조각으로 나누어 원하는 크기의 아카이브를 안정적으로 다운로드할 수 있습니다.

## 개요
<a name="downloading-large-archive-python-overview"></a>

이 예제에 제공된 Python 스크립트는 다음 작업을 수행합니다.

1. 알림에 필요한 AWS 리소스(Amazon SNS 주제 및 Amazon SQS 대기열)를 설정합니다.

1. Amazon Glacier에서 아카이브 가져오기 작업을 시작합니다.

1. Amazon SQS 대기열에서 작업 완료 알림을 모니터링합니다.

1. 대용량 아카이브를 관리 가능한 청크로 분할합니다.

1. 여러 작업자 스레드를 사용하여 청크를 병렬로 다운로드합니다.

1. 나중에 다시 조립할 수 있도록 각 청크를 디스크에 저장합니다.

## 사전 조건
<a name="downloading-large-archive-python-prerequisites"></a>

시작하기 전에, 다음 사항을 확인해야 합니다.
+ Python 3.6 이상 설치
+ AWS SDK for Python(Boto3) 설치됨
+ AWS Amazon Glacier, Amazon SNS 및 Amazon SQS에 대한 적절한 권한으로 구성된 자격 증명
+ 다운로드한 아카이브 청크를 저장하기에 충분한 디스크 공간

## 예: Python을 통한 병렬 처리를 사용하여 아카이브 다운로드
<a name="downloading-large-archive-python-code"></a>

다음 Python 스크립트는 병렬 처리를 사용하여 Amazon Glacier에서 대용량 아카이브를 다운로드하는 방법을 보여줍니다.

```
import boto3
import time
import json
import jmespath
import re
import concurrent.futures
import os

output_file_path = "output_directory_path"
vault_name = "vault_name"

chunk_size = 1000000000 #1gb - size of chunks for parallel download.
notify_queue_name = 'GlacierJobCompleteNotifyQueue' # SQS queue for Glacier recall notification
chunk_download_queue_name='GlacierChunkReadyNotifyQueue' # SQS queue for chunks
sns_topic_name = 'GlacierRecallJobCompleted' # the SNS topic to be notified when Glacier archive is restored.
chunk_queue_visibility_timeout = 7200 # 2 hours - this may need to be adjusted.
region = 'us-east-1'
archive_id = "archive_id_to_restore"
retrieve_archive = True # set to false if you do not want to restore from Glacier - useful for restarting or parallel processing of the chunk queue.
workers = 12 # the number of parallel worker threads for downloading chunks. 

def setup_queues_and_topic():
    sqs = boto3.client('sqs')
    sns = boto3.client('sns')

    # Create the SNS topic
    topic_response = sns.create_topic(
        Name=sns_topic_name
    )
    topic_arn = topic_response['TopicArn']
    print("Creating the SNS topic " + topic_arn)

    # Create the notification queue
    notify_queue_response = sqs.create_queue(
        QueueName=notify_queue_name,
        Attributes={
            'VisibilityTimeout': '300',  # 5 minutes
            'ReceiveMessageWaitTimeSeconds': '20'  # Enable long polling
        }
    )
    notify_queue_url = notify_queue_response['QueueUrl']
    print("Creating the archive-retrieval notification queue " + notify_queue_url)

    # Create the chunk download queue
    chunk_queue_response = sqs.create_queue(
        QueueName=chunk_download_queue_name,
        Attributes={
            'VisibilityTimeout': str(chunk_queue_visibility_timeout),  # 5 minutes
            'ReceiveMessageWaitTimeSeconds': '0'
        }
    )
    chunk_queue_url = chunk_queue_response['QueueUrl']

    print("Creating the chunk ready notification queue " + chunk_queue_url)


   # Get the ARN for the notification queue
    notify_queue_attributes = sqs.get_queue_attributes(
        QueueUrl=notify_queue_url,
        AttributeNames=['QueueArn']
    )
    notify_queue_arn = notify_queue_attributes['Attributes']['QueueArn']

    # Set up the SNS topic policy on the notification queue
    queue_policy = {
        "Version": "2012-10-17",		 	 	 
        "Statement": [{
            "Sid": "allow-sns-messages",
            "Effect": "Allow",
            "Principal": {"AWS": "*"},
            "Action": "SQS:SendMessage",
            "Resource": notify_queue_arn,
            "Condition": {
                "ArnEquals": {
                    "aws:SourceArn": topic_arn
                }
            }
        }]
    }

    # Set the queue policy
    sqs.set_queue_attributes(
        QueueUrl=notify_queue_url,
        Attributes={
            'Policy': json.dumps(queue_policy)
        }
    )

    # Subscribe the notification queue to the SNS topic
    sns.subscribe(
        TopicArn=topic_arn,
        Protocol='sqs',
        Endpoint=notify_queue_arn
    )

    return {
        'topic_arn': topic_arn,
        'notify_queue_url': notify_queue_url,
        'chunk_queue_url': chunk_queue_url
    }


def split_and_send_chunks(archive_size, job_id,chunk_queue_url):
    ranges = []
    current = 0
    chunk_number = 0

    while current < archive_size:
        chunk_number += 1
        next_range = min(current + chunk_size - 1, archive_size - 1)
        ranges.append((current, next_range, chunk_number))
        current = next_range + 1

    # Send messages to SQS queue
    for start, end, chunk_number in ranges:
        body = {"start": start, "end": end, "job_id": job_id, "chunk_number": chunk_number}
        body = json.dumps(body)
        print("Sending SQS message for range:" + str(body))
        response = sqs.send_message(
            QueueUrl=chunk_queue_url,
            MessageBody=str(body)
        )

def GetJobOutputChunks(job_id, byterange, chunk_number):
    glacier = boto3.client('glacier')
    response = glacier.get_job_output(
        vaultName=vault_name,
        jobId=job_id,
        range=byterange,

    )

    with open(os.path.join(output_file_path,str(chunk_number)+".chunk"), 'wb') as output_file:
        output_file.write(response['body'].read())

    return response

def ReceiveArchiveReadyMessages(notify_queue_url,chunk_queue_url):

    response = sqs.receive_message(
        QueueUrl=notify_queue_url,
        AttributeNames=['All'],
        MaxNumberOfMessages=1,
        WaitTimeSeconds=20,
        MessageAttributeNames=['Message']
    )
    print("Polling archive retrieval job ready queue...")
    # Checking that there is a Messages key before proceeding. No 'Messages' key likely means the queue is empty

    if 'Messages' in response:
        print("Received a message from the archive retrieval job queue")
        jsonresponse = response
        # Loading the string into JSON and checking that ArchiveSizeInBytes key is present before continuing.
        jsonresponse=json.loads(jsonresponse['Messages'][0]['Body'])
        jsonresponse=json.loads(jsonresponse['Message'])
        if 'ArchiveSizeInBytes' in jsonresponse:
            receipt_handle = response['Messages'][0]['ReceiptHandle']    
            if jsonresponse['ArchiveSizeInBytes']:
                archive_size = jsonresponse['ArchiveSizeInBytes']

                print(f'Received message: {response}')      
                if archive_size > chunk_size:
                    split_and_send_chunks(archive_size, jsonresponse['JobId'],chunk_queue_url)

                    sqs.delete_message(
                    QueueUrl=notify_queue_url,
                    ReceiptHandle=receipt_handle)

            else:
                print("No ArchiveSizeInBytes value found in message")
                print(response)

    else:
        print('No messages available in the queue at this time.')

    time.sleep(1)

def ReceiveArchiveChunkMessages(chunk_queue_url):
    response = sqs.receive_message(
        QueueUrl=chunk_queue_url,
        AttributeNames=['All'],
        MaxNumberOfMessages=1,
        WaitTimeSeconds=0,
        MessageAttributeNames=['Message']
    )
    print("Polling archive chunk queue...")
    print(response)
    # Checking that there is a Messages key before proceeding. No 'Messages' key likely means the queue is empty
    if 'Messages' in response:
        jsonresponse = response
        # Loading the string into JSON and checking that ArchiveSizeInBytes key is present before continuing.
        jsonresponse=json.loads(jsonresponse['Messages'][0]['Body'])
        if 'job_id' in jsonresponse: #checking that there is a job id before continuing
            job_id = jsonresponse['job_id']
            byterange = "bytes="+str(jsonresponse['start']) + '-' + str(jsonresponse['end'])
            chunk_number = jsonresponse['chunk_number']
            receipt_handle = response['Messages'][0]['ReceiptHandle']
            if jsonresponse['job_id']:
                print(f'Received message: {response}')
                GetJobOutputChunks(job_id,byterange,chunk_number)
                sqs.delete_message(
                QueueUrl=chunk_queue_url,
                ReceiptHandle=receipt_handle)
    else:
        print('No messages available in the chunk queue at this time.')

def initiate_archive_retrieval(archive_id, topic_arn):
    glacier = boto3.client('glacier')

    job_parameters = {
        "Type": "archive-retrieval",
        "ArchiveId": archive_id,
        "Description": "Archive retrieval job",
        "SNSTopic": topic_arn,
        "Tier": "Bulk"  # You can change this to "Standard" or "Expedited" based on your needs
    }

    try:
        response = glacier.initiate_job(
            vaultName=vault_name,
            jobParameters=job_parameters
        )

        print("Archive retrieval job initiated:")
        print(f"Job ID: {response['jobId']}")
        print(f"Job parameters: {job_parameters}")
        print(f"Complete response: {json.dumps(response, indent=2)}")

        return response['jobId']

    except Exception as e:
        print(f"Error initiating archive retrieval job: {str(e)}")
        raise

def run_async_tasks(chunk_queue_url, workers):
    max_workers = workers  # Set the desired maximum number of concurrent tasks
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        for _ in range(max_workers):
            executor.submit(ReceiveArchiveChunkMessages, chunk_queue_url)

# One time setup of the necessary queues and topics. 
queue_and_topic_atts = setup_queues_and_topic()

topic_arn = queue_and_topic_atts['topic_arn']
notify_queue_url = queue_and_topic_atts['notify_queue_url']
chunk_queue_url = queue_and_topic_atts['chunk_queue_url']

if retrieve_archive:
    print("Retrieving the defined archive... The topic arn we will notify when recalling the archive is: "+topic_arn)
    job_id = initiate_archive_retrieval(archive_id, topic_arn)
else:
    print("Retrieve archive is false, polling queues and downloading only.")

while True:
   ReceiveArchiveReadyMessages(notify_queue_url,chunk_queue_url)
   run_async_tasks(chunk_queue_url,workers)
```

## 스크립트 사용
<a name="downloading-large-archive-python-usage"></a>

이 스크립트를 사용하려면 다음 단계를 따르세요.

1. 스크립트의 자리 표시자 값을 특정 정보로 바꿉니다.
   + *output\$1file\$1path*: 청크 파일이 저장될 디렉터리
   + *vault\$1name*: S3 Glacier 볼트의 이름
   + *notify\$1queue\$1name*: 작업 알림 대기열의 이름
   + *chunk\$1download\$1queue\$1name*: 청크 다운로드 대기열의 이름
   + *sns\$1topic\$1name*: SNS 토픽의 이름
   + 볼트가 위치한 *region*: AWS region
   + *archive\$1id*: 검색할 아카이브의 ID

1. 스크립트를 실행합니다.

   ```
   python download_large_archive.py
   ```

1. 모든 청크를 다운로드한 후 다음과 같은 명령을 사용하여 청크를 단일 파일로 결합할 수 있습니다.

   ```
   cat /path/to/chunks/*.chunk > complete_archive.file
   ```

## 중요 고려 사항
<a name="downloading-large-archive-python-considerations"></a>

이 스크립트를 사용할 때는 다음 사항에 유의해야 합니다.
+ 선택한 검색 계층에 따라 S3 Glacier에서 아카이브 검색을 완료하는 데 몇 시간이 걸릴 수 있습니다.
+ 스크립트는 무기한 실행되어 대기열을 지속적으로 폴링합니다. 특정 요구 사항에 따라 종료 조건을 추가할 수 있습니다.
+ 아카이브의 모든 청크를 저장할 디스크 공간이 충분한지 확인합니다.
+ 스크립트가 중단되면 `retrieve_archive=False`를 사용해 다시 시작하여 새 검색 작업을 시작하지 않고 청크를 계속 다운로드할 수 있습니다.
+ 네트워크 대역폭 및 시스템 리소스에 따라 *chunk\$1size* 및 *workers* 파라미터를 조정합니다.
+ Amazon S3 검색, Amazon SNS 및 Amazon SQS 사용량에는 표준 AWS 요금이 적용됩니다.

# REST API를 사용하여 아카이브 다운로드
<a name="downloading-an-archive-using-rest"></a>

**REST API를 사용하여 아카이브 다운로드**

아카이브를 다운로드하는 작업은 2단계 프로세스로 구성됩니다.

1. `archive-retrieval` 유형의 작업을 시작합니다. 자세한 내용은 [작업 시작(POST jobs)](api-initiate-job-post.md) 단원을 참조하십시오.

1. 작업이 완료된 후 아카이브 데이터를 다운로드합니다. 자세한 내용은 [작업 출력 가져오기(GET output)](api-job-output-get.md) 단원을 참조하십시오.

# 를 사용하여 Amazon Glacier에서 아카이브 다운로드 AWS CLI
<a name="downloading-an-archive-using-cli"></a>

 AWS Command Line Interface ()를 사용하여 Amazon Glacier(Amazon Glacier)에서 아카이브를 다운로드할 수 있습니다AWS CLI.

**Topics**
+ [(사전 조건) 설정 AWS CLI](#Creating-Vaults-CLI-Setup)
+ [예:를 사용하여 아카이브 다운로드 AWS CLI](#Downloading-Archives-CLI-Implementation)

## (사전 조건) 설정 AWS CLI
<a name="Creating-Vaults-CLI-Setup"></a>

1.  AWS CLI를 다운로드하고 구성합니다. 관련 지침은 *AWS Command Line Interface 사용 설명서*에서 다음 토픽을 참조하세요.

    [설치 AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/installing.html) 

   [구성 AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)

1. 명령 프롬프트에 다음 명령을 입력하여 AWS CLI 설정을 확인합니다. 이러한 명령은 명시적으로 자격 증명을 제공하지 않으므로 기본 프로파일의 자격 증명이 사용됩니다.
   + help 명령을 사용해 보십시오.

     ```
     aws help
     ```
   + 구성된 계정의 Amazon Glacier 볼트 목록을 가져오려면 `list-vaults` 명령을 사용합니다. *123456789012*을 AWS 계정 ID로 바꿉니다.

     ```
     aws glacier list-vaults --account-id 123456789012
     ```
   + 에 대한 현재 구성 데이터를 보려면 `aws configure list` 명령을 AWS CLI사용합니다.

     ```
     aws configure list
     ```

## 예:를 사용하여 아카이브 다운로드 AWS CLI
<a name="Downloading-Archives-CLI-Implementation"></a>
**참고**  
아카이브를 다운로드하려면 반드시 아카이브 ID를 알아야 합니다. 1\$14단계를 따라 아카이브 ID를 검색합니다. 다운로드하려는 아카이브 ID를 이미 알고 있는 경우 5단계로 건너뛰세요.

1. `initiate-job` 명령을 사용하여 인벤토리 검색 작업을 시작합니다. 인벤토리 보고서에는 사용자의 아카이브 ID가 나열됩니다.

   ```
   aws glacier initiate-job --vault-name awsexamplevault --account-id 111122223333 --job-parameters="{\"Type\":\"inventory-retrieval\"}"
   ```

    예상 결과:

   ```
   {
       "location": "/111122223333/vaults/awsexamplevault/jobs/*** jobid ***", 
       "jobId": "*** jobid ***"
   }
   ```

1. `describe-job` 명령을 사용하여 이전 `` 작업의 명령의 상태를 확인합니다.

   ```
   aws glacier describe-job --vault-name awsexamplevault --account-id 111122223333 --job-id *** jobid ***
   ```

    예상 결과:

   ```
   {
       "InventoryRetrievalParameters": {
           "Format": "JSON"
       }, 
       "VaultARN": "*** vault arn ***", 
       "Completed": false, 
       "JobId": "*** jobid ***", 
       "Action": "InventoryRetrieval", 
       "CreationDate": "*** job creation date ***", 
       "StatusCode": "InProgress"
   }
   ```

1.  작업이 완료될 때까지 기다립니다.

   작업 출력을 다운로드할 수 있을 때까지 기다려야 합니다. 볼트에서 알림 구성을 설정하거나 작업을 시작할 때 Amazon Simple Notification Service(Amazon SNS) 토픽을 지정했다면 Amazon Glacier가 작업 완료 후 해당 토픽에 메시지를 보냅니다.

   볼트의 특정 이벤트에 대해 알림 구성을 설정할 수 있습니다. 자세한 내용은 [Amazon Glacier의 볼트 알림 구성](configuring-notifications.md) 단원을 참조하십시오. Amazon Glacier는 특정 이벤트가 발생할 때마다 지정된 SNS 토픽에 메시지를 보냅니다.

1. 완료되면 `get-job-output` 명령을 사용하여 검색 작업을 `output.json` 파일로 다운로드합니다. 이 파일에는 사용자의 아카이브 ID가 포함될 것입니다.

   ```
   aws glacier get-job-output --vault-name awsexamplevault --account-id 111122223333 --job-id *** jobid *** output.json
   ```

   이 명령은 다음 필드가 있는 파일을 생성합니다.

   ```
   {
   "VaultARN":"arn:aws:glacier:region:111122223333:vaults/awsexamplevault",
   "InventoryDate":"*** job completion date ***",
   "ArchiveList":[
   {"ArchiveId":"*** archiveid ***",
   "ArchiveDescription":*** archive description (if set) ***,
   "CreationDate":"*** archive creation date ***",
   "Size":"*** archive size (in bytes) ***",
   "SHA256TreeHash":"*** archive hash ***"
   }
   {"ArchiveId":
   ...
   ]}
   ```

1. `initiate-job` 명령을 사용하여 볼트에서 각 아카이브를 검색하는 프로세스를 시작합니다. 아래 `archive-retrieval`과 같이 작업 파라미터를 지정해야 합니다.

   ```
   aws glacier initiate-job --vault-name awsexamplevault --account-id 111122223333 --job-parameters="{\"Type\":\"archive-retrieval\",\"ArchiveId\":\"*** archiveId ***\"}"
   ```

1. `archive-retrieval` 작업이 완료될 때까지 기다립니다. `describe-job` 명령을 사용하여 이전 명령의 상태를 확인합니다.

   ```
   aws glacier describe-job --vault-name awsexamplevault --account-id 111122223333 --job-id *** jobid ***
   ```

1. 위 작업이 완료되면 `get-job-output` 명령을 사용하여 아카이브를 다운로드합니다.

   ```
   aws glacier get-job-output --vault-name awsexamplevault --account-id 111122223333 --job-id *** jobid *** output_file_name
   ```

# Amazon Glacier에서 아카이브 삭제
<a name="deleting-an-archive"></a>

Amazon Glacier(Amazon Glacier) 관리 콘솔을 사용하여 아카이브를 삭제할 수 없습니다. 아카이브를 삭제하려면 AWS Command Line Interface (CLI) 또는 쓰기 코드를 사용하여 REST API 직접 또는 AWS SDK for Java 및 .NET 래퍼 라이브러리를 사용하여 삭제 요청을 해야 합니다. 다음 주제에서는 AWS SDK for Java 및 .NET 래퍼 라이브러리, REST API 및를 사용하는 방법을 설명합니다 AWS CLI.

**Topics**
+ [AWS SDK for Java를 사용하여 Amazon Glacier에서 아카이브 삭제](deleting-an-archive-using-java.md)
+ [를 사용하여 Amazon Glacier에서 아카이브 삭제 AWS SDK for .NET](deleting-an-archive-using-dot-net.md)
+ [REST API를 사용하여 Amazon Glacier 아카이브 삭제](deleting-an-archive-using-rest.md)
+ [를 사용하여 Amazon Glacier에서 아카이브 삭제 AWS Command Line Interface](deleting-an-archive-using-cli.md)

아카이브는 볼트에서 한 번에 하나씩 삭제할 수 있습니다. 아카이브를 삭제하려면 삭제 요청 시 아카이브 ID를 입력해야 합니다. 아카이브 ID는 해당 아카이브가 포함된 볼트에서 볼트 인벤토리를 다운로드하여 가져올 수 있습니다. 볼트 인벤토리 다운로드에 대한 자세한 내용은 [Amazon Glacier에서 볼트 인벤토리 다운로드](vault-inventory.md) 섹션을 참조하세요.

아카이브를 삭제한 후에도 삭제한 아카이브를 가져오는 작업을 시작할 수 있도록 요청하는 것은 가능하지만 아카이브 가져오기 작업이 실행되지는 않습니다.

아카이브를 삭제할 때 아카이브 ID에 대해 진행 중인 아카이브 가져오기는 다음 시나리오에 따라 성공할 수도, 혹은 성공하지 않을 수도 있습니다.

 
+ Amazon Glacier가 아카이브 삭제 요청을 수신할 때, 아카이브 가져오기 작업이 활성화되어 데이터 다운로드를 준비하고 있다면 아카이브 가져오기 작업이 중단될 수도 있습니다.
+ Amazon Glacier가 아카이브 삭제 요청을 수신할 때 아카이브 가져오기 작업이 아카이브 다운로드를 성공적으로 준비했다면 출력을 다운로드할 수 있습니다.

아카이브 가져오기에 대한 자세한 내용은 [Amazon Glacier에서 아카이브 다운로드](downloading-an-archive.md) 섹션을 참조하세요.

이 작업은 멱등성을 갖습니다. 이미 삭제된 아카이브를 삭제하려고 해도 오류가 발생하지는 않습니다.

아카이브를 삭제한 직후에 볼트 인벤토리를 다운로드할 경우 삭제된 아카이브가 목록에 포함될 수도 있습니다. Amazon Glacier는 하루에 한 번만 볼트 인벤토리를 준비하기 때문입니다.

**참고**  
볼트 아카이브의 자동 삭제는 [Amazon S3 Glacier에서 볼트 아카이브의 자동 삭제](https://aws.amazon.com/solutions/guidance/automated-deletion-of-vault-archives-in-amazon-s3-glacier/)를 참조하세요.

# AWS SDK for Java를 사용하여 Amazon Glacier에서 아카이브 삭제
<a name="deleting-an-archive-using-java"></a>

다음은 AWS SDK for Java의 로우레벨 API를 사용해 아카이브를 삭제하는 단계입니다.

 

1. `AmazonGlacierClient` 클래스(클라이언트)의 인스턴스를 만듭니다.

   삭제를 원하는 아카이브가 저장된 AWS 리전을 지정합니다. 이 클라이언트를 사용하여 실행하는 모든 작업이 해당 AWS 리전에 적용됩니다.

1. `DeleteArchiveRequest` 클래스 인스턴스를 생성하여 요청 정보를 입력합니다.

   아카이브 ID와 볼트 이름, 그리고 계정 ID를 입력해야 합니다. 계정 ID를 입력하지 않는 경우에는 요청 서명을 위해 입력하는 자격 증명과 연결되어 있는 계정 ID로 간주합니다. 자세한 내용은 [Amazon Glacier AWS SDK for Java 에서 사용](using-aws-sdk-for-java.md) 섹션을 참조하세요.

1. 요청 객체를 파라미터로 입력하여 `deleteArchive` 메서드를 실행합니다.

다음은 위에서 설명한 단계를 나타내는 Java 코드 조각입니다.

```
AmazonGlacierClient client;

DeleteArchiveRequest request = new DeleteArchiveRequest()
    .withVaultName("*** provide a vault name ***")
    .withArchiveId("*** provide an archive ID ***");

client.deleteArchive(request);
```

 

**참고**  
기본 REST API에 대한 자세한 내용은 [아카이브 삭제(DELETE archive)](api-archive-delete.md) 섹션을 참조하세요.

## 예: AWS SDK for Java를 사용하여 아카이브 삭제
<a name="deleting-an-archive-using-java-example"></a>

다음은 AWS SDK for Java를 이용해 아카이브를 삭제하는 Java 코드 예제입니다. 이 예제의 실행 방법에 대한 단계별 지침은 [Eclipse를 사용하여 Amazon Glacier의 Java 예 실행](using-aws-sdk-for-java.md#setting-up-and-testing-sdk-java) 섹션을 참조하세요. 아래와 같이 볼트 이름과 삭제를 원하는 아카이브의 아카이브 ID를 사용해 코드를 업데이트해야 합니다.

**Example**  

```
import java.io.IOException;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.model.DeleteArchiveRequest;

public class ArchiveDelete {

    public static String vaultName = "*** provide vault name ****";
    public static String archiveId = "*** provide archive ID***";
    public static AmazonGlacierClient client;
    
    public static void main(String[] args) throws IOException {
        
    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();

        client = new AmazonGlacierClient(credentials);
        client.setEndpoint("https://glacier.us-east-1.amazonaws.com/");        

        try {

            // Delete the archive.
            client.deleteArchive(new DeleteArchiveRequest()
                .withVaultName(vaultName)
                .withArchiveId(archiveId));
            
            System.out.println("Deleted archive successfully.");
            
        } catch (Exception e) {
            System.err.println("Archive not deleted.");
            System.err.println(e);
        }
    }
}
```

# 를 사용하여 Amazon Glacier에서 아카이브 삭제 AWS SDK for .NET
<a name="deleting-an-archive-using-dot-net"></a>

.NET용 Amazon SDK에서 제공하는 [하이레벨 및 로우레벨 API](using-aws-sdk.md)는 모두 아카이브를 삭제하는 방법을 제공합니다.

**Topics**
+ [의 상위 수준 API를 사용하여 아카이브 삭제 AWS SDK for .NET](#delete-archive-using-dot-net-high-level)
+ [하위 수준 API를 사용하여 아카이브 삭제 AWS SDK for .NET](#delete-archive-using-dot-net-low-level)

## 의 상위 수준 API를 사용하여 아카이브 삭제 AWS SDK for .NET
<a name="delete-archive-using-dot-net-high-level"></a>

하이레벨 API의 `ArchiveTransferManager` 클래스는 아카이브를 삭제하는 데 사용할 수 있는 `DeleteArchive` 메서드를 제공합니다.

### 예:의 상위 수준 API를 사용하여 아카이브 삭제 AWS SDK for .NET
<a name="delete-archive-dot-net-high-level-example"></a>

다음 C\$1 코드 예제에서는의 상위 수준 API AWS SDK for .NET 를 사용하여 아카이브를 삭제합니다. 이 예제의 실행 방법에 대한 단계별 지침은 [코드 예제 실행](using-aws-sdk-for-dot-net.md#setting-up-and-testing-sdk-dotnet) 섹션을 참조하세요. 아래와 같이 삭제를 원하는 아카이브의 아카이브 ID를 사용해 코드를 업데이트합니다.

**Example**  

```
using System;
using Amazon.Glacier;
using Amazon.Glacier.Transfer;
using Amazon.Runtime; 

namespace glacier.amazon.com.rproxy.govskope.us.docsamples
{
  class ArchiveDeleteHighLevel
  {
    static string vaultName = "examplevault";
    static string archiveId = "*** Provide archive ID ***";

    public static void Main(string[] args)
    {
      try
      {
        var manager = new ArchiveTransferManager(Amazon.RegionEndpoint.USWest2);
        manager.DeleteArchive(vaultName, archiveId);
        Console.ReadKey();
      }
      catch (AmazonGlacierException e) { Console.WriteLine(e.Message); }
      catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
      catch (Exception e) { Console.WriteLine(e.Message); }
      Console.WriteLine("To continue, press Enter");
      Console.ReadKey();
    }
  }
}
```

## 하위 수준 API를 사용하여 아카이브 삭제 AWS SDK for .NET
<a name="delete-archive-using-dot-net-low-level"></a>

다음은 AWS SDK for .NET를 사용하여 삭제하는 단계입니다.

 

1. `AmazonGlacierClient` 클래스(클라이언트)의 인스턴스를 만듭니다.

   삭제하려는 아카이브가 저장되는 AWS 리전을 지정해야 합니다. 이 클라이언트를 사용하여 수행하는 모든 작업은 해당 AWS 리전에 적용됩니다.

1. `DeleteArchiveRequest` 클래스 인스턴스를 생성하여 요청 정보를 입력합니다.

   아카이브 ID와 볼트 이름, 그리고 계정 ID를 입력해야 합니다. 계정 ID를 입력하지 않는 경우에는 요청 서명을 위해 입력하는 자격 증명과 연결되어 있는 계정 ID로 간주합니다. 자세한 내용은 [Amazon Glacier에서 AWS SDKs 사용](using-aws-sdk.md) 단원을 참조하십시오.

1. 요청 객체를 파라미터로 입력하여 `DeleteArchive` 메서드를 실행합니다.

### 예:의 하위 수준 API를 사용하여 아카이브 삭제 AWS SDK for .NET
<a name="delete-archive-dot-net-low-level-example"></a>

다음은 앞선 단계를 설명하는 C\$1 예제입니다. 이 예제에서는의 하위 수준 API AWS SDK for .NET 를 사용하여 아카이브를 삭제합니다.

**참고**  
기본 REST API에 대한 자세한 내용은 [아카이브 삭제(DELETE archive)](api-archive-delete.md) 섹션을 참조하세요.

 이 예제의 실행 방법에 대한 단계별 지침은 [코드 예제 실행](using-aws-sdk-for-dot-net.md#setting-up-and-testing-sdk-dotnet) 섹션을 참조하세요. 아래와 같이 삭제를 원하는 아카이브의 아카이브 ID를 사용해 코드를 업데이트합니다.

**Example**  

```
using System;
using Amazon.Glacier;
using Amazon.Glacier.Model;
using Amazon.Runtime;

namespace glacier.amazon.com.rproxy.govskope.us.docsamples
{
  class ArchiveDeleteLowLevel
  {
    static string vaultName = "examplevault";
    static string archiveId = "*** Provide archive ID ***";

    public static void Main(string[] args)
    {
      AmazonGlacierClient client;
      try
      {
        using (client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2))
        {
          Console.WriteLine("Deleting the archive");
          DeleteAnArchive(client);
        }
        Console.WriteLine("Operations successful. To continue, press Enter");
        Console.ReadKey();
      }
      catch (AmazonGlacierException e) { Console.WriteLine(e.Message); }
      catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
      catch (Exception e) { Console.WriteLine(e.Message); }
      Console.WriteLine("To continue, press Enter");
      Console.ReadKey();
    }

    static void DeleteAnArchive(AmazonGlacierClient client)
    {
      DeleteArchiveRequest request = new DeleteArchiveRequest()
      {
        VaultName = vaultName,
        ArchiveId = archiveId
      };
      DeleteArchiveResponse response = client.DeleteArchive(request);
    }
  }
}
```

# REST API를 사용하여 Amazon Glacier 아카이브 삭제
<a name="deleting-an-archive-using-rest"></a>

아카이브는 아카이브 삭제 API를 사용하여 삭제할 수 있습니다.
+ 아카이브 삭제 API에 대한 자세한 내용은 [아카이브 삭제(DELETE archive)](api-archive-delete.md) 섹션을 참조하세요.
+ REST API 사용에 대한 자세한 내용은 [Amazon Glacier를 위한 API 참조](amazon-glacier-api.md) 섹션을 참조하세요.

# 를 사용하여 Amazon Glacier에서 아카이브 삭제 AWS Command Line Interface
<a name="deleting-an-archive-using-cli"></a>

 AWS Command Line Interface ()를 사용하여 Amazon Glacier(Amazon Glacier)에서 아카이브를 삭제할 수 있습니다AWS CLI.

**Topics**
+ [(사전 조건) 설정 AWS CLI](#Creating-Vaults-CLI-Setup)
+ [예:를 사용하여 아카이브 삭제 AWS CLI](#Deleting-Archives-CLI-Implementation)

## (사전 조건) 설정 AWS CLI
<a name="Creating-Vaults-CLI-Setup"></a>

1.  AWS CLI를 다운로드하고 구성합니다. 관련 지침은 *AWS Command Line Interface 사용 설명서*에서 다음 토픽을 참조하세요.

    [설치 AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/installing.html) 

   [구성 AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)

1. 명령 프롬프트에 다음 명령을 입력하여 AWS CLI 설정을 확인합니다. 이러한 명령은 명시적으로 자격 증명을 제공하지 않으므로 기본 프로파일의 자격 증명이 사용됩니다.
   + help 명령을 사용해 보십시오.

     ```
     aws help
     ```
   + 구성된 계정의 Amazon Glacier 볼트 목록을 가져오려면 `list-vaults` 명령을 사용합니다. *123456789012*을 AWS 계정 ID로 바꿉니다.

     ```
     aws glacier list-vaults --account-id 123456789012
     ```
   + 에 대한 현재 구성 데이터를 보려면 `aws configure list` 명령을 AWS CLI사용합니다.

     ```
     aws configure list
     ```

## 예:를 사용하여 아카이브 삭제 AWS CLI
<a name="Deleting-Archives-CLI-Implementation"></a>

1. [https://docs.aws.amazon.com/cli/latest/reference/glacier/initiate-job.html](https://docs.aws.amazon.com/cli/latest/reference/glacier/initiate-job.html) 명령을 사용하여 인벤토리 검색 작업을 시작합니다.

   ```
   aws glacier initiate-job --vault-name awsexamplevault --account-id 111122223333 --job-parameters="{\"Type\":\"inventory-retrieval\"}"
   ```

    예상 결과:

   ```
   {
       "location": "/111122223333/vaults/awsexamplevault/jobs/*** jobid ***", 
       "jobId": "*** jobid ***"
   }
   ```

1. [https://docs.aws.amazon.com/cli/latest/reference/glacier/describe-job.html](https://docs.aws.amazon.com/cli/latest/reference/glacier/describe-job.html) 명령을 사용하여 이전 검색 작업의 상태를 확인합니다.

   ```
   aws glacier describe-job --vault-name awsexamplevault --account-id 111122223333 --job-id *** jobid ***
   ```

    예상 결과:

   ```
   {
       "InventoryRetrievalParameters": {
           "Format": "JSON"
       }, 
       "VaultARN": "*** vault arn ***", 
       "Completed": false, 
       "JobId": "*** jobid ***", 
       "Action": "InventoryRetrieval", 
       "CreationDate": "*** job creation date ***", 
       "StatusCode": "InProgress"
   }
   ```

1.  작업이 완료될 때까지 기다립니다.

   작업 출력을 다운로드할 수 있을 때까지 기다려야 합니다. 볼트에서 알림 구성을 설정하거나 작업을 시작할 때 Amazon Simple Notification Service(Amazon SNS) 토픽을 지정했다면 Amazon Glacier가 작업 완료 후 해당 토픽에 메시지를 보냅니다.

   볼트의 특정 이벤트에 대해 알림 구성을 설정할 수 있습니다. 자세한 내용은 [Amazon Glacier의 볼트 알림 구성](configuring-notifications.md) 단원을 참조하십시오. Amazon Glacier는 특정 이벤트가 발생할 때마다 지정된 SNS 토픽에 메시지를 보냅니다.

1. 완료되면 [https://docs.aws.amazon.com/cli/latest/reference/glacier/get-job-output.html](https://docs.aws.amazon.com/cli/latest/reference/glacier/get-job-output.html) 명령을 사용하여 검색 작업을 `output.json` 파일로 다운로드합니다.

   ```
   aws glacier get-job-output --vault-name awsexamplevault --account-id 111122223333 --job-id *** jobid *** output.json
   ```

   이 명령은 다음 필드가 있는 파일을 생성합니다.

   ```
   {
   "VaultARN":"arn:aws:glacier:region:111122223333:vaults/awsexamplevault",
   "InventoryDate":"*** job completion date ***",
   "ArchiveList":[
   {"ArchiveId":"*** archiveid ***",
   "ArchiveDescription":*** archive description (if set) ***,
   "CreationDate":"*** archive creation date ***",
   "Size":"*** archive size (in bytes) ***",
   "SHA256TreeHash":"*** archive hash ***"
   }
   {"ArchiveId":
   ...
   ]}
   ```

1. `delete-archive` 명령을 사용하여 볼트가 비워질 때까지 볼트에서 각 아카이브를 삭제합니다.

   ```
   aws glacier delete-archive --vault-name awsexamplevault --account-id 111122223333 --archive-id *** archiveid ***
   ```