

# 객체 업로드
<a name="upload-objects"></a>

Amazon S3에 파일을 업로드하면 이 파일은 S3 객체로 저장됩니다.** 객체는 파일 데이터 및 그 객체를 설명하는 메타데이터로 구성됩니다. 또한 버킷에 저장할 수 있는 객체 수에는 제한이 없습니다. Amazon S3 버킷에 파일을 업로드하려면 해당 버킷에 대한 쓰기 권한이 있어야 합니다. 액세스 권한에 대한 자세한 내용은 [Amazon S3의 ID 및 액세스 관리](security-iam.md)을 참조하십시오.

이미지, 백업, 데이터, 동영상 등 모든 유형의 파일을 S3 버킷에 업로드할 수 있습니다. Amazon S3 콘솔을 사용하여 업로드할 수 있는 파일의 최대 크기는 160GB입니다. 160GB가 넘는 파일을 업로드하려면 AWS Command Line Interface(AWS CLI), AWS SDK 또는 Amazon S3 REST API를 사용하십시오.

버전 관리를 사용하는 버킷에 이미 키 이름이 있는 객체를 업로드하면 Amazon S3는 기존 객체를 대체하는 대신 객체의 다른 버전을 만듭니다. 버전 관리 활성화에 대한 자세한 내용은 [버킷에 버전 관리 사용 설정](manage-versioning-examples.md) 섹션을 참조하세요.

 업로드하는 데이터의 크기에 따라 Amazon S3는 다음과 같은 옵션을 제공합니다.
+ **AWS SDK, REST API 또는 AWS CLI를 사용하여 단일 작업으로 객체 업로드** - 단일 `PUT` 작업으로 최대 5GB 크기의 단일 객체를 업로드할 수 있습니다.
+ **Amazon S3 콘솔을 사용하여 단일 객체 업로드**** -** Amazon S3 콘솔을 사용하면 최대 160GB 크기의 단일 객체를 업로드할 수 있습니다.
+ **AWS SDK, REST API 또는 AWS CLI를 사용하여 부분으로 나누어 객체 업로드**** -** 멀티파트 업로드 API 작업을 사용하여 최대 50TB 크기의 단일 대형 객체를 업로드할 수 있습니다.

  멀티파트 업로드 API 작업은 대용량 객체의 업로드 경험을 개선하기 위해 설계되었습니다. 객체를 부분별로 업로드할 수 있습니다. 이러한 객체 부분은 임의의 순서로 독립적으로, 그리고 병렬적으로 업로드할 수 있습니다. 크기가 5MB에서 50TB까지인 객체에 대해 멀티파트 업로드를 사용할 수 있습니다. 자세한 내용은 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하세요.

5TB를 초과하는 파일을 업로드하려면 Java v1/v2, Python 또는 AWS CLI SDK에서 S3 Transfer Manager를 사용합니다. 최상의 성능을 얻으려면 리소스 사용률을 높이기 위해 최적화된 최신 AWS 공통 런타임(CRT)SDK와 함께 사용합니다.

메모리 스트림에서 대용량 객체를 업로드할 때 CRT는 각 부분을 최대 5GB의 메모리로 버퍼링하여 할당된 메모리의 전체 처리량을 제한합니다. Java SDK용 `maxNativeMemoryLimitInBytes`와 같은 구성 옵션을 사용하여 CRT 메모리 제한을 조정할 수 있습니다. 디스크에서 업로드하는 경우 CRT는 중간 부분 버퍼링 대신 직접 디스크 스트리밍으로 자동 전환하여 메모리 사용량을 개선합니다. 이 동작은 대형 객체에 대해 자동으로 활성화되지만 AWS CLI용 `should_stream` 및 Java SDK용 `CRT_MEMORY_BUFFER_DISABLED` 같은 요청 파라미터를 통해 더 작은 파일에 대해서도 활성화할 수 있습니다.

객체를 업로드할 때 기본적으로 Amazon S3 관리형 키(SSE-S3)를 통한 서버 측 암호화를 사용하여 객체가 자동으로 암호화됩니다. 다운로드하면 객체의 암호가 해독됩니다. 자세한 내용은 [Amazon S3 버킷에 대한 기본 서버 측 암호화 동작 설정](bucket-encryption.md) 및 [암호화로 데이터 보호](UsingEncryption.md)(을)를 참조하세요.

객체를 업로드할 때 다른 유형의 기본 암호화를 사용하려는 경우 S3 `PUT` 요청에서 AWS Key Management Service(AWS KMS) 키(SSE-KMS)를 사용하여 서버 측 암호화를 지정하거나 SSE-KMS를 사용하여 데이터를 암호화하도록 대상 버킷의 기본 암호화 구성을 설정할 수도 있습니다. SSE-KMS에 대한 자세한 내용은 [AWS KMS(SSE-KMS)를 사용한 서버 측 암호화 지정](specifying-kms-encryption.md) 단원을 참조하십시오. 다른 계정에서 소유한 KMS 키를 사용하려면 먼저 해당 키에 대한 사용 권한이 있어야 합니다. KMS 키의 크로스 계정 권한에 대한 자세한 내용은 **AWS Key Management Service 개발자 안내서에서 [다른 계정에서 사용할 수 있는 KMS 키 만들기](https://docs.aws.amazon.com//kms/latest/developerguide/key-policy-modifying-external-accounts.html#cross-account-console)를 참조하십시오.

Amazon S3에서 액세스 거부됨(403 Forbidden) 오류가 발생하는 경우 [Amazon S3의 액세스 거부(403 Forbidden) 오류 문제 해결](troubleshoot-403-errors.md) 섹션에서 일반적인 원인에 대해 자세히 알아보세요.

## 객체 업로드
<a name="upload-objects-procedure"></a>

### S3 콘솔 사용
<a name="upload-objects-by-drag-and-drop"></a>

이 절차는 콘솔을 사용하여 Amazon S3 버킷에 객체 및 폴더를 업로드하는 방법을 설명합니다.

객체를 업로드할 때 객체 키 이름은 파일 이름과 선택적 접두사입니다. Amazon S3 콘솔에서 폴더를 생성하여 객체를 구성할 수 있습니다. Amazon S3에서 폴더는 객체 키 이름에 나타나는 접두사로 표시됩니다. Amazon S3 콘솔의 폴더에 개별 객체를 업로드하면 객체 키 이름에 폴더 이름이 포함됩니다.

예를 들어 이름이 `sample1.jpg`인 객체를 이름이 `backup`인 폴더에 업로드하는 경우 키 이름은 `backup/sample1.jpg`입니다. 그러나 콘솔에는 해당 객체가 `sample1.jpg` 폴더의 `backup`로 표시됩니다. 키 이름에 대한 자세한 내용은 [객체 메타데이터 작업](UsingMetadata.md) 섹션을 참조하세요.

**참고**  
Amazon S3 콘솔에서 객체 이름을 바꾸거나 **스토리지 클래스**, **암호화** 또는 **메타데이터** 등의 속성을 변경하면 새 객체가 생성되어 이전 객체를 대체합니다. S3 버전 관리가 사용 설정된 경우 객체의 새 버전이 생성되고 기존 객체는 이전 버전이 됩니다. 또한 속성을 변경하는 역할도 새 객체(또는 객체 버전)의 소유자가 됩니다.

폴더를 업로드하면 Amazon S3는 지정된 폴더의 모든 파일과 하위 폴더를 버킷으로 업로드합니다. 그러면 업로드된 파일 이름과 폴더 이름을 조합하여 객체 키 이름이 지정됩니다. 예를 들어 `/images` 및 `sample1.jpg`라는 두 개의 파일을 포함하는 폴더 `sample2.jpg`를 업로드하는 경우 Amazon S3는 파일을 업로드한 후 해당 키 이름인 `images/sample1.jpg` 및 `images/sample2.jpg`를 할당합니다. 키 이름에는 폴더 이름이 접두사로 포함됩니다. Amazon S3 콘솔에는 마지막 `/` 이후의 키 이름 부분만 표시됩니다. 예를 들어, `images` 폴더에서 `images/sample1.jpg` 및 `images/sample2.jpg` 객체는 `sample1.jpg` 및 `sample2.jpg`로 표시됩니다.<a name="upload-files-folders"></a>

**S3 버킷에 폴더 및 파일 업로드**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)에서 S3 콘솔을 엽니다.

1. 왼쪽 탐색 창에서 **버킷(Buckets)**을 선택합니다.

1. **버킷** 목록에서 폴더 또는 파일을 업로드할 버킷 이름을 선택합니다.

1. **업로드**를 선택합니다.

1. **업로드** 창에서 다음 중 하나를 수행합니다.
   + 파일 및 폴더를 **업로드** 창으로 끌어다 놓습니다.
   + **파일 추가** 또는 **폴더 추가**를 선택하고 업로드할 파일 또는 폴더를 선택한 후 **열기**를 선택합니다.

1. 버전 관리를 사용 설정하려면 **대상**에서 **버킷 버전 관리 사용 설정**를 선택합니다.

1. 추가 업로드 옵션을 구성하지 않고 나열된 파일 및 폴더를 업로드하려면 페이지 하단에서 **업로드**를 선택합니다.

   Amazon S3가 객체와 폴더를 업로드합니다. 업로드가 완료되면 **업로드: 상태** 페이지에서 성공 메시지를 볼 수 있습니다.<a name="configure-additional-properties"></a>

**추가 객체 속성 구성**

1. 액세스 제어 목록 권한을 변경하려면 **권한(Permissions)**을 선택합니다.

1. **액세스 제어 목록(ACL)(Access control list (ACL))**에서 권한을 편집합니다.

   객체 액세스 권한에 대한 자세한 내용은 [S3 콘솔을 사용하여 객체에 대한 ACL 권한 설정](managing-acls.md#set-object-permissions)를 참조하십시오. 현재 업로드 중인 모든 파일에 대해 대중(전 세계 모든 사람)에게 객체에 대한 읽기 액세스 권한을 부여할 수 있습니다. 그러나 퍼블릭 읽기 액세스의 기본 설정은 변경하지 않는 것이 좋습니다. 퍼블릭 읽기 액세스 권한 부여는 웹 사이트에 버킷을 사용하는 경우와 같은 소수의 사용 사례에 적용될 수 있습니다. 객체를 업로드한 후에도 언제든 객체 권한을 변경할 수 있습니다.

1. 다른 추가 속성을 구성하려면 **속성(Properties)**을 선택합니다.

1. **스토리지 클래스**에서 업로드하려는 파일의 스토리지 클래스를 선택합니다.

   스토리지 클래스에 대한 자세한 정보는 [Amazon S3 스토리지 클래스 이해 및 관리](storage-class-intro.md)를 참조하세요.

1. 객체에 대한 암호화 설정을 업데이트하려면 **서버 측 암호화 설정**에서 다음을 수행합니다.

   1. **암호화 키 지정(Specify an encryption key)**을 선택합니다.

   1. **암호화 설정**에서 **버킷 기본 암호화 설정 사용** 또는 **기본 암호화에 버킷 설정 재정의**를 선택합니다.

   1. **기본 암호화에 버킷 설정 재정의**를 선택한 경우 다음과 같은 암호화 설정을 구성해야 합니다.
      + Amazon S3에서 관리하는 키를 사용하여 업로드된 파일을 암호화하려면 **Amazon S3 관리형 키(SSE-S3)**를 선택합니다.

        자세한 내용은 [Amazon S3 관리형 키를 사용한 서버 측 암호화(SSE-S3) 사용](UsingServerSideEncryption.md) 섹션을 참조하세요.
      + AWS Key Management Service(AWS KMS)에 저장된 키를 사용하여 업로드된 파일을 암호화하려면 **AWS Key Management Service 키(SSE-KMS)**를 선택합니다. 그리고 나서 **AWS KMS 키**에 다음 옵션 중 하나를 선택합니다.
        + 사용 가능한 KMS 키 목록에서 **AWS KMS keys 중에서 선택**을 선택한 다음, 사용 가능한 키 목록에서 **KMS 키**를 선택합니다.

          AWS 관리형 키(`aws/s3`)와 고객 관리형 키가 모두 목록에 표시됩니다. 고객 관리형 키에 대한 자세한 내용은 *AWS Key Management Service* 개발자 안내서의 [ 고객 키 및 AWS 키](https://docs.aws.amazon.com//kms/latest/developerguide/concepts.html#key-mgmt)를 참조하세요.
        + KMS 키 ARN을 입력하려면 **AWS KMS key ARN 입력**을 선택한 다음 나타나는 필드에 KMS 키 ARN을 입력합니다.
        + AWS KMS 콘솔에서 고객 관리형 키를 생성하려면 **KMS 키 생성**을 선택합니다.

          AWS KMS key 생성에 대한 자세한 내용은 *AWS Key Management Service 개발자 가이드*의 [키 생성](https://docs.aws.amazon.com//kms/latest/developerguide/create-keys.html)을 참조하십시오.
**중요**  
버킷과 동일한 AWS 리전에서 사용할 수 있는 KMS 키만 사용 가능합니다. Amazon S3 콘솔은 버킷과 동일한 리전에 있는 처음 100개의 KMS 키만 나열합니다. 목록에 없는 KMS 키를 사용하려면 KMS 키 ARN을 입력해야 합니다. 다른 계정에서 소유한 KMS 키를 사용하려면 먼저 해당 키에 대한 사용 권한이 있어야 하고, 다음 단계로 KMS 키 ARN을 입력해야 합니다.  
Amazon S3는 대칭 암호화 KMS 키만 지원하며 비대칭 KMS 키는 지원하지 않습니다. 자세한 내용은 **AWS Key Management Service 개발자 안내서에서 [대칭 및 비대칭 KMS 키 식별](https://docs.aws.amazon.com//kms/latest/developerguide/find-symm-asymm.html)을 참조하세요.

1. 추가 체크섬을 사용하려면 **켜기(On)**를 선택합니다. 그런 다음 **체크섬 함수(Checksum function)**에서 사용할 함수를 선택합니다. Amazon S3는 전체 객체를 수신한 후 체크섬 값을 계산하고 저장합니다. **미리 계산된 값(Precalculated value)** 상자를 사용하여 미리 계산된 값을 제공할 수 있습니다. 이렇게 하면 Amazon S3가 제공한 값과 계산한 값을 비교합니다. 두 값이 일치하지 않으면 Amazon S3가 오류를 생성합니다.

   추가 체크섬을 사용하면 데이터를 확인하는 데 사용할 체크섬 알고리즘을 지정할 수 있습니다. 추가 체크섬에 대한 자세한 내용은 [Amazon S3에서 객체 무결성 확인](checking-object-integrity.md) 단원을 참조하십시오.

1. 업로드 중인 모든 객체에 태그를 추가하려면 **태그 추가**를 선택합니다. **키** 필드에 태그 이름을 입력합니다. 태그 값을 입력합니다.

   객체 태그 지정을 통해 스토리지를 분류할 수 있습니다. 각 태그는 키-값 페어입니다. 키와 태그 값은 대/소문자를 구분합니다. 객체마다 태그를 10개까지 포함할 수 있습니다. 태그 키는 최대 128개 길이의 유니코드 문자이며, 태그 값은 최대 255개의 유니코드 문자입니다. 객체 태그에 대한 자세한 내용은 [태그를 사용하여 객체 분류](object-tagging.md) 섹션을 참조하세요.

1. 메타데이터를 추가하려면 **메타데이터 추가**를 선택합니다.

   1. **유형**에서 **시스템 정의** 또는 **사용자 정의**를 선택합니다.

      시스템 정의 메타데이터의 경우, **콘텐츠 유형** 및 **콘텐츠 처리** 같은 일반적인 HTTP 헤더를 선택할 수 있습니다. 시스템 정의 메타데이터 목록과 값 추가 가능 여부를 확인하려면 [시스템 정의 객체 메타데이터](UsingMetadata.md#SysMetadata) 단원을 참조하십시오. 접두사 `x-amz-meta-`로 시작하는 모든 메타데이터는 사용자 정의 메타데이터로 처리됩니다. 사용자 정의 메타데이터는 객체와 함께 저장되었다가 해당 객체를 다운로드할 때 반환됩니다. 키와 값 모두 US-ASCII 표준에 부합해야 합니다. 사용자 정의 메타데이터의 최대 크기는 2KB입니다. 시스템 정의 메타데이터와 사용자 정의 메타데이터에 대한 자세한 내용은 [객체 메타데이터 작업](UsingMetadata.md) 단원을 참조하십시오.

   1. **키**에 대해 키를 선택합니다.

   1. 키 값을 입력합니다.

1. 객체를 업로드하려면 **업로드**를 선택합니다.

   Amazon S3가 객체를 업로드합니다. 업로드가 완료되면 **업로드: 상태** 페이지에서 성공 메시지를 볼 수 있습니다.

1. **종료**를 선택합니다.

### AWS CLI 사용
<a name="UploadObjSingleOpCLI"></a>

`PUT` 요청을 보내 한 번의 작업으로 최대 5GB의 객체를 업로드할 수 있습니다. 자세한 내용은 *AWS CLI 명령 참조*의 [https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html#examples](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html#examples) 예시를 참조하십시오.

### REST API 사용
<a name="UploadObjSingleOpREST"></a>

객체를 업로드하기 위해 REST 요청을 보낼 수 있습니다. `PUT` 요청을 전송하여 단일 작업에서 데이터를 업로드할 수 있습니다. 자세한 내용은 [PUT Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html) 섹션을 참조하세요.

### AWS SDK 사용
<a name="UploadInSingleOp"></a>

AWS SDK를 사용하여 객체를 업로드하는 방법에 대한 예제는 *Amazon Simple Storage Service API 참조*의 [코드 예제](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_PutObject_section.html)를 참조하세요.

다양한 AWS SDK 사용에 대한 일반적인 정보는 *Amazon Simple Storage Service API 참조*의 [AWS SDK를 사용하여 Amazon S3로 개발하기](https://docs.aws.amazon.com/AmazonS3/latest/API/sdk-general-information-section.html)를 참조하세요.

## 동일한 키 이름을 가진 객체 업로드 방지
<a name="upload-objects-with-same-key-name"></a>

업로드 시 조건부 쓰기 작업을 사용하여 객체를 생성하기 전에 버킷에 객체가 있는지 확인할 수 있습니다. 이렇게 하면 기존 데이터의 덮어쓰기를 방지할 수 있습니다. 조건부 쓰기는 업로드하는 동안 버킷에 이미 같은 키 이름을 가진 기존 객체가 없는지 확인합니다.

[https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) 또는 [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) 요청에 조건부 쓰기를 사용할 수 있습니다.

조건부 요청에 대한 자세한 내용은 [조건부 요청을 통해 S3 작업에 사전 조건 추가](conditional-requests.md) 섹션을 참조하세요.

# Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사
<a name="mpuoverview"></a>

멀티파트 업로드를 사용하면 단일 객체를 여러 파트의 집합으로 Amazon S3에 업로드할 수 있습니다. 각 부분은 객체 데이터의 연속적인 부분입니다. 이러한 객체 파트는 독립적으로 그리고 임의의 순서로 업로드할 수 있습니다. 업로드의 경우 업데이트된 AWS 클라이언트는 객체의 체크섬을 자동으로 계산하여 요청의 일부로 객체 크기와 함께 Amazon S3로 전송합니다. 부분의 전송이 실패할 경우 다른 부분에 영향을 주지 않고도 해당 부분을 재전송할 수 있습니다. 객체의 모든 파트가 업로드되면 Amazon S3가 이 파트를 수집하여 객체를 생성합니다. 100MB 이상의 객체인 경우 단일 작업으로 업로드하는 대신 멀티파트 업로드를 사용하는 것이 좋습니다.

멀티파트 업로드 사용은 다음 이점을 제공합니다.
+ **개선된 처리량 개선** - 부분을 병렬적으로 업로드하여 처리량을 개선할 수 있습니다.
+ **네트워크 문제로부터 빠른 복구** - 더 작아진 부분 크기는 네트워크 오류로 인해 실패한 업로드 재시작의 영향을 최소화합니다.
+ **객체 업로드 일시 중지 및 재개** – 객체 부분을 장시간에 걸쳐 업로드할 수 있습니다. 일단 멀티파트 업로드가 시작되면 제한 시간이 없습니다. 멀티파트 업로드를 명시적으로 완료하거나 중단해야 합니다.
+ **최종 객체 크기를 알기 전에 업로드를 시작** – 객체를 생성하면서 업로드할 수 있습니다.

다음 방법으로 멀티파트 업로드를 사용하는 것이 좋습니다.
+ 안정적인 높은 대역폭 네트워크를 통해 큰 객체를 업로드하는 경우, 멀티파트 업로드를 사용하여 멀티스레드 성능을 위해 여러 객체 파트를 동시에 업로드함으로써 대역폭 사용을 극대화합니다.
+ 불규칙한 네트워크를 통해 업로드하는 경우, 멀티파트 업로드를 사용하여 업로드가 다시 시작되는 것을 방지하여 네트워크 오류에 대한 복원력을 높입니다. 멀티파트 업로드를 사용하는 경우, 업로드 중에 중단된 파트만 다시 업로드를 시도하면 됩니다. 객체 업로드를 처음부터 다시 시작하지 않아도 됩니다.

**참고**  
Amazon S3 Express One Zone 스토리지 클래스를 디렉터리 버킷과 함께 사용하는 방법에 대한 자세한 내용은 [S3 Express One Zone](directory-bucket-high-performance.md#s3-express-one-zone) 및 [디렉터리 버킷 작업](directory-buckets-overview.md) 섹션을 참조하세요. S3 Express One Zone 및 디렉터리 버킷에서 멀티파트 업로드를 사용하는 방법에 대한 자세한 내용은 [디렉터리 버킷에 멀티파트 업로드 사용](s3-express-using-multipart-upload.md) 섹션을 참조하세요.

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

멀티파트 업로드는 3단계 프로세스입니다. 업로드를 시작하고, 객체 파트를 업로드하고, 모두 업로드했으면 멀티파트 업로드를 완료합니다. 멀티파트 업로드 완료 요청이 전송되면 Amazon S3는 업로드된 각 파트를 모아 완전한 객체를 구성합니다. 버킷의 다른 객체와 마찬가지로 이 객체에 액세스할 수 있습니다.

진행 중인 모든 멀티파트 업로드 작업의 목록 또는 특정 멀티파트 업로드에 대해 업로드한 부분의 목록을 확인할 수 있습니다. 다음 섹션에서 이러한 각 작업에 대해 자세히 설명합니다.

**멀티파트 업로드 시작**  
멀티파트 업로드 시작 요청을 보낼 때는 체크섬 유형을 지정해야 합니다. 그런 다음 Amazon S3는 멀티파트 업로드의 고유 식별자인 업로드 ID가 포함된 응답을 반환합니다. 파트를 업로드하거나 파트를 나열하거나 업로드를 완료하거나 업로드를 중지할 때 이 업로드 ID가 필요합니다. 업로드되는 객체를 설명하는 메타데이터를 제공하려는 경우 멀티파트 업로드 시작 요청에서 제공해야 합니다. 익명 사용자는 멀티파트 업로드를 시작할 수 없습니다.

**부분 업로드**  
파트를 업로드할 때 업로드 ID와 함께 파트 번호를 지정해야 합니다. 1부터 10,000까지 부분 번호를 지정할 수 있습니다. 부분 번호를 사용하여 업로드하는 객체에서 각 부분과 그 위치를 고유하게 식별합니다. 부분 번호는 굳이 연속 시퀀스로 선택할 필요가 없습니다(예를 들면 1, 5 및 14를 선택해도 됩니다). 이전에 업로드한 파트와 동일한 파트 번호로 새 파트를 업로드할 경우 이전에 업로드한 파트를 덮어쓰게 된다는 것을 유의하세요.

파트를 업로드하면 Amazon S3는 각 파트의 체크섬 값과 함께 체크섬 알고리즘 유형을 응답의 헤더로 반환합니다. 각 부분 업로드에 대해 부분 번호와 ETag 값을 기록해야 합니다. 이후 멀티파트 업로드를 완료하기 위한 요청에 이러한 값을 포함해야 하기 때문입니다. 업로드 시 각 부분에는 고유한 ETag가 있습니다. 하지만 멀티파트 업로드가 완료되고 모든 파트가 통합되면 모든 파트는 체크섬의 체크섬으로 하나의 ETag에 속하게 됩니다.

**중요**  
멀티파트 업로드를 시작하여 하나 이상의 파트를 업로드한 후에는 멀티파트 업로드를 완료하거나 중지해야 업로드된 파트의 스토리지 비용이 청구되지 않습니다. 멀티파트 업로드를 완료 또는 중단한 *후*에만 Amazon S3가 파트 스토리지를 비우고 파트 스토리지에 대한 비용 청구를 중지합니다.  
멀티파트 업로드를 중지한 후에는 해당 업로드 ID로 다시 파트를 업로드할 수 없습니다. 파트 업로드가 진행 중일 때 멀티파트 업로드를 중지하더라도 진행 중인 파트 업로드는 성공하거나 실패할 수 있습니다. 따라서 각 파트에서 사용하고 있는 스토리지를 모두 비우려면 모든 파트 업로드가 완료된 후에 멀티파트 업로드를 중지해야 합니다.

**멀티파트 업로드 완료**  
멀티파트 업로드를 완료하면 Amazon S3는 부분 번호를 바탕으로 오름차순으로 각 부분을 결합하여 객체를 완성합니다. *멀티파트 업로드 시작* 요청에서 객체 메타데이터가 제공된 경우 Amazon S3는 객체에 해당 메타데이터를 연결합니다. 성공적으로 *완료* 요청이 수행되면 부분은 더 이상 존재하지 않습니다.

*멀티파트 업로드 완료* 요청에는 업로드 ID와 각 파트 번호 및 해당 ETag 값의 목록이 포함되어야 합니다. Amazon S3 응답에는 결합된 객체 데이터를 고유하게 식별하는 ETag가 포함됩니다. 이 ETag가 반드시 객체 데이터의 MD5 해시여야 하는 것은 아닙니다.

멀티파트 업로드 중에 전체 객체 체크섬을 제공하면 AWS SDK는 체크섬을 Amazon S3에 전달하고 S3는 서버 측의 객체 무결성을 검증하여 수신된 값과 비교합니다. 그런 다음 값이 일치하면 S3가 객체를 저장합니다. 두 값이 일치하지 않으면 Amazon S3에서 `BadDigest` 오류와 함께 요청이 실패합니다. 객체의 체크섬은 나중에 객체의 데이터 무결성을 검증하는 데 사용할 객체 메타데이터에도 저장됩니다.

**멀티파트 업로드 호출 샘플**  
 이 예시에서는 100GB 파일에 대해 멀티파트 업로드를 생성한다고 가정합니다. 이 경우 전체 프로세스를 위해 다음과 같은 API 호출이 이루어집니다. 총 1,002개의 API 직접 호출이 수행됩니다.
+ 프로세스를 시작하는 `[CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)` 호출.
+ 총 100GB 크기에 대해 각각 100MB인 파트를 업로드하는 1,000개의 개별 `[UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)` 직접 호출
+ 프로세스를 완료하기 위한 `[CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)` 직접 호출

**멀티파트 업로드 나열**  
특정 멀티파트 업로드 또는 진행 중인 모든 멀티파트 업로드에 대해 부분 목록을 확인할 수 있습니다. 파트 나열 작업은 특정 멀티파트 업로드에 대해 업로드한 파트의 정보를 반환합니다. 각 부분 목록 조회 요청에 대해 Amazon S3는 특정 멀티파트 업로드에서 최대 1,000개의 부분에 대해 부분 정보를 반환합니다. 멀티파트 업로드에서 1,000개 이상의 파트가 있을 경우 모든 파트를 검색하려면 파트 나열 요청을 여러 번 반복해야 합니다. 반환된 부분 목록에는 업로드가 완료되지 않은 부분이 포함되지 않습니다. *멀티파트 업로드 나열* 작업을 사용하여 진행 중인 멀티파트 업로드의 목록을 확인할 수 있습니다.

진행 중인 멀티파트 업로드는 시작했지만 아직 완료 또는 중단하지 않은 업로드입니다. 각 요청은 최대 1,000개의 멀티파트 업로드를 반환합니다. 진행 중인 멀티파트 업로드가 1,000개 이상일 경우 남은 멀티파트 업로드를 모두 검색하려면 추가 요청을 전송해야 합니다. 반환된 목록은 확인을 위해서만 사용합니다.

**중요**  
*멀티파트 업로드 완료* 요청을 전송할 때 이 나열 결과를 사용하면 안 됩니다. 그 대신, 부분을 업로드할 때 지정한 부분 번호 및 Amazon S3가 반환한 해당 ETag 값의 목록을 보관해야 합니다.

## 멀티파트 업로드 작업을 사용한 체크섬
<a name="mpuchecksums"></a>

Amazon S3에 객체를 업로드할 때 Amazon S3에서 사용할 체크섬 알고리즘을 지정할 수 있습니다. 기본적으로 AWS SDK 및 S3 콘솔은 모든 객체 업로드에 알고리즘을 사용하며, 이를 재정의할 수 있습니다. 이전 SDK를 사용하고 업로드된 객체에 지정된 체크섬이 없는 경우 Amazon S3는 CRC-64/NVME(`CRC64NVME`) 체크섬 알고리즘을 자동으로 사용합니다. (효율적인 데이터 무결성 확인을 위한 권장 옵션이기도 합니다.) CRC-64/NVME를 사용할 때 Amazon S3는 멀티파트 또는 단일 파트 업로드가 완료된 후 전체 객체의 체크섬을 계산합니다. CRC-64/NVME 체크섬 알고리즘은 각 개별 파트에 대해 전체 객체의 직접 체크섬 또는 체크섬의 체크섬을 계산하는 데 사용됩니다.

멀티파트 업로드를 사용하여 객체를 S3에 업로드한 후 Amazon S3는 각 파트 또는 전체 객체에 대한 체크섬 값을 계산하고 값을 저장합니다. S3 API 또는 AWS SDK를 사용하여 다음과 같은 방법으로 체크섬 값을 검색할 수 있습니다.
+ 개별 파트의 경우 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) 또는 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)를 사용할 수 있습니다. 아직 진행 중인 멀티파트 업로드의 개별 파트에 대한 체크섬 값을 검색하려면 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)를 사용하면 됩니다.
+ 전체 객체에 대해 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)를 사용할 수 있습니다. 전체 객체 체크섬으로 멀티파트 업로드를 수행하려면 전체 객체 체크섬 유형을 지정하여 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload) 및 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload)를 사용합니다. 전체 객체의 체크섬 값을 검증하거나 멀티파트 업로드에서 사용 중인 체크섬 유형을 확인하려면 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)를 사용합니다.

**중요**  
**체크섬**과 함께 멀티파트 업로드를 사용하는 경우 멀티파트 업로드에서 각 파트 업로드에 대한 파트 번호는 연속 파트 번호를 사용해야 하고 1로 시작해야 합니다. **체크섬**을 사용할 때 연속되지 않는 파트 번호로 멀티파트 업로드 요청을 완료하려고 하면 Amazon S3가 `HTTP 500 Internal Server` 오류를 생성합니다.

 멀티파트 업로드 객체를 통한 체크섬 작업에 대한 자세한 내용은 [Amazon S3에서 객체 무결성 확인](checking-object-integrity.md) 섹션을 참조하세요.

추가 체크섬이 포함된 멀티파트 업로드를 사용하여 객체를 업로드하는 전체 절차는 [튜토리얼: 멀티파트 업로드를 통한 객체 업로드 및 데이터 무결성 확인](tutorial-s3-mpu-additional-checksums.md) 섹션을 참조하세요.

## 동시 멀티파트 업로드 작업
<a name="distributedmpupload"></a>

분산 개발 환경에서는 애플리케이션에서 한 객체에 대해 동시에 여러 업데이트를 시작할 수 있습니다. 애플리케이션은 동일한 객체 키를 사용하여 여러 멀티파트 업로드를 시작할 수 있습니다. 이러한 각 업로드에 대해 애플리케이션은 부분을 업로드한 후 Amazon S3가 객체를 생성하도록 업로드 완료 요청을 전송할 수 있습니다. 버킷에서 S3 버전 관리를 사용할 경우 멀티파트 업로드를 완료하면 항상 새 버전이 생성됩니다. 버전 관리가 활성화된 버킷에서 동일한 객체 키를 사용하는 멀티파트 업로드를 여러 개 시작하는 경우, 가장 최근에 시작된 업로드(`createdDate`)에 따라 객체의 현재 버전이 결정됩니다.

예를 들어 오전 10시에 객체에 대한 `CreateMultipartUpload` 요청을 시작합니다. 그런 다음 오전 11시에 같은 객체에 대한 두 번째 `CreateMultipartUpload` 요청을 제출합니다. 두 번째 요청이 가장 최근에 제출되었으므로 첫 번째 업로드가 두 번째 업로드 후에 완료되더라도 오전 11시 요청에 의해 업로드된 객체가 현재 버전이 됩니다. 버전 관리가 활성화되지 않은 버킷의 경우 멀티파트 업로드의 시작과 완료 사이에 전송된 다른 요청을 우선 수행할 수 있습니다.

동시 멀티파트 업로드 요청이 우선할 수 있는 또 다른 예는 키를 사용하여 멀티파트 업로드를 시작한 후 다른 작업이 해당 키를 삭제하는 경우입니다. 작업을 완료하기 전에 전체 멀티파트 업로드 응답은 객체를 보지 못한 상태에서도 객체를 성공적으로 생성했다고 나타낼 수 있습니다.

## 멀티파트 업로드 중에 키 이름이 동일한 객체 업로드 방지
<a name="multipart-upload-objects-with-same-key-name"></a>

업로드 시 조건부 쓰기 작업을 사용하여 객체를 생성하기 전에 버킷에 객체가 있는지 확인할 수 있습니다. 이렇게 하면 기존 데이터의 덮어쓰기를 방지할 수 있습니다. 조건부 쓰기는 업로드하는 동안 버킷에 이미 같은 키 이름을 가진 기존 객체가 없는지 확인합니다.

[https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) 또는 [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) 요청에 조건부 쓰기를 사용할 수 있습니다.

조건부 요청에 대한 자세한 내용은 [조건부 요청을 통해 S3 작업에 사전 조건 추가](conditional-requests.md) 섹션을 참조하세요.

## 멀티파트 업로드 및 요금
<a name="mpuploadpricing"></a>

멀티파트 업로드가 시작되면 Amazon S3는 업로드가 완료되거나 중단될 때까지 모든 부분을 계속 유지합니다. 수명 주기가 끝날 때까지 이 멀티파트 업로드와 관련 부분의 모든 스토리지, 대역폭 및 요청에 대해 비용이 청구됩니다.

이러한 파트는 파트를 업로드할 때 지정한 스토리지 클래스에 따라 요금이 부과됩니다. 그러나 이러한 파트가 S3 Glacier Flexible Retrieval 또는 S3 Glacier Deep Archive에 업로드된 경우 해당 파트에 대한 요금이 부과되지 않습니다. S3 Glacier Flexier Flexible Retrieval 스토리지 클래스로의 PUT 요청에 멀티파트 파트가 진행 중인 경우, 업로드가 완료될 때까지 S3 Glacier Flexible Retrieval 스테이징 스토리지에 대해 S3 Standard 스토리지 요금이 부과됩니다. 또한 `CreateMultipartUpload` 및 `UploadPart` 모두 S3 Standard 요금이 부과됩니다. `CompleteMultipartUpload` 요청만 S3 Glacier Flexible Retrieval 요금이 부과됩니다. 마찬가지로, S3 Glacier Deep Archive 스토리지 클래스로의 PUT에 대한 진행 중인 멀티파트 파트는 업로드가 완료될 때까지 S3 Glacier Flexible Retrieval 스테이징 스토리지에 대해 S3 Standard 스토리지 요금이 부과되며, `CompleteMultipartUpload` 요청만 S3 Glacier Deep Archive 요금이 부과됩니다.

멀티파트 업로드를 중단하면 Amazon S3가 아티팩트 업로드 및 업로드된 모든 파트를 삭제합니다. 이러한 아티팩트에 대해서는 요금이 부과되지 않습니다. 지정한 스토리지 클래스에 관계없이 불완전한 멀티파트 업로드를 삭제하는 경우 조기 삭제 요금이 부과되지 않습니다. 요금에 대한 자세한 내용은 [Amazon S3 요금](https://aws.amazon.com/s3/pricing/)을 참조하십시오.

**참고**  
스토리지 비용을 최소화하려면 `AbortIncompleteMultipartUpload` 작업을 사용하여 특정 기간이 지나면 불완전한 멀티파트 업로드를 삭제하는 수명 주기 규칙을 구성하는 것이 좋습니다. 불완전한 멀티파트 업로드를 삭제하기 위한 수명 주기 규칙을 만드는 방법과 관련하여 자세한 내용은 [불완전한 멀티파트 업로드를 삭제하도록 버킷 수명 주기 구성 설정](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpu-abort-incomplete-mpu-lifecycle-config.html)을 참조하십시오.

## 멀티파트 업로드를 위한 API 지원
<a name="apisupportformpu"></a>

*Amazon Simple Storage Service API 참조*의 다음 섹션에서는 멀티파트 업로드를 위한 REST API에 대해 설명합니다.

AWS Lambda 함수를 사용하는 멀티파트 업로드 방법에 대한 자세한 내용은 [Uploading large objects to Amazon S3 using multipart upload and transfer acceleration](https://aws.amazon.com/blogs/compute/uploading-large-objects-to-amazon-s3-using-multipart-upload-and-transfer-acceleration/)을 참조하세요.
+ [멀티파트 업로드 생성](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)
+ [부분 업로드](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)
+ [부분 업로드(복사)](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html)
+ [멀티파트 업로드 완료](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)
+ [멀티파트 업로드 중단](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html)
+ [부분 목록 조회](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)
+ [멀티파트 업로드 목록 조회](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html)

## AWS Command Line Interface멀티파트 업로드를 위한 지원
<a name="clisupportformpu"></a>

AWS Command Line Interface의 다음 주제에서는 멀티파트 업로드를 위한 작업을 설명합니다.
+ [멀티파트 업로드 시작](https://docs.aws.amazon.com/cli/latest/reference/s3api/create-multipart-upload.html)
+ [부분 업로드](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html)
+ [부분 업로드(복사)](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html)
+ [멀티파트 업로드 완료](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html)
+ [멀티파트 업로드 중단](https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html)
+ [부분 목록 조회](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html)
+ [멀티파트 업로드 목록 조회](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-multipart-uploads.html)

## AWS멀티파트 업로드에 대한 SDK 지원
<a name="sdksupportformpu"></a>



AWS SDK를 사용하여 객체를 여러 부분으로 나누어 업로드할 수 있습니다. API 작업에서 지원하는 AWS SDK 목록은 다음을 참조하십시오.
+ [멀티파트 업로드 생성](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)
+ [부분 업로드](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)
+ [부분 업로드(복사)](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html)
+ [멀티파트 업로드 완료](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)
+ [멀티파트 업로드 중단](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html)
+ [부분 목록 조회](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)
+ [멀티파트 업로드 목록 조회](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html)

## 멀티파트 업로드 API 및 권한
<a name="mpuAndPermissions"></a>

멀티파트 업로드 작업을 수행하려면 필수 권한이 있어야 합니다. ACL(액세스 제어 목록), 버킷 정책 또는 사용자 정책을 사용하여 각 사용자에게 이 작업을 수행할 권한을 부여할 수 있습니다. 다음 표에는 ACL, 버킷 정책 또는 사용자 정책을 사용할 때 여러 멀티파트 업로드 작업에 대한 필수 권한이 나와 있습니다.


| 작업 | 필수 권한 | 
| --- | --- | 
|  멀티파트 업로드 생성  |  멀티파트 업로드를 생성하려면 객체에 대해 `s3:PutObject` 작업을 수행할 수 있어야 합니다. 버킷 소유자는 다른 주체가 `s3:PutObject` 작업을 수행하도록 허가할 수 있습니다.  | 
|  멀티파트 업로드 시작  |  멀티파트 업로드를 시작하려면 객체에 대해 `s3:PutObject` 작업을 수행할 수 있어야 합니다. 버킷 소유자는 다른 주체가 `s3:PutObject` 작업을 수행하도록 허가할 수 있습니다.  | 
| 시작한 사용자 | 멀티파트 업로드를 시작한 사용자를 식별하는 컨테이너 요소입니다. 시작한 사용자가 AWS 계정일 경우 이 요소는 소유자 요소와 동일한 정보를 제공합니다. 시작한 사용자가 IAM 사용자일 경우 이 요소는 사용자 ARN 및 표시 이름을 제공합니다. | 
| 파트 업로드 | 부분을 업로드하려면 객체에 대해 `s3:PutObject` 작업을 수행할 수 있어야 합니다. 버킷 소유자는 멀티파트 작업을 시작한 사용자가 객체의 부분을 업로드할 수 있도록 객체에 대해 `s3:PutObject` 작업을 수행할 수 있는 권한을 부여해야 합니다. | 
| 파트 업로드(복사) | 부분을 업로드하려면 객체에 대해 `s3:PutObject` 작업을 수행할 수 있어야 합니다. 기존 객체의 부분을 업로드하므로 원본 객체에 대해 `s3:GetObject` 작업을 수행할 수 있어야 합니다. 버킷 소유자는 객체의 멀티파트 업로드를 시작하는 사용자에게 `s3:PutObject` 작업을 수행할 수 있는 권한을 부여해야 합니다. | 
| 멀티파트 업로드 완료 | 멀티파트 업로드를 완료하려면 객체에 대해 `s3:PutObject` 작업을 수행할 수 있어야 합니다. 버킷 소유자는 멀티파트 작업을 시작한 사용자가 해당 객체의 멀티파트 업로드를 완료할 수 있도록 객체에 대해 `s3:PutObject` 작업을 수행할 수 있는 권한을 부여해야 합니다. | 
| 멀티파트 업로드 중지 | 멀티파트 업로드를 중단하려면 객체에 대해 `s3:AbortMultipartUpload` 작업을 수행할 수 있어야 합니다. 기본적으로 버킷 소유자와 멀티파트 업로드를 시작한 사용자는 이 작업을 IAM 및 S3 버킷 정책의 일환으로 수행하도록 허용됩니다. 시작한 사용자가 IAM 사용자인 경우 해당 사용자의 AWS 계정도 이 멀티파트 업로드를 중단할 수 있어야 합니다. VPC 엔드포인트 정책의 경우 멀티파트 업로드를 시작한 사용자는 `s3:AbortMultipartUpload` 작업을 수행할 권한을 자동으로 얻지 못합니다. 버킷 소유자는 이러한 기본 사용자 외 다른 주체가 객체에 대해 `s3:AbortMultipartUpload` 작업을 수행하도록 허가할 수 있습니다. 버킷 소유자는 다른 주체의 `s3:AbortMultipartUpload` 작업 수행을 거부할 수 있습니다. | 
| 파트 목록 조회 | `s3:ListMultipartUploadParts` 작업을 수행하여 멀티파트 업로드의 각 부분을 나열할 수 있어야 합니다. 기본적으로 버킷 소유자에게는 버킷에 대한 멀티파트 업로드의 부분을 나열할 권한이 부여됩니다. 멀티파트 업로드를 시작한 사용자는 특정 멀티파트 업로드의 부분을 나열할 권한이 있습니다. 멀티파트 업로드를 시작한 사용자가 IAM 사용자인 경우 이 IAM 사용자를 제어하는 AWS 계정도 해당 업로드의 부분을 나열할 권한이 있습니다.  버킷 소유자는 이러한 기본 사용자 외 다른 주체가 객체에 대해 `s3:ListMultipartUploadParts` 작업을 수행하도록 허가할 수 있습니다. 버킷 소유자는 또한 다른 주체의 `s3:ListMultipartUploadParts` 작업 수행을 거부할 수 있습니다. | 
| 멀티파트 업로드 목록 조회 | 버킷에 대해 `s3:ListBucketMultipartUploads` 작업을 수행하여 해당 버킷에 대해 진행 중인 멀티파트 업로드를 나열할 수 있어야 합니다. 버킷 소유자는 이러한 기본 사용자 외, 다른 주체가 버킷에 대해 `s3:ListBucketMultipartUploads` 작업을 수행하도록 허가할 수 있습니다. | 
| AWS KMS 암호화 및 암호 해독 관련 권한 |  AWS Key Management Service(AWS KMS) KMS 키를 통한 암호화를 사용해 멀티파트 업로드를 수행하려면 요청자에게 다음 권한이 있어야 합니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/mpuoverview.html)  이러한 권한이 필요한 이유는 Amazon S3이 멀티파트 업로드를 완료하기 전에 암호화된 파일 부분에서 데이터를 암호 해독하고 읽어야 하기 때문입니다. 객체의 체크섬 값을 얻으려면 `kms:Decrypt` 권한과 고객이 제공한 암호화 키를 사용한 서버 측 암호화도 필요합니다. [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) API를 사용할 때 이러한 필수 권한이 없는 경우 체크섬 값 없이 객체가 생성됩니다. IAM 사용자 또는 역할이 KMS 키와 동일한 AWS 계정에 있는 경우 키 및 IAM 정책 둘 다에 대한 권한이 있는지 확인하세요. IAM 사용자 또는 역할이 KMS 키와 다른 계정에 속한 경우, 키 정책과 IAM 사용자 또는 역할 모두에 대한 권한이 있어야 합니다.  | 
| SSE-C(고객 제공 암호화 키를 사용한 서버 측 암호화) | [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) API를 사용하는 경우 SSE-C(고객 제공 암호화 키를 사용한 서버 측 암호화)를 제공해야 합니다. 그렇지 않으면 체크섬 없이 객체가 생성되고 체크섬 값이 반환되지 않습니다.  | 

ACL 권한 및 액세스 정책의 권한 간 관계에 대한 자세한 내용은 [ACL 권한과 액세스 정책 권한의 매핑](acl-overview.md#acl-access-policy-permission-mapping) 섹션을 참조하세요. IAM 사용자, 역할 및 모범 사례에 대한 자세한 내용은 **IAM 사용 설명서의 [IAM 자격 증명(사용자, 사용자 그룹 및 역할)](https://docs.aws.amazon.com/IAM/latest/UserGuide/id.html)을 참조하십시오.

## 멀티파트 업로드 작업을 사용한 체크섬
<a name="Checksums-mpu-operations"></a>

실제 멀티파트 업로드를 수행하는 데 사용되는 세 가지 Amazon S3 API는 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html), [https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html), [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)입니다. 다음 표는 각 API에 제공해야 하는 체크섬 헤더 및 값을 나타냅니다.


| 체크섬 알고리즘 | 체크섬 유형 | `CreateMultipartUpload` | `UploadPart` | `CompleteMultipartUpoad` | 
| --- | --- | --- | --- | --- | 
| CRC-64/NVME(`CRC64NVME`) | 전체 객체 | 필수 헤더: `x-amz-checksum-algorithm` |  선택적 헤더: `x-amz-checksum-crc64nvme`  |  선택적 헤더: `x-amz-checksum-algorithm` `x-amz-crc64`  | 
| CRC-32(`CRC32`) CRC 32-C(`CRC32C`) | 전체 객체 |  필수 헤더: `x-amz-checksum-algorithm` `x-amz-checksum-type`  |  선택적 헤더: `x-amz-checksum-crc64nvme`  |  선택적 헤더: `x-amz-checksum-algorithm` `x-amz-crc32` `x-amz-crc32c`  | 
|  CRC-32(`CRC32`) CRC-32C(`CRC32C`) SHA-1(`SHA1`) SHA-256(`SHA256`) | 복합 |  필수 헤더: `x-amz-checksum-algorithm`  |  필수 헤더: `x-amz-checksum-crc32` `x-amz-checksum-crc32c` `x-amz-checksum-sha1` `x-amz-checksum-sha256`  |  필수 헤더: 모든 파트 수준 체크섬을 `CompleteMultiPartUpload` 요청에 포함해야 합니다. 선택적 헤더: `x-amz-crc32` `x-amz-crc32c` `x-amz-sha1` `x-amz-sha256`  | 

**Topics**
+ [멀티파트 업로드 프로세스](#mpu-process)
+ [멀티파트 업로드 작업을 사용한 체크섬](#mpuchecksums)
+ [동시 멀티파트 업로드 작업](#distributedmpupload)
+ [멀티파트 업로드 중에 키 이름이 동일한 객체 업로드 방지](#multipart-upload-objects-with-same-key-name)
+ [멀티파트 업로드 및 요금](#mpuploadpricing)
+ [멀티파트 업로드를 위한 API 지원](#apisupportformpu)
+ [AWS Command Line Interface멀티파트 업로드를 위한 지원](#clisupportformpu)
+ [AWS멀티파트 업로드에 대한 SDK 지원](#sdksupportformpu)
+ [멀티파트 업로드 API 및 권한](#mpuAndPermissions)
+ [멀티파트 업로드 작업을 사용한 체크섬](#Checksums-mpu-operations)
+ [불완전한 멀티파트 업로드를 삭제하도록 버킷 수명 주기 구성 설정](mpu-abort-incomplete-mpu-lifecycle-config.md)
+ [멀티파트 업로드를 사용한 객체 업로드](mpu-upload-object.md)
+ [상위 수준 .NET TransferUtility 클래스를 사용하여 디렉터리 업로드](HLuploadDirDotNet.md)
+ [멀티파트 업로드 나열](list-mpu.md)
+ [AWS SDK를 사용하여 멀티파트 업로드 추적](track-mpu.md)
+ [멀티파트 업로드 중단](abort-mpu.md)
+ [멀티파트 업로드를 사용한 객체 복사](CopyingObjectsMPUapi.md)
+ [튜토리얼: 멀티파트 업로드를 통한 객체 업로드 및 데이터 무결성 확인](tutorial-s3-mpu-additional-checksums.md)
+ [Amazon S3 멀티파트 업로드 제한](qfacts.md)

# 불완전한 멀티파트 업로드를 삭제하도록 버킷 수명 주기 구성 설정
<a name="mpu-abort-incomplete-mpu-lifecycle-config"></a>

모범 사례로, 저장 비용을 최소화하도록 `AbortIncompleteMultipartUpload` 작업을 사용하여 수명 주기 규칙을 구성할 것을 권장합니다. 멀티파트 업로드 중단에 대한 자세한 내용은 [멀티파트 업로드 중단](abort-mpu.md) 단원을 참조하십시오.

이제 Amazon S3는 시작된 후 지정 일수 내에 완료되지 않은 멀티파트 업로드를 중단하도록 Amazon S3에 지시하는 데 사용할 수 있는 버킷 수명 주기 규칙을 지원합니다. 지정된 기간 내에 멀티파트 업로드가 완료되지 않으면 중단 작업을 수행할 수 있습니다. 그러면 Amazon S3가 멀티파트 업로드를 중단하고 멀티파트 업로드와 관련된 모든 부분을 삭제합니다. 이 규칙은 기존 멀티파트 업로드와 나중에 생성하는 멀티파트 업로드 모두에 적용됩니다.

 다음은 `AbortIncompleteMultipartUpload` 작업으로 규칙을 지정하는 수명 주기 구성의 예시입니다.

```
<LifecycleConfiguration>
    <Rule>
        <ID>sample-rule</ID>
        <Prefix></Prefix>
        <Status>Enabled</Status>
        <AbortIncompleteMultipartUpload>
          <DaysAfterInitiation>7</DaysAfterInitiation>
        </AbortIncompleteMultipartUpload>
    </Rule>
</LifecycleConfiguration>
```

이 예제에서 규칙은 `Prefix` 요소의 값([객체 키 이름 접두사](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#keyprefix))을 지정하지 않습니다. 따라서 멀티파트 업로드를 시작한 버킷의 모든 객체에 규칙이 적용됩니다. 시작된 후 7일 이내에 완료되지 않은 멀티파트 업로드는 중단 작업을 수행할 수 있습니다. 중단 작업은 완료된 멀티파트 업로드에 영향을 주지 않습니다.

버킷 수명 주기 구성에 대한 자세한 내용은 [객체 수명 주기 관리](object-lifecycle-mgmt.md) 섹션을 참조하세요.

**참고**  
규칙에 지정된 일수 내에 멀티파트 업로드가 완료되면 `AbortIncompleteMultipartUpload` 수명 주기 작업은 적용되지 않습니다(즉, Amazon S3가 어떤 작업도 하지 않음). 또한 이 작업이 객체에도 적용되지 않습니다. 이 수명 주기 작업으로 객체가 삭제되지는 않습니다. 또한 불완전한 멀티파트 업로드 부분을 제거하더라도 S3 수명 주기에 대한 조기 삭제 요금이 발생하지 않습니다.

## S3 콘솔 사용
<a name="mpu-abort-incomplete-mpu-lifecycle-config-console"></a>

불완전한 멀티파트 업로드를 자동으로 관리하려면, 지정된 일수가 지난 후에 버킷에서 미완료 멀티파트 업로드 바이트를 만료시키는 수명 주기 규칙을 S3 콘솔을 사용하여 만들면 됩니다. 다음 절차는 7일 후 미완료 멀티파트 업로드를 삭제하기 위한 수명 주기 규칙을 추가하는 방법을 보여줍니다. 수명 주기 규칙에 대한 자세한 내용은 [버킷에서 S3 수명 주기 구성 설정](how-to-set-lifecycle-configuration-intro.md) 페이지를 참조하십시오.

**7일 이상 지난 미완료 멀티파트 업로드를 중단하기 위한 수명 주기 규칙을 추가하려면**

1. AWS Management Console에 로그인한 후 [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)에서 S3 콘솔을 엽니다.

1. **버킷(Buckets)** 목록에서 수명 주기 규칙을 생성할 버킷의 이름을 선택합니다.

1. **관리(Management)** 탭을 선택하고 **수명 주기 규칙 생성(Create lifecycle rule)**을 선택합니다.

1.  **수명 주기 규칙 이름(Lifecycle rule name)**에 규칙의 이름을 입력합니다.

   단, 버킷 내에서 고유한 이름을 갖도록 합니다.

1. 수명 주기 규칙의 범위를 선택합니다.
   + 특정 접두사가 있는 모든 객체에 수명 주기 규칙을 생성하려면 **Limit the scope of this rule using one or more filters**(하나 이상의 필터를 사용하여 이 규칙의 범위 제한)를 선택하고 **Prefix**(접두사) 필드에 접두사를 입력합니다.
   + 이 수명 주기 규칙을 버킷의 모든 객체에 적용하려면 **This rule applies to **all** objects in the bucket**(이 규칙이 버킷의 모든 객체에 적용됨)을 선택하고 **I acknowledge that this rule applies to all objects in the bucket**(이 규칙이 버킷의 모든 객체에 적용됨을 확인합니다)을 선택합니다.

1. **Lifecycle rule actions**(수명 주기 규칙 작업)에서 **Delete expired object delete markers or incomplete multipart uploads**(만료된 객체 삭제 마커 또는 미완료 멀티파트 업로드 삭제)를 선택합니다.

1. **Delete expired object delete markers or incomplete multipart uploads**(만료된 객체 삭제 마커 또는 미완료 멀티파트 업로드 삭제)에서 **Delete incomplete multipart uploads**(미완료 멀티파트 업로드 삭제)를 선택합니다.

1. **Number of days**(일수) 필드에, 미완료 멀티파트 업로드를 삭제하기까지의 경과 일수(이 예에서는 7일)를 입력합니다.

1. **규칙 생성**을 선택합니다.

## AWS CLI 사용
<a name="mpu-abort-incomplete-mpu-lifecycle-config-cli"></a>

다음`put-bucket-lifecycle-configuration` AWS Command Line Interface(AWS CLI) 명령은 지정된 버킷에 수명 주기 구성을 추가합니다. 이 명령을 사용하려면 `user input placeholders`를 자체 정보로 대체합니다.

```
aws s3api put-bucket-lifecycle-configuration  \
        --bucket amzn-s3-demo-bucket  \
        --lifecycle-configuration filename-containing-lifecycle-configuration
```

다음 예제는 AWS CLI를 사용하여 미완료 멀티파트 업로드를 중단하는 수명 주기 규칙을 추가하는 방법을 보여줍니다. 여기에는 7일 이상 경과된 미완료 멀티파트 업로드를 중단하기 위한 JSON 수명 주기 구성 예제가 포함되어 있습니다.

이 예제에서 CLI 명령을 사용하려면 `user input placeholders`를 자체 정보로 대체합니다.

**미완료 멀티파트 업로드를 중단하기 위한 수명 주기 규칙을 추가하려면**

1. AWS CLI를 설정합니다. 자세한 내용은 **Amazon S3 API 참조의 [AWS CLI를 사용하여 Amazon S3에서 개발](https://docs.aws.amazon.com/AmazonS3/latest/API/setup-aws-cli.html)을 참조하세요.

1. 다음 수명 주기 구성 예제를 파일(예: *`lifecycle.json`*``)에 저장합니다. 이 예제 구성에서는 빈 접두사가 지정되어 있으므로, 버킷에 있는 모든 객체에 적용됩니다. 구성을 객체의 하위 집합에만 제한적으로 적용하려면 접두사를 지정하면 됩니다.

   ```
   {
       "Rules": [
           {
               "ID": "Test Rule",
               "Status": "Enabled",
               "Filter": {
                   "Prefix": ""
               },
               "AbortIncompleteMultipartUpload": {
                   "DaysAfterInitiation": 7
               }
           }
       ]
   }
   ```

1.  다음 CLI 명령을 사용하여 버킷에서 이 수명 주기 구성을 설정합니다.

   ```
   aws s3api put-bucket-lifecycle-configuration   \
   --bucket amzn-s3-demo-bucket  \
   --lifecycle-configuration file://lifecycle.json
   ```

1.  버킷에 수명 주기 구성이 설정되었는지 확인하려면 다음 `get-bucket-lifecycle` 명령을 사용하여 수명 주기 구성을 검색합니다.

   ```
   aws s3api get-bucket-lifecycle  \
   --bucket amzn-s3-demo-bucket
   ```

1.  수명 주기 구성을 삭제하려면 다음 `delete-bucket-lifecycle` 명령을 사용합니다.

   ```
   aws s3api delete-bucket-lifecycle \
   --bucket amzn-s3-demo-bucket
   ```

# 멀티파트 업로드를 사용한 객체 업로드
<a name="mpu-upload-object"></a>

멀티파트 업로드를 사용하여 프로그래밍 방식으로 단일 객체를 Amazon S3에 업로드할 수 있습니다. 각 객체는 여러 파트의 집합으로 업로드됩니다. 각 부분은 객체 데이터의 연속적인 부분입니다. 이러한 객체 부분은 독립적으로 그리고 임의의 순서로 업로드할 수 있습니다. 부분의 전송이 실패할 경우 다른 부분에 영향을 주지 않고도 해당 부분을 재전송할 수 있습니다. 객체의 모든 부분이 업로드되면 Amazon S3가 이들 부분을 수집하여 객체를 생성합니다. 익명 사용자는 멀티파트 업로드를 시작할 수 없습니다.

추가 체크섬이 포함된 멀티파트 업로드를 사용하여 객체를 업로드하는 전체 절차는 [튜토리얼: 멀티파트 업로드를 통한 객체 업로드 및 데이터 무결성 확인](tutorial-s3-mpu-additional-checksums.md) 섹션을 참조하세요.

다음 섹션에서는 AWS Command Line Interface 및 AWS SDK와 함께 멀티파트 업로드를 사용하는 방법을 보여줍니다.

## S3 콘솔 사용
<a name="MultipartUploadConsole"></a>

이미지, 백업, 데이터, 동영상 등 모든 유형의 파일을 S3 버킷에 업로드할 수 있습니다. Amazon S3 콘솔을 사용하여 업로드할 수 있는 파일의 최대 크기는 160GB입니다. 160GB가 넘는 파일을 업로드하려면 AWS Command Line Interface(AWS CLI), AWS SDK 또는 Amazon S3 REST API를 사용하십시오.

AWS Management Console을 통한 객체 업로드 지침은 [객체 업로드](upload-objects.md) 섹션을 참조하세요.

## AWS CLI 사용
<a name="UsingCLImpUpload"></a>

다음은 AWS CLI를 사용하여 멀티파트 업로드를 위한 Amazon S3 작업을 설명합니다.
+ [멀티파트 업로드 시작](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/create-multipart-upload.html)
+ [부분 업로드](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html)
+ [부분 업로드(복사)](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html)
+ [멀티파트 업로드 완료](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html)
+ [멀티파트 업로드 중단](https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html)
+ [부분 목록 조회](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html)
+ [멀티파트 업로드 목록 조회](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-multipart-uploads.html)

## REST API 사용
<a name="UsingRESTAPImpUpload"></a>

*Amazon Simple Storage Service API 참조*의 다음 섹션에서는 멀티파트 업로드를 위한 REST API에 대해 설명합니다.
+ [멀티파트 업로드 시작](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html)
+ [부분 업로드](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html)
+ [멀티파트 업로드 완료](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadComplete.html)
+ [멀티파트 업로드 중지](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadAbort.html)
+ [부분 목록 조회](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadListParts.html)
+ [멀티파트 업로드 목록 조회](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadListMPUpload.html)

## AWS SDK 사용(상위 수준 API)
<a name="multipart-upload-high-level"></a>

일부 AWS SDK는 멀티파트 업로드를 완료하는 데 필요한 다양한 API 작업을 단일 작업으로 결합하여 멀티파트 업로드를 간소화하는 상위 수준 API를 제공합니다. 자세한 내용은 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하세요.

멀티파트 업로드를 일시 중지했다 다시 시작해야 하거나 업로드 중에 파트의 크기를 변경해야 하거나 혹은 데이터 크기를 미리 확인하지 않은 경우 하위 수준 API를 사용합니다. 멀티파트 업로드를 위한 하위 수준 API 메서드에서 제공하는 추가 기능에 대한 자세한 내용은 [AWS SDK 사용(하위 수준 API)](#mpu-upload-low-level) 섹션을 참조하세요.

------
#### [ Java ]

AWS SDK for Java를 사용하여 멀티파트 업로드를 수행하는 방법의 예는 *Amazon S3 API 참조*의 [Upload or download large files to and from Amazon S3 using an AWS SDK](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_Scenario_UsingLargeFiles_section.html)를 참조하세요.

------
#### [ .NET ]

S3 버킷에 파일을 업로드하려면 `TransferUtility` 클래스를 사용합니다. 파일에서 데이터를 업로드할 경우에는 객체의 키 이름을 제공해야 합니다. 제공하지 않으면 API에서는 키 이름에 해당하는 파일 이름을 사용합니다. 스트림에서 데이터를 업로드할 경우에는 객체의 키 이름을 제공해야 합니다.

고급 업로드 옵션(예: 부분 크기, 부분을 동시에 업로드할 때 스레드 수, 메타데이터, 스토리지 클래스 또는 ACL)을 설정하려면 `TransferUtilityUploadRequest` 클래스를 사용합니다.

**참고**  
데이터 소스로 스트림을 사용하는 경우, `TransferUtility` 클래스는 동시 업로드를 수행하지 않습니다.

다음 C\$1 예제는 파일을 여러 파트로 나누어 Amazon S3 버킷에 업로드합니다. 다양한 `TransferUtility.Upload` 오버로드를 사용하여 파일을 업로드하는 방법을 보여줍니다. 업로드에 대해 연속적으로 수행되는 각 호출이 이전 업로드를 대체합니다. 코드 예제 설정 및 실행에 대한 자세한 내용은 *AWS SDK for .NET 개발자 안내서*의 [AWS SDK for .NET 시작하기](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)를 참조하세요.

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using System;
using System.IO;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class UploadFileMPUHighLevelAPITest
    {
        private const string bucketName = "*** provide bucket name ***";
        private const string keyName = "*** provide a name for the uploaded object ***";
        private const string filePath = "*** provide the full path name of the file to upload ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;

        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            UploadFileAsync().Wait();
        }

        private static async Task UploadFileAsync()
        {
            try
            {
                var fileTransferUtility =
                    new TransferUtility(s3Client);

                // Option 1. Upload a file. The file name is used as the object key name.
                await fileTransferUtility.UploadAsync(filePath, bucketName);
                Console.WriteLine("Upload 1 completed");

                // Option 2. Specify object key name explicitly.
                await fileTransferUtility.UploadAsync(filePath, bucketName, keyName);
                Console.WriteLine("Upload 2 completed");

                // Option 3. Upload data from a type of System.IO.Stream.
                using (var fileToUpload = 
                    new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    await fileTransferUtility.UploadAsync(fileToUpload,
                                               bucketName, keyName);
                }
                Console.WriteLine("Upload 3 completed");

                // Option 4. Specify advanced settings.
                var fileTransferUtilityRequest = new TransferUtilityUploadRequest
                {
                    BucketName = bucketName,
                    FilePath = filePath,
                    StorageClass = S3StorageClass.StandardInfrequentAccess,
                    PartSize = 6291456, // 6 MB.
                    Key = keyName,
                    CannedACL = S3CannedACL.PublicRead
                };
                fileTransferUtilityRequest.Metadata.Add("param1", "Value1");
                fileTransferUtilityRequest.Metadata.Add("param2", "Value2");

                await fileTransferUtility.UploadAsync(fileTransferUtilityRequest);
                Console.WriteLine("Upload 4 completed");
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }

        }
    }
}
```

------
#### [ JavaScript ]

**Example**  
대용량 파일을 업로드합니다.  

```
import { S3Client } from "@aws-sdk/client-s3";
import { Upload } from "@aws-sdk/lib-storage";

import {
  ProgressBar,
  logger,
} from "@aws-doc-sdk-examples/lib/utils/util-log.js";

const twentyFiveMB = 25 * 1024 * 1024;

export const createString = (size = twentyFiveMB) => {
  return "x".repeat(size);
};

/**
 * Create a 25MB file and upload it in parts to the specified
 * Amazon S3 bucket.
 * @param {{ bucketName: string, key: string }}
 */
export const main = async ({ bucketName, key }) => {
  const str = createString();
  const buffer = Buffer.from(str, "utf8");
  const progressBar = new ProgressBar({
    description: `Uploading "${key}" to "${bucketName}"`,
    barLength: 30,
  });

  try {
    const upload = new Upload({
      client: new S3Client({}),
      params: {
        Bucket: bucketName,
        Key: key,
        Body: buffer,
      },
    });

    upload.on("httpUploadProgress", ({ loaded, total }) => {
      progressBar.update({ current: loaded, total });
    });

    await upload.done();
  } catch (caught) {
    if (caught instanceof Error && caught.name === "AbortError") {
      logger.error(`Multipart upload was aborted. ${caught.message}`);
    } else {
      throw caught;
    }
  }
};
```

**Example**  
대용량 파일을 다운로드합니다.  

```
import { fileURLToPath } from "node:url";
import { GetObjectCommand, NoSuchKey, S3Client } from "@aws-sdk/client-s3";
import { createWriteStream, rmSync } from "node:fs";

const s3Client = new S3Client({});
const oneMB = 1024 * 1024;

export const getObjectRange = ({ bucket, key, start, end }) => {
  const command = new GetObjectCommand({
    Bucket: bucket,
    Key: key,
    Range: `bytes=${start}-${end}`,
  });

  return s3Client.send(command);
};

/**
 * @param {string | undefined} contentRange
 */
export const getRangeAndLength = (contentRange) => {
  const [range, length] = contentRange.split("/");
  const [start, end] = range.split("-");
  return {
    start: Number.parseInt(start),
    end: Number.parseInt(end),
    length: Number.parseInt(length),
  };
};

export const isComplete = ({ end, length }) => end === length - 1;

const downloadInChunks = async ({ bucket, key }) => {
  const writeStream = createWriteStream(
    fileURLToPath(new URL(`./${key}`, import.meta.url)),
  ).on("error", (err) => console.error(err));

  let rangeAndLength = { start: -1, end: -1, length: -1 };

  while (!isComplete(rangeAndLength)) {
    const { end } = rangeAndLength;
    const nextRange = { start: end + 1, end: end + oneMB };

    const { ContentRange, Body } = await getObjectRange({
      bucket,
      key,
      ...nextRange,
    });
    console.log(`Downloaded bytes ${nextRange.start} to ${nextRange.end}`);

    writeStream.write(await Body.transformToByteArray());
    rangeAndLength = getRangeAndLength(ContentRange);
  }
};

/**
 * Download a large object from and Amazon S3 bucket.
 *
 * When downloading a large file, you might want to break it down into
 * smaller pieces. Amazon S3 accepts a Range header to specify the start
 * and end of the byte range to be downloaded.
 *
 * @param {{ bucketName: string, key: string }}
 */
export const main = async ({ bucketName, key }) => {
  try {
    await downloadInChunks({
      bucket: bucketName,
      key: key,
    });
  } catch (caught) {
    if (caught instanceof NoSuchKey) {
      console.error(`Failed to download object. No such key "${key}".`);
      rmSync(key);
    }
  }
};
```

------
#### [ Go ]

멀티파트 업로드를 위한 Go 코드 예제에 대한 자세한 내용은 [AWS SDK를 사용하여 Amazon S3에 대용량 파일 업로드 또는 다운로드](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_Scenario_UsingLargeFiles_section.html)를 참조하세요.

**Example**  
업로드 관리자를 사용하여 데이터를 부분으로 나누고 동시에 업로드하여 큰 객체를 업로드합니다.  

```
import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"time"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/aws/aws-sdk-go-v2/service/s3/types"
	"github.com/aws/smithy-go"
)

// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
	S3Client *s3.Client
}
```

```
// UploadLargeObject uses an upload manager to upload data to an object in a bucket.
// The upload manager breaks large data into parts and uploads the parts concurrently.
func (basics BucketBasics) UploadLargeObject(ctx context.Context, bucketName string, objectKey string, largeObject []byte) error {
	largeBuffer := bytes.NewReader(largeObject)
	var partMiBs int64 = 10
	uploader := manager.NewUploader(basics.S3Client, func(u *manager.Uploader) {
		u.PartSize = partMiBs * 1024 * 1024
	})
	_, err := uploader.Upload(ctx, &s3.PutObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
		Body:   largeBuffer,
	})
	if err != nil {
		var apiErr smithy.APIError
		if errors.As(err, &apiErr) && apiErr.ErrorCode() == "EntityTooLarge" {
			log.Printf("Error while uploading object to %s. The object is too large.\n"+
				"The maximum size for a multipart upload is 5TB.", bucketName)
		} else {
			log.Printf("Couldn't upload large object to %v:%v. Here's why: %v\n",
				bucketName, objectKey, err)
		}
	} else {
		err = s3.NewObjectExistsWaiter(basics.S3Client).Wait(
			ctx, &s3.HeadObjectInput{Bucket: aws.String(bucketName), Key: aws.String(objectKey)}, time.Minute)
		if err != nil {
			log.Printf("Failed attempt to wait for object %s to exist.\n", objectKey)
		}
	}

	return err
}
```

**Example**  
다운로드 관리자를 사용하여 데이터를 부분으로 나누고 동시에 다운로드하여 큰 객체를 다운로드합니다.  

```
// DownloadLargeObject uses a download manager to download an object from a bucket.
// The download manager gets the data in parts and writes them to a buffer until all of
// the data has been downloaded.
func (basics BucketBasics) DownloadLargeObject(ctx context.Context, bucketName string, objectKey string) ([]byte, error) {
	var partMiBs int64 = 10
	downloader := manager.NewDownloader(basics.S3Client, func(d *manager.Downloader) {
		d.PartSize = partMiBs * 1024 * 1024
	})
	buffer := manager.NewWriteAtBuffer([]byte{})
	_, err := downloader.Download(ctx, buffer, &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
	})
	if err != nil {
		log.Printf("Couldn't download large object from %v:%v. Here's why: %v\n",
			bucketName, objectKey, err)
	}
	return buffer.Bytes(), err
}
```

------
#### [ PHP ]

이 주제에서는 멀티파트 파일 업로드를 위해 `Aws\S3\Model\MultipartUpload\UploadBuilder`의 상위 수준 AWS SDK for PHP 클래스를 사용하는 방법을 설명합니다. AWS SDK for Ruby API에 대한 자세한 내용은 [AWS SDK for Ruby – 버전 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)를 참조하세요.

다음은 Amazon S3 버킷에 파일을 업로드하는 PHP 예제입니다. 이 예제는 `MultipartUploader` 객체에 대한 파라미터를 설정하는 방법을 보여 줍니다.

```
 require 'vendor/autoload.php';

use Aws\Exception\MultipartUploadException;
use Aws\S3\MultipartUploader;
use Aws\S3\S3Client;

$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

// Prepare the upload parameters.
$uploader = new MultipartUploader($s3, '/path/to/large/file.zip', [
    'bucket' => $bucket,
    'key'    => $keyname
]);

// Perform the upload.
try {
    $result = $uploader->upload();
    echo "Upload complete: {$result['ObjectURL']}" . PHP_EOL;
} catch (MultipartUploadException $e) {
    echo $e->getMessage() . PHP_EOL;
}
```

------
#### [ Python ]

다음 예제에서는 상위 수준 멀티파트 업로드 Python API(`TransferManager` 클래스)를 사용하여 객체를 업로드합니다.

```
import sys
import threading

import boto3
from boto3.s3.transfer import TransferConfig


MB = 1024 * 1024
s3 = boto3.resource("s3")


class TransferCallback:
    """
    Handle callbacks from the transfer manager.

    The transfer manager periodically calls the __call__ method throughout
    the upload and download process so that it can take action, such as
    displaying progress to the user and collecting data about the transfer.
    """

    def __init__(self, target_size):
        self._target_size = target_size
        self._total_transferred = 0
        self._lock = threading.Lock()
        self.thread_info = {}

    def __call__(self, bytes_transferred):
        """
        The callback method that is called by the transfer manager.

        Display progress during file transfer and collect per-thread transfer
        data. This method can be called by multiple threads, so shared instance
        data is protected by a thread lock.
        """
        thread = threading.current_thread()
        with self._lock:
            self._total_transferred += bytes_transferred
            if thread.ident not in self.thread_info.keys():
                self.thread_info[thread.ident] = bytes_transferred
            else:
                self.thread_info[thread.ident] += bytes_transferred

            target = self._target_size * MB
            sys.stdout.write(
                f"\r{self._total_transferred} of {target} transferred "
                f"({(self._total_transferred / target) * 100:.2f}%)."
            )
            sys.stdout.flush()


def upload_with_default_configuration(
    local_file_path, bucket_name, object_key, file_size_mb
):
    """
    Upload a file from a local folder to an Amazon S3 bucket, using the default
    configuration.
    """
    transfer_callback = TransferCallback(file_size_mb)
    s3.Bucket(bucket_name).upload_file(
        local_file_path, object_key, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def upload_with_chunksize_and_meta(
    local_file_path, bucket_name, object_key, file_size_mb, metadata=None
):
    """
    Upload a file from a local folder to an Amazon S3 bucket, setting a
    multipart chunk size and adding metadata to the Amazon S3 object.

    The multipart chunk size controls the size of the chunks of data that are
    sent in the request. A smaller chunk size typically results in the transfer
    manager using more threads for the upload.

    The metadata is a set of key-value pairs that are stored with the object
    in Amazon S3.
    """
    transfer_callback = TransferCallback(file_size_mb)

    config = TransferConfig(multipart_chunksize=1 * MB)
    extra_args = {"Metadata": metadata} if metadata else None
    s3.Bucket(bucket_name).upload_file(
        local_file_path,
        object_key,
        Config=config,
        ExtraArgs=extra_args,
        Callback=transfer_callback,
    )
    return transfer_callback.thread_info


def upload_with_high_threshold(local_file_path, bucket_name, object_key, file_size_mb):
    """
    Upload a file from a local folder to an Amazon S3 bucket, setting a
    multipart threshold larger than the size of the file.

    Setting a multipart threshold larger than the size of the file results
    in the transfer manager sending the file as a standard upload instead of
    a multipart upload.
    """
    transfer_callback = TransferCallback(file_size_mb)
    config = TransferConfig(multipart_threshold=file_size_mb * 2 * MB)
    s3.Bucket(bucket_name).upload_file(
        local_file_path, object_key, Config=config, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def upload_with_sse(
    local_file_path, bucket_name, object_key, file_size_mb, sse_key=None
):
    """
    Upload a file from a local folder to an Amazon S3 bucket, adding server-side
    encryption with customer-provided encryption keys to the object.

    When this kind of encryption is specified, Amazon S3 encrypts the object
    at rest and allows downloads only when the expected encryption key is
    provided in the download request.
    """
    transfer_callback = TransferCallback(file_size_mb)
    if sse_key:
        extra_args = {"SSECustomerAlgorithm": "AES256", "SSECustomerKey": sse_key}
    else:
        extra_args = None
    s3.Bucket(bucket_name).upload_file(
        local_file_path, object_key, ExtraArgs=extra_args, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def download_with_default_configuration(
    bucket_name, object_key, download_file_path, file_size_mb
):
    """
    Download a file from an Amazon S3 bucket to a local folder, using the
    default configuration.
    """
    transfer_callback = TransferCallback(file_size_mb)
    s3.Bucket(bucket_name).Object(object_key).download_file(
        download_file_path, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def download_with_single_thread(
    bucket_name, object_key, download_file_path, file_size_mb
):
    """
    Download a file from an Amazon S3 bucket to a local folder, using a
    single thread.
    """
    transfer_callback = TransferCallback(file_size_mb)
    config = TransferConfig(use_threads=False)
    s3.Bucket(bucket_name).Object(object_key).download_file(
        download_file_path, Config=config, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def download_with_high_threshold(
    bucket_name, object_key, download_file_path, file_size_mb
):
    """
    Download a file from an Amazon S3 bucket to a local folder, setting a
    multipart threshold larger than the size of the file.

    Setting a multipart threshold larger than the size of the file results
    in the transfer manager sending the file as a standard download instead
    of a multipart download.
    """
    transfer_callback = TransferCallback(file_size_mb)
    config = TransferConfig(multipart_threshold=file_size_mb * 2 * MB)
    s3.Bucket(bucket_name).Object(object_key).download_file(
        download_file_path, Config=config, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def download_with_sse(
    bucket_name, object_key, download_file_path, file_size_mb, sse_key
):
    """
    Download a file from an Amazon S3 bucket to a local folder, adding a
    customer-provided encryption key to the request.

    When this kind of encryption is specified, Amazon S3 encrypts the object
    at rest and allows downloads only when the expected encryption key is
    provided in the download request.
    """
    transfer_callback = TransferCallback(file_size_mb)

    if sse_key:
        extra_args = {"SSECustomerAlgorithm": "AES256", "SSECustomerKey": sse_key}
    else:
        extra_args = None
    s3.Bucket(bucket_name).Object(object_key).download_file(
        download_file_path, ExtraArgs=extra_args, Callback=transfer_callback
    )
    return transfer_callback.thread_info
```

------

## AWS SDK 사용(하위 수준 API)
<a name="mpu-upload-low-level"></a>

AWS SDK는 멀티파트 업로드를 위해 Amazon S3 REST API와 매우 유사한 하위 수준 API를 표시합니다([Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 참조). 멀티파트 업로드를 일시 중지한 후 다시 시작해야 하거나 업로드 중에 부분 크기를 변경해야 하거나 업로드 데이터 크기를 미리 확인하지 않은 경우 하위 수준 API를 사용합니다. 이러한 요구 사항이 없는 경우에는 상위 수준 API를 사용합니다([AWS SDK 사용(상위 수준 API)](#multipart-upload-high-level) 참조).

------
#### [ Java ]

다음 예제에서는 하위 수준 Java 클래스를 사용하여 파일을 업로드하는 방법을 보여 줍니다. 여기에서는 다음 단계를 수행합니다.
+ `AmazonS3Client.initiateMultipartUpload()` 메서드를 사용하여 멀티파트 업로드를 시작하고, `InitiateMultipartUploadRequest` 객체를 전달합니다.
+ `AmazonS3Client.initiateMultipartUpload()` 메서드가 반환하는 업로드 ID를 저장합니다. 이후의 각 멀티파트 업로드 작업에서 이 업로드 ID를 제공합니다.
+ 객체의 파트를 업로드합니다. 각 파트에 대해 `AmazonS3Client.uploadPart()` 메서드를 호출합니다. `UploadPartRequest` 객체를 사용하여 파트 업로드 정보를 제공합니다.
+ 각 파트에 대해 `AmazonS3Client.uploadPart()` 메서드의 응답에서 얻은 ETag를 목록에 저장합니다. ETag 값을 사용하여 멀티파트 업로드를 완료합니다.
+ `AmazonS3Client.completeMultipartUpload()` 메서드를 호출하여 멀티파트 업로드를 완료합니다.

**Example**  
실제 예제를 작성 및 테스트하는 방법에 대한 자세한 내용은 AWS SDK for Java 개발자 안내서의 [시작하기](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html) 섹션을 참조하세요.  

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class LowLevelMultipartUpload {

    public static void main(String[] args) throws IOException {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";
        String keyName = "*** Key name ***";
        String filePath = "*** Path to file to upload ***";

        File file = new File(filePath);
        long contentLength = file.length();
        long partSize = 5 * 1024 * 1024; // Set part size to 5 MB.

        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withRegion(clientRegion)
                    .withCredentials(new ProfileCredentialsProvider())
                    .build();

            // Create a list of ETag objects. You retrieve ETags for each object part
            // uploaded,
            // then, after each individual part has been uploaded, pass the list of ETags to
            // the request to complete the upload.
            List<PartETag> partETags = new ArrayList<PartETag>();

            // Initiate the multipart upload.
            InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(bucketName, keyName);
            InitiateMultipartUploadResult initResponse = s3Client.initiateMultipartUpload(initRequest);

            // Upload the file parts.
            long filePosition = 0;
            for (int i = 1; filePosition < contentLength; i++) {
                // Because the last part could be less than 5 MB, adjust the part size as
                // needed.
                partSize = Math.min(partSize, (contentLength - filePosition));

                // Create the request to upload a part.
                UploadPartRequest uploadRequest = new UploadPartRequest()
                        .withBucketName(bucketName)
                        .withKey(keyName)
                        .withUploadId(initResponse.getUploadId())
                        .withPartNumber(i)
                        .withFileOffset(filePosition)
                        .withFile(file)
                        .withPartSize(partSize);

                // Upload the part and add the response's ETag to our list.
                UploadPartResult uploadResult = s3Client.uploadPart(uploadRequest);
                partETags.add(uploadResult.getPartETag());

                filePosition += partSize;
            }

            // Complete the multipart upload.
            CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(bucketName, keyName,
                    initResponse.getUploadId(), partETags);
            s3Client.completeMultipartUpload(compRequest);
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }
}
```

------
#### [ .NET ]

다음은 하위 수준 SDK for .NET 멀티파트 업로드 API를 사용하여 S3 버킷에 파일을 업로드하는 방법을 보여주는 C\$1 예제입니다. Amazon S3 멀티파트 업로드에 대한 자세한 내용은 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하세요.

**참고**  
SDK for .NET API를 사용하여 대용량 객체를 업로드하는 경우 요청 스트림에 데이터를 기록하는 중 시간 초과가 발생할 수 있습니다. `UploadPartRequest`를 사용하여 제한 시간을 명시적으로 설정할 수 있습니다.

다음은 하위 수준 멀티파트 업로드 API를 사용하여 S3 버킷에 파일을 업로드하는 C\$1 예제입니다. 코드 예제 설정 및 실행에 대한 자세한 내용은 *AWS SDK for .NET 개발자 안내서*의 [AWS SDK for .NET 시작하기](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)를 참조하세요.

```
using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class UploadFileMPULowLevelAPITest
    {
        private const string bucketName = "*** provide bucket name ***";
        private const string keyName = "*** provide a name for the uploaded object ***";
        private const string filePath = "*** provide the full path name of the file to upload ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;

        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            Console.WriteLine("Uploading an object");
            UploadObjectAsync().Wait(); 
        }

        private static async Task UploadObjectAsync()
        {
            // Create list to store upload part responses.
            List<UploadPartResponse> uploadResponses = new List<UploadPartResponse>();

            // Setup information required to initiate the multipart upload.
            InitiateMultipartUploadRequest initiateRequest = new InitiateMultipartUploadRequest
            {
                BucketName = bucketName,
                Key = keyName
            };

            // Initiate the upload.
            InitiateMultipartUploadResponse initResponse =
                await s3Client.InitiateMultipartUploadAsync(initiateRequest);

            // Upload parts.
            long contentLength = new FileInfo(filePath).Length;
            long partSize = 5 * (long)Math.Pow(2, 20); // 5 MB

            try
            {
                Console.WriteLine("Uploading parts");
        
                long filePosition = 0;
                for (int i = 1; filePosition < contentLength; i++)
                {
                    UploadPartRequest uploadRequest = new UploadPartRequest
                        {
                            BucketName = bucketName,
                            Key = keyName,
                            UploadId = initResponse.UploadId,
                            PartNumber = i,
                            PartSize = partSize,
                            FilePosition = filePosition,
                            FilePath = filePath
                        };

                    // Track upload progress.
                    uploadRequest.StreamTransferProgress +=
                        new EventHandler<StreamTransferProgressArgs>(UploadPartProgressEventCallback);

                    // Upload a part and add the response to our list.
                    uploadResponses.Add(await s3Client.UploadPartAsync(uploadRequest));

                    filePosition += partSize;
                }

                // Setup to complete the upload.
                CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest
                    {
                        BucketName = bucketName,
                        Key = keyName,
                        UploadId = initResponse.UploadId
                     };
                completeRequest.AddPartETags(uploadResponses);

                // Complete the upload.
                CompleteMultipartUploadResponse completeUploadResponse =
                    await s3Client.CompleteMultipartUploadAsync(completeRequest);
            }
            catch (Exception exception)
            {
                Console.WriteLine("An AmazonS3Exception was thrown: { 0}", exception.Message);

                // Abort the upload.
                AbortMultipartUploadRequest abortMPURequest = new AbortMultipartUploadRequest
                {
                    BucketName = bucketName,
                    Key = keyName,
                    UploadId = initResponse.UploadId
                };
               await s3Client.AbortMultipartUploadAsync(abortMPURequest);
            }
        }
        public static void UploadPartProgressEventCallback(object sender, StreamTransferProgressArgs e)
        {
            // Process event. 
            Console.WriteLine("{0}/{1}", e.TransferredBytes, e.TotalBytes);
        }
    }
}
```

------
#### [ PHP ]

이 주제는 AWS SDK for PHP 버전 3에서 하위 수준 `uploadPart` 메서드를 사용하여 파일을 여러 부분으로 업로드하는 방법을 보여 줍니다. AWS SDK for Ruby API에 대한 자세한 내용은 [AWS SDK for Ruby – 버전 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)를 참조하세요.

다음은 하위 수준 PHP API 멀티파트 업로드를 사용하여 Amazon S3 버킷에 파일을 업로드하는 PHP 예제입니다.

```
 require 'vendor/autoload.php';

use Aws\S3\Exception\S3Exception;
use Aws\S3\S3Client;

$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';
$filename = '*** Path to and Name of the File to Upload ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

$result = $s3->createMultipartUpload([
    'Bucket'       => $bucket,
    'Key'          => $keyname,
    'StorageClass' => 'REDUCED_REDUNDANCY',
    'Metadata'     => [
        'param1' => 'value 1',
        'param2' => 'value 2',
        'param3' => 'value 3'
    ]
]);
$uploadId = $result['UploadId'];

// Upload the file in parts.
try {
    $file = fopen($filename, 'r');
    $partNumber = 1;
    while (!feof($file)) {
        $result = $s3->uploadPart([
            'Bucket'     => $bucket,
            'Key'        => $keyname,
            'UploadId'   => $uploadId,
            'PartNumber' => $partNumber,
            'Body'       => fread($file, 5 * 1024 * 1024),
        ]);
        $parts['Parts'][$partNumber] = [
            'PartNumber' => $partNumber,
            'ETag' => $result['ETag'],
        ];
        $partNumber++;

        echo "Uploading part $partNumber of $filename." . PHP_EOL;
    }
    fclose($file);
} catch (S3Exception $e) {
    $result = $s3->abortMultipartUpload([
        'Bucket'   => $bucket,
        'Key'      => $keyname,
        'UploadId' => $uploadId
    ]);

    echo "Upload of $filename failed." . PHP_EOL;
}

// Complete the multipart upload.
$result = $s3->completeMultipartUpload([
    'Bucket'   => $bucket,
    'Key'      => $keyname,
    'UploadId' => $uploadId,
    'MultipartUpload'    => $parts,
]);
$url = $result['Location'];

echo "Uploaded $filename to $url." . PHP_EOL;
```

------

## AWS SDK for Ruby 사용
<a name="mpuoverview-ruby-sdk"></a>

AWS SDK for Ruby 버전 3은 Amazon S3 멀티파트 업로드를 두 가지 방법으로 지원합니다. 첫 번째 옵션으로 관리형 파일 업로드를 사용할 수 있습니다. 자세한 내용은 *AWS 개발자 블로그*에서 [Amazon S3에 파일 업로드](https://aws.amazon.com/blogs/developer/uploading-files-to-amazon-s3/)를 참조하십시오. 관리형 파일 업로드는 파일을 버킷에 업로드하는 데 권장되는 방법입니다. 관리형 파일 업로드에는 다음과 같은 이점이 있습니다.
+ 15MB를 초과하는 객체에 대해 멀티파트 업로드를 관리합니다.
+ 인코딩 문제를 방지하기 위해 이진 모드에서 파일을 올바로 엽니다.
+ 대형 객체의 부분 업로드에 대한 여러 스레드를 병렬로 사용합니다.

또는 다음의 멀티파트 업로드 클라이언트 작업을 직접 사용할 수 있습니다.
+ [create\$1multipart\$1upload](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#create_multipart_upload-instance_method) – 멀티파트 업로드를 시작하고 업로드 ID를 반환합니다.
+ [upload\$1part](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#upload_part-instance_method) – 멀티파트 업로드에서 파트를 업로드합니다.
+ [upload\$1part\$1copy](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#upload_part_copy-instance_method) – 기존 객체에서 데이터를 복사하여 파트를 데이터 원본으로 업로드합니다.
+ [complete\$1multipart\$1upload](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#complete_multipart_upload-instance_method) – 이전에 업로드된 파트를 어셈블하여 멀티파트 업로드를 완료합니다.
+ [abort\$1multipart\$1upload](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#abort_multipart_upload-instance_method) – 멀티파트 업로드를 중단합니다.

# 상위 수준 .NET TransferUtility 클래스를 사용하여 디렉터리 업로드
<a name="HLuploadDirDotNet"></a>

`TransferUtility` 클래스를 사용하여 전체 디렉터리를 업로드할 수 있습니다. 기본적으로 API는 지정된 디렉터리의 루트에서만 파일을 업로드합니다. 하지만 모든 하위 디렉터리에서 반복적으로 파일을 업로드하도록 지정할 수 있습니다.

필터링 기준에 따라 지정된 디렉터리에서 파일을 선택하려면 필터링 표현식을 지정합니다. 예를 들어 디렉터리에서 `PDF` 파일만 업로드하려면 `"*.pdf"` 필터 표현식을 지정합니다.

디렉터리에서 파일을 업로드할 경우 결과 객체의 키 이름을 지정하지 않습니다. Amazon S3는 원래 파일 경로를 사용하여 키 이름을 구성합니다. 예를 들어, 다음 구조의 `c:\myfolder` 디렉터리가 있다고 가정합니다.

**Example**  

```
1. C:\myfolder
2.       \a.txt
3.       \b.pdf
4.       \media\               
5.              An.mp3
```

이 디렉터리를 업로드하는 경우 Amazon S3는 다음 키 이름을 사용합니다.

**Example**  

```
1. a.txt
2. b.pdf
3. media/An.mp3
```

**Example**  
다음 C\$1 예제는 Amazon S3 버킷에 디렉터리를 업로드합니다. 다양한 `TransferUtility.UploadDirectory` 오버로드를 사용하여 디렉터리를 업로드하는 방법을 보여줍니다. 업로드에 대해 연속적으로 수행되는 각 호출이 이전 업로드를 대체합니다. 코드 예제 설정 및 실행에 대한 자세한 내용은 *AWS SDK for .NET 개발자 안내서*의 [AWS SDK for .NET 시작하기](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)를 참조하세요.  

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using System;
using System.IO;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class UploadDirMPUHighLevelAPITest
    {
        private const string existingBucketName = "*** bucket name ***";
        private const string directoryPath = @"*** directory path ***";
        // The example uploads only .txt files.
        private const string wildCard = "*.txt";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;
        static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            UploadDirAsync().Wait();
        }

        private static async Task UploadDirAsync()
        {
            try
            {
                var directoryTransferUtility =
                    new TransferUtility(s3Client);

                // 1. Upload a directory.
                await directoryTransferUtility.UploadDirectoryAsync(directoryPath,
                    existingBucketName);
                Console.WriteLine("Upload statement 1 completed");

                // 2. Upload only the .txt files from a directory 
                //    and search recursively. 
                await directoryTransferUtility.UploadDirectoryAsync(
                                               directoryPath,
                                               existingBucketName,
                                               wildCard,
                                               SearchOption.AllDirectories);
                Console.WriteLine("Upload statement 2 completed");

                // 3. The same as Step 2 and some optional configuration. 
                //    Search recursively for .txt files to upload.
                var request = new TransferUtilityUploadDirectoryRequest
                {
                    BucketName = existingBucketName,
                    Directory = directoryPath,
                    SearchOption = SearchOption.AllDirectories,
                    SearchPattern = wildCard
                };

                await directoryTransferUtility.UploadDirectoryAsync(request);
                Console.WriteLine("Upload statement 3 completed");
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine(
                        "Error encountered ***. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine(
                    "Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }
    }
}
```

# 멀티파트 업로드 나열
<a name="list-mpu"></a>

AWS CLI, REST API 또는 AWS SDK를 사용하여 Amazon S3에서 진행 중인 멀티파트 업로드 목록을 검색할 수 있습니다. 멀티파트 업로드를 사용하여 프로그래밍 방식으로 단일 객체를 Amazon S3에 업로드할 수 있습니다. 멀티파트 업로드는 한 번에 객체 데이터를 일부분씩 옮겨 객체를 Amazon S3로 이동합니다. 멀티파트 업로드에 대한 일반적인 내용을 자세히 알아보려면 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하세요.

추가 체크섬이 포함된 멀티파트 업로드를 사용하여 객체를 업로드하는 전체 절차는 [튜토리얼: 멀티파트 업로드를 통한 객체 업로드 및 데이터 무결성 확인](tutorial-s3-mpu-additional-checksums.md) 섹션을 참조하세요.

다음 섹션에서는 AWS Command Line Interface, Amazon S3 REST API, AWS SDK를 사용하여 진행 중인 멀티파트 업로드를 나열하는 방법을 보여줍니다.

## AWS CLI를 사용한 멀티파트 업로드 나열
<a name="list-mpu-cli"></a>

AWS Command Line Interface의 다음 섹션에서는 멀티파트 업로드를 나열하는 작업을 설명합니다.
+ [list-parts](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/list-parts.html) - 특정 멀티파트 업로드의 업로드된 부분을 나열합니다.
+ [list-multipart-uploads](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-multipart-uploads.html) - 진행 중인 멀티파트 업로드를 나열합니다.

# REST API를 사용한 멀티파트 업로드 나열
<a name="list-mpu-rest"></a>

*Amazon Simple Storage Service API 참조*의 다음 섹션에서는 멀티파트 업로드 나열을 위한 REST API에 대해 설명합니다.
+ [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html) - 특정 멀티파트 업로드의 업로드된 부분을 나열합니다.
+ [ListMultipartUploads](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html) - 진행 중인 멀티파트 업로드를 나열합니다.

## AWS SDK(하위 수준 API)를 사용한 멀티파트 업로드 나열
<a name="list-aws-sdk"></a>

------
#### [ Java ]

AWS SDK for Java를 사용하여 버킷에서 진행 중인 모든 멀티파트 업로드를 나열하려면 하위 수준 API 클래스를 사용하여 다음을 수행할 수 있습니다.


**하위 수준 API 멀티파트 업로드 목록 조회 프로세스**  

|  |  | 
| --- |--- |
| 1 | `ListMultipartUploadsRequest` 클래스의 인스턴스를 만들고 버킷 이름을 제공합니다. | 
| 2 | S3Client `listMultipartUploads` 메서드를 실행합니다. 이 메서드는 진행 중인 멀티파트 업로드에 대한 정보를 제공하는 `ListMultipartUploadsResponse` 클래스의 인스턴스를 반환합니다. | 

AWS SDK for Java를 사용하여 멀티파트 업로드를 나열하는 방법의 예는 *Amazon S3 API 참조*의 [List multipart uploads](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_ListMultipartUploads_section.html)를 참조하세요.

------
#### [ .NET ]

특정 버킷에 대해 진행 중인 멀티파트 업로드를 모두 나열하려면 SDK for .NET 하위 수준 멀티파트 업로드 API의 `ListMultipartUploadsRequest` 클래스를 사용합니다. `AmazonS3Client.ListMultipartUploads` 메서드는 진행 중인 멀티파트 업로드에 대한 정보를 제공하는 `ListMultipartUploadsResponse` 클래스의 인스턴스를 반환합니다.

여기에서 진행 중인 멀티파트 업로드란 멀티파트 업로드 요청 시작을 통해 시작되었지만 아직 완료되거나 중지되지 않은 멀티파트 업로드를 말합니다. Amazon S3 멀티파트 업로드에 대한 자세한 내용은 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하세요.

다음 C\$1 예제는 SDK for .NET를 사용하여 버킷에 대해 진행 중인 모든 멀티파트 업로드를 나열하는 방법을 보여줍니다. 코드 예제 설정 및 실행에 대한 자세한 내용은 *AWS SDK for .NET 개발자 안내서*의 [AWS SDK for .NET 시작하기](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)를 참조하세요.

```
ListMultipartUploadsRequest request = new ListMultipartUploadsRequest
{
	 BucketName = bucketName // Bucket receiving the uploads.
};

ListMultipartUploadsResponse response = await AmazonS3Client.ListMultipartUploadsAsync(request);
```

------
#### [ PHP ]

이 주제에서는 AWS SDK for PHP 버전 3의 하위 수준 API 클래스를 사용하여 버킷에서 진행 중인 멀티파트 업로드를 모두 나열하는 방법을 보여줍니다. AWS SDK for Ruby API에 대한 자세한 내용은 [AWS SDK for Ruby – 버전 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)를 참조하세요.

다음은 버킷에서 진행 중인 멀티파트 업로드를 모두 나열하는 방법을 보여 주는 PHP 예제입니다.

```
 require 'vendor/autoload.php';

use Aws\S3\S3Client;

$bucket = '*** Your Bucket Name ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

// Retrieve a list of the current multipart uploads.
$result = $s3->listMultipartUploads([
    'Bucket' => $bucket
]);

// Write the list of uploads to the page.
print_r($result->toArray());
```

------

# AWS SDK를 사용하여 멀티파트 업로드 추적
<a name="track-mpu"></a>

수신 대기 인터페이스를 사용하여 Amazon S3에 대한 객체 업로드 진행 상황을 추적할 수 있습니다. 고급 멀티파트 업로드 API는 `ProgressListener`라는 수신 대기 인터페이스를 제공합니다. 진행률 이벤트는 주기적으로 발생하며 바이트가 전송되었음을 리스너에게 통보합니다. 멀티파트 업로드에 대한 일반적인 내용을 자세히 알아보려면 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하세요.

추가 체크섬이 포함된 멀티파트 업로드를 사용하여 객체를 업로드하는 전체 절차는 [튜토리얼: 멀티파트 업로드를 통한 객체 업로드 및 데이터 무결성 확인](tutorial-s3-mpu-additional-checksums.md) 섹션을 참조하세요.

다음 섹션에서는 AWS SDK와 함께 멀티파트 업로드를 추적하는 방법을 보여줍니다.

------
#### [ Java ]

**Example**  
다음 Java 코드는 파일을 업로드하고 `ExecutionInterceptor`을(를) 사용하여 업로드 진행률을 추적합니다. 작동하는 샘플을 만들어 테스트하는 방법에 대한 지침은 AWS SDK for Java 2.x 개발자 안내서의 [Getting Started](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html)를 참조하세요.  

```
import java.nio.file.Paths;

import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.interceptor.Context;
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

public class TrackMPUProgressUsingHighLevelAPI {

    static class ProgressListener implements ExecutionInterceptor {
        private long transferredBytes = 0;

        @Override
        public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) {
            if (context.httpRequest().firstMatchingHeader("Content-Length").isPresent()) {
                String contentLength = context.httpRequest().firstMatchingHeader("Content-Length").get();
                long partSize = Long.parseLong(contentLength);
                transferredBytes += partSize;
                System.out.println("Transferred bytes: " + transferredBytes);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        String existingBucketName = "*** Provide bucket name ***";
        String keyName = "*** Provide object key ***";
        String filePath = "*** file to upload ***";

        S3AsyncClient s3Client = S3AsyncClient.builder()
                .credentialsProvider(ProfileCredentialsProvider.create())
                .overrideConfiguration(c -> c.addExecutionInterceptor(new ProgressListener()))
                .build();

        // For more advanced uploads, you can create a request object
        // and supply additional request parameters (ex: progress listeners,
        // canned ACLs, etc.)
        PutObjectRequest request = PutObjectRequest.builder()
                .bucket(existingBucketName)
                .key(keyName)
                .build();

        AsyncRequestBody requestBody = AsyncRequestBody.fromFile(Paths.get(filePath));

        // You can ask the upload for its progress, or you can
        // add a ProgressListener to your request to receive notifications
        // when bytes are transferred.
        // S3AsyncClient processes all transfers asynchronously,
        // so this call will return immediately.
        var upload = s3Client.putObject(request, requestBody);

        try {
            // You can block and wait for the upload to finish
            upload.join();
        } catch (Exception exception) {
            System.out.println("Unable to upload file, upload aborted.");
            exception.printStackTrace();
        } finally {
            s3Client.close();
        }
    }
}
```

------
#### [ .NET ]

다음 C\$1 예제는 `TransferUtility` 클래스를 사용하여 S3 버킷에 파일을 업로드하고 업로드 진행률을 추적합니다. 코드 예제 설정 및 실행에 대한 자세한 내용은 *AWS SDK for .NET 개발자 안내서*의 [AWS SDK for .NET 시작하기](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)를 참조하세요.

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using System;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class TrackMPUUsingHighLevelAPITest
    {
        private const string bucketName = "*** provide the bucket name ***";
        private const string keyName = "*** provide the name for the uploaded object ***";
        private const string filePath = " *** provide the full path name of the file to upload **";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;


        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            TrackMPUAsync().Wait();
        }

        private static async Task TrackMPUAsync()
        {
            try
            {
                var fileTransferUtility = new TransferUtility(s3Client);

                // Use TransferUtilityUploadRequest to configure options.
                // In this example we subscribe to an event.
                var uploadRequest =
                    new TransferUtilityUploadRequest
                    {
                        BucketName = bucketName,
                        FilePath = filePath,
                        Key = keyName
                    };

                uploadRequest.UploadProgressEvent +=
                    new EventHandler<UploadProgressArgs>
                        (uploadRequest_UploadPartProgressEvent);

                await fileTransferUtility.UploadAsync(uploadRequest);
                Console.WriteLine("Upload completed");
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }

        static void uploadRequest_UploadPartProgressEvent(object sender, UploadProgressArgs e)
        {
            // Process event.
            Console.WriteLine("{0}/{1}", e.TransferredBytes, e.TotalBytes);
        }
    }
}
```

------

# 멀티파트 업로드 중단
<a name="abort-mpu"></a>

멀티파트 업로드를 개시한 후에 부분 업로드를 시작합니다. Amazon S3는 부분들을 저장하며, 모든 부분을 업로드하고 멀티파트 업로드 완료 요청을 보낸 후에만 객체를 생성합니다. 완전한 멀티파트 업로드 요청을 수신하면 그 즉시 Amazon S3는 부분들을 결합해 객체를 생성합니다. 완전한 멀티파트 업로드 요청을 성공적으로 전송하지 못하면 S3는 부분들을 결합하지 않고 어떤 객체도 생성하지 않습니다. 부분들을 업로드한 후 멀티파트 업로드를 완료하지 않으려면 멀티파트 업로드를 중단해야 합니다.

업로드된 부분에 연결된 모든 스토리지에 대해 요금이 청구됩니다. 항상 멀티파트 업로드를 완료하거나 멀티파트 업로드를 중지하여 업로드된 부분을 제거하는 것이 좋습니다. 요금에 대한 자세한 내용은 [멀티파트 업로드 및 요금](mpuoverview.md#mpuploadpricing) 단원을 참조하세요.

버킷 수명 주기 구성을 사용하여 불완전한 멀티파트 업로드를 중지할 수도 있습니다. 자세한 내용은 [불완전한 멀티파트 업로드를 삭제하도록 버킷 수명 주기 구성 설정](mpu-abort-incomplete-mpu-lifecycle-config.md) 섹션을 참조하세요.

다음 섹션에서는 AWS Command Line Interface, REST API 또는 AWS SDK를 사용하여 Amazon S3에서 진행 중인 멀티파트 업로드를 중지하는 방법을 보여줍니다.

## AWS CLI 사용
<a name="abort-mpu-cli"></a>

AWS CLI를 사용하여 멀티파트 업로드를 중지하는 방법에 대한 자세한 내용은 *AWS CLI 명령 참조*의 [abort-multipart-upload](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/abort-multipart-upload.html)를 참조하십시오.

## REST API 사용
<a name="abort-mpu-rest"></a>

REST API를 사용하여 멀티파트 업로드를 중지하는 방법에 대한 자세한 내용은 *Amazon Simple Storage Service API 참조*의 [AbortMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html)를 참조하십시오.

## AWS SDK 사용(상위 수준 API)
<a name="abort-mpu-high-level"></a>

------
#### [ Java ]

AWS SDK for Java를 사용하여 진행 중인 멀티파트 업로드를 중지하려면 지정된 날짜 이전에 시작되어 아직 진행 중인 업로드를 중단할 수 있습니다. 사용자가 업로드를 시작한 후 완료 또는 중지할 때까지 업로드가 진행 중인 것으로 간주됩니다.

멀티파트 업로드를 중지하려면 다음을 수행할 수 있습니다.


|  |  | 
| --- |--- |
| 1 | S3Client 인스턴스를 만듭니다. | 
| 2 | 버킷 이름과 기타 필수 파라미터를 전달하여 클라이언트의 중단 메서드를 사용합니다. | 

**참고**  
특정 멀티파트 업로드를 중지할 수도 있습니다. 자세한 내용은 [AWS SDK 사용(하위 수준 API)](#abort-mpu-low-level) 섹션을 참조하세요.

AWS SDK for Java를 사용하여 멀티파트 업로드를 중단하는 방법의 예는 *Amazon S3 API 참조*의 [Cancel a multipart upload](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_AbortMultipartUpload_section.html)를 참조하세요.

------
#### [ .NET ]

다음 C\$1 예제는 1주일 이상 전에 특정 버킷에서 시작되어 진행 중인 멀티파트 업로드를 모두 중지합니다. 코드 예제 설정 및 실행에 대한 자세한 내용은 *AWS SDK for .NET 개발자 안내서*의 [AWS SDK for .NET 시작하기](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)를 참조하세요.

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using System;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class AbortMPUUsingHighLevelAPITest
    {
        private const string bucketName = "*** provide bucket name ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;

        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            AbortMPUAsync().Wait();
        }

        private static async Task AbortMPUAsync()
        {
            try
            {
                var transferUtility = new TransferUtility(s3Client);

                // Abort all in-progress uploads initiated before the specified date.
                await transferUtility.AbortMultipartUploadsAsync(
                    bucketName, DateTime.Now.AddDays(-7));
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        } 
    }
}
```

**참고**  
특정 멀티파트 업로드를 중지할 수도 있습니다. 자세한 내용은 [AWS SDK 사용(하위 수준 API)](#abort-mpu-low-level) 섹션을 참조하세요.

------

## AWS SDK 사용(하위 수준 API)
<a name="abort-mpu-low-level"></a>

`AmazonS3.abortMultipartUpload` 메서드를 호출하여 진행 중인 멀티파트 업로드를 중단할 수 있습니다. 이 메서드는 Amazon S3에 업로드된 모든 부분을 삭제하므로 가용 리소스가 늘어나게 됩니다. 업로드 ID, 버킷 이름 및 키 이름을 제공해야 합니다. 다음은 진행 중인 멀티파트 업로드를 중지하는 방법을 보여주는 Java 코드 예제입니다.

멀티파트 업로드를 중지하려면 업로드에 사용된 업로드 ID, 버킷 및 키 이름을 제공해야 합니다. 멀티파트 업로드를 중지하면 해당 업로드 ID를 사용해 추가 파트를 업로드할 수 없습니다. Amazon S3 멀티파트 업로드에 대한 자세한 내용은 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하세요.

------
#### [ Java ]

AWS SDK for Java를 사용하여 진행 중인 특정 멀티파트 업로드를 중지하려면 하위 수준 API를 사용하여 버킷 이름, 객체 키 및 업로드 ID를 제공함으로써 업로드를 중단할 수 있습니다.

**참고**  
특정 멀티파트 업로드를 중단하는 대신, 특정 시간 이전에 시작되어 아직 진행 중인 모든 멀티파트 업로드를 중지할 수 있습니다. 이 정리 작업은 시작되었지만 완료되거나 중지되지 않은 이전 멀티파트 업로드를 중지하는 데 유용합니다. 자세한 내용은 [AWS SDK 사용(상위 수준 API)](#abort-mpu-high-level) 섹션을 참조하세요.

AWS SDK for Java를 사용하여 특정 멀티파트 업로드를 중단하는 방법의 예는 *Amazon S3 API 참조*의 [Cancel a multipart upload](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_AbortMultipartUpload_section.html)를 참조하세요.

------
#### [ .NET ]

다음 C\$1 예제는 멀티파트 업로드를 중지하는 방법을 보여줍니다. 다음 코드가 포함된 전체 C\$1 예제는 [AWS SDK 사용(하위 수준 API)](mpu-upload-object.md#mpu-upload-low-level) 섹션을 참조하세요.

```
AbortMultipartUploadRequest abortMPURequest = new AbortMultipartUploadRequest
{
    BucketName = existingBucketName,
    Key = keyName,
    UploadId = initResponse.UploadId
};
await AmazonS3Client.AbortMultipartUploadAsync(abortMPURequest);
```

또한 특정 시간 이전에 시작되어 진행 중인 멀티파트 업로드를 중단할 수도 있습니다. 이 정리 작업은 완료 또는 중단되지 않은 멀티파트 업로드를 중단할 때 유용합니다. 자세한 내용은 [AWS SDK 사용(상위 수준 API)](#abort-mpu-high-level) 섹션을 참조하세요.

------
#### [ PHP ]

이 예제에서는 진행 중인 멀티파트 업로드를 중지하기 위해 AWS SDK for PHP 버전 3의 클래스를 사용하는 방법을 보여줍니다. AWS SDK for Ruby API에 대한 자세한 내용은 [AWS SDK for Ruby – 버전 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)를 참조하세요. 예를 들어 `abortMultipartUpload()` 메서드입니다.

AWS SDK for Ruby API에 대한 자세한 내용은 [AWS SDK for Ruby – 버전 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)를 참조하세요.

```
 require 'vendor/autoload.php';

use Aws\S3\S3Client;

$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';
$uploadId = '*** Upload ID of upload to Abort ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

// Abort the multipart upload.
$s3->abortMultipartUpload([
    'Bucket'   => $bucket,
    'Key'      => $keyname,
    'UploadId' => $uploadId,
]);
```

------

# 멀티파트 업로드를 사용한 객체 복사
<a name="CopyingObjectsMPUapi"></a>

멀티파트 업로드를 통해 객체를 여러 부분의 집합으로 복사할 수 있습니다. 이 섹션의 예제는 멀티파트 업로드 API를 사용하여 5GB보다 큰 객체를 복사하는 방법을 보여 줍니다. 멀티파트 업로드에 대한 내용은 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하세요.

멀티파트 업로드 API를 사용하지 않고 단일 작업으로는 5GB보다 작은 객체를 복사할 수 있습니다. AWS Management Console, AWS CLI, REST API 또는 AWS SDK를 사용하여 5GB보다 작은 객체를 복사할 수 있습니다. 자세한 내용은 [객체 복사, 이동, 이름 변경](copy-object.md) 섹션을 참조하세요.

추가 체크섬이 포함된 멀티파트 업로드를 사용하여 객체를 업로드하는 전체 절차는 [튜토리얼: 멀티파트 업로드를 통한 객체 업로드 및 데이터 무결성 확인](tutorial-s3-mpu-additional-checksums.md) 섹션을 참조하세요.

다음 섹션에서는 REST API 또는 AWS SDK를 사용하여 멀티파트 업로드로 객체를 복사하는 방법을 보여줍니다.

## REST API 사용
<a name="CopyingObjctsUsingRESTMPUapi"></a>

*Amazon Simple Storage Service API 참조*의 다음 섹션에서는 멀티파트 업로드를 위한 REST API에 대해 설명합니다. 기존 객체를 복사하려면, 파트 업로드(복사) API를 사용하고 요청에 `x-amz-copy-source` 요청 헤더를 추가하여 소스 객체를 지정합니다.
+ [멀티파트 업로드 시작](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html)
+ [부분 업로드](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html)
+ [부분 업로드(복사)](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html)
+ [멀티파트 업로드 완료](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadComplete.html)
+ [멀티파트 업로드 중단](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadAbort.html)
+ [부분 목록 조회](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadListParts.html)
+ [멀티파트 업로드 목록 조회](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadListMPUpload.html)

이러한 API를 사용하여 REST 요청을 만들거나, 제공된 SDK 중 하나를 사용할 수 있습니다. AWS CLI에서 멀티파트 업로드를 사용하는 방법에 대한 자세한 내용은 [AWS CLI 사용](mpu-upload-object.md#UsingCLImpUpload) 단원을 참조하십시오. SDK에 대한 자세한 내용은 [AWS멀티파트 업로드에 대한 SDK 지원](mpuoverview.md#sdksupportformpu)을 참조하십시오.

## AWS SDK 사용
<a name="copy-object-mpu-sdks"></a>

하위 수준 API를 사용하여 객체를 복사하려면 다음을 수행합니다.
+ `AmazonS3Client.initiateMultipartUpload()` 메서드를 호출하여 멀티파트 업로드를 시작합니다.
+ `AmazonS3Client.initiateMultipartUpload()` 메서드가 반환하는 응답 객체에서 업로드 ID를 저장합니다. 이후의 각 파트 업로드 작업에서 이 업로드 ID를 제공합니다.
+ 모든 파트를 복사합니다. 복사해야 하는 각 파트에 대해 `CopyPartRequest` 클래스의 새 인스턴스를 생성합니다. 소스 및 대상 버킷 이름, 소스 및 대상 객체 키, 업로드 ID, 파트의 첫 번째 및 마지막 바이트 위치와 파트 번호 등과 같은 파트 정보를 제공합니다.
+ `AmazonS3Client.copyPart()` 메서드 호출에 대한 응답을 저장합니다. 각 응답에는 업로드된 파트의 파트 번호화 `ETag` 값이 포함되어 있습니다. 멀티파트 업로드를 완료하려면 이러한 정보가 필요합니다.
+ `AmazonS3Client.completeMultipartUpload()` 메서드를 호출하여 복사 작업을 완료합니다.

------
#### [ Java ]

AWS SDK for Java를 통해 멀티파트 업로드를 사용하여 객체를 복사하는 방법의 예는 *Amazon S3 API 참조*의 [Copy part of an object from another object](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_UploadPartCopy_section.html)를 참조하세요.

------
#### [ .NET ]

다음 C\$1 예제는 SDK for .NET을 사용하여 5GB보다 큰 Amazon S3 객체를 하나의 소스 위치에서 다른 위치(예: 한 버킷에서 다른 버킷으로)로 복사합니다. 5GB보다 작은 객체를 복사하려면 [AWS SDK 사용](copy-object.md#CopyingObjectsUsingSDKs)에 설명된 단일 작업 복사 프로시저를 사용하십시오. Amazon S3 멀티파트 업로드에 대한 자세한 내용은 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하세요.

이 예제에서는 SDK for .NET 멀티파트 업로드 API를 사용하여 S3 버킷 간에 5GB보다 큰 Amazon S3 객체를 복사하는 방법을 보여 줍니다.

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class CopyObjectUsingMPUapiTest
    {
        private const string sourceBucket = "*** provide the name of the bucket with source object ***";
        private const string targetBucket = "*** provide the name of the bucket to copy the object to ***";
        private const string sourceObjectKey = "*** provide the name of object to copy ***";
        private const string targetObjectKey = "*** provide the name of the object copy ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2; 
        private static IAmazonS3 s3Client;

        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            Console.WriteLine("Copying an object");
            MPUCopyObjectAsync().Wait();
        }
        private static async Task MPUCopyObjectAsync()
        {
            // Create a list to store the upload part responses.
            List<UploadPartResponse> uploadResponses = new List<UploadPartResponse>();
            List<CopyPartResponse> copyResponses = new List<CopyPartResponse>();

            // Setup information required to initiate the multipart upload.
            InitiateMultipartUploadRequest initiateRequest =
                new InitiateMultipartUploadRequest
                {
                    BucketName = targetBucket,
                    Key = targetObjectKey
                };

            // Initiate the upload.
            InitiateMultipartUploadResponse initResponse =
                await s3Client.InitiateMultipartUploadAsync(initiateRequest);

            // Save the upload ID.
            String uploadId = initResponse.UploadId;

            try
            {
                // Get the size of the object.
                GetObjectMetadataRequest metadataRequest = new GetObjectMetadataRequest
                {
                    BucketName = sourceBucket,
                    Key = sourceObjectKey
                };

                GetObjectMetadataResponse metadataResponse =
                    await s3Client.GetObjectMetadataAsync(metadataRequest);
                long objectSize = metadataResponse.ContentLength; // Length in bytes.

                // Copy the parts.
                long partSize = 5 * (long)Math.Pow(2, 20); // Part size is 5 MB.

                long bytePosition = 0;
                for (int i = 1; bytePosition < objectSize; i++)
                {
                    CopyPartRequest copyRequest = new CopyPartRequest
                    {
                        DestinationBucket = targetBucket,
                        DestinationKey = targetObjectKey,
                        SourceBucket = sourceBucket,
                        SourceKey = sourceObjectKey,
                        UploadId = uploadId,
                        FirstByte = bytePosition,
                        LastByte = bytePosition + partSize - 1 >= objectSize ? objectSize - 1 : bytePosition + partSize - 1,
                        PartNumber = i
                    };

                    copyResponses.Add(await s3Client.CopyPartAsync(copyRequest));

                    bytePosition += partSize;
                }

                // Set up to complete the copy.
                CompleteMultipartUploadRequest completeRequest =
                new CompleteMultipartUploadRequest
                {
                    BucketName = targetBucket,
                    Key = targetObjectKey,
                    UploadId = initResponse.UploadId
                };
                completeRequest.AddPartETags(copyResponses);

                // Complete the copy.
                CompleteMultipartUploadResponse completeUploadResponse = 
                    await s3Client.CompleteMultipartUploadAsync(completeRequest);
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }
    }
}
```

------

# 튜토리얼: 멀티파트 업로드를 통한 객체 업로드 및 데이터 무결성 확인
<a name="tutorial-s3-mpu-additional-checksums"></a>

 멀티파트 업로드를 사용하면 단일 객체를 여러 부분의 집합으로 업로드할 수 있습니다. 각 부분은 객체 데이터의 연속적인 부분입니다. 이러한 객체 부분은 독립적으로 그리고 임의의 순서로 업로드할 수 있습니다. 부분의 전송이 실패할 경우 다른 부분에 영향을 주지 않고도 해당 부분을 재전송할 수 있습니다. 객체의 모든 부분이 업로드되면 Amazon S3가 이들 부분을 수집하여 객체를 생성합니다. 일반적으로 객체 크기가 100MB에 근접할 경우, 단일 작업에서 객체를 업로드하는 대신 멀티파트 업로드 사용을 고려해 봐야 합니다. 멀티파트 업로드에 대한 자세한 내용은 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하십시오. 멀티파트 업로드와 관련된 제한은 [Amazon S3 멀티파트 업로드 제한](qfacts.md) 섹션을 참조하세요.

 체크섬을 사용하여 자산을 복사할 때 자산이 변경되지 않았는지 확인할 수 있습니다. 체크섬을 수행하는 것은 알고리즘을 사용하여 파일의 모든 바이트를 순차적으로 반복하는 작업으로 구성됩니다. Amazon S3는 데이터 무결성을 검사하기 위한 여러 체크섬 옵션을 제공합니다. 내구성 모범 사례로 이러한 무결성 검사를 수행하고 모든 바이트가 변경 없이 전송되는지 확인하는 것이 좋습니다. Amazon S3는 SHA-1, SHA-256, CRC32, CRC32C 등의 알고리즘도 지원합니다. Amazon S3는 이러한 알고리즘을 하나 이상 사용하여 추가 체크섬 값을 계산하고 객체 메타데이터의 일부로 저장합니다. 체크섬에 대한 자세한 내용은 [Amazon S3에서 객체 무결성 확인](checking-object-integrity.md) 섹션을 참조하십시오.

**목표**  
 이 튜토리얼에서는 AWS 명령줄 인터페이스(AWS CLI)를 통해 멀티파트 업로드 및 추가 SHA-256 체크섬을 사용하여 Amazon S3에 객체를 업로드하는 방법을 알아봅니다. 또한 업로드한 객체의 MD5 해시 및 SHA-256 체크섬을 계산하여 객체의 데이터 무결성을 검사하는 방법도 배우게 됩니다.

**Topics**
+ [사전 조건](#mpu-prerequisites)
+ [1단계: 대용량 파일 생성](#create-large-file-step1)
+ [2단계: 파일을 여러 파일로 분할](#split-large-file-step2)
+ [3단계: 추가 체크섬을 사용하여 멀티파트 업로드 생성](#create-multipart-upload-step3)
+ [4단계: 멀티파트 업로드의 부분 업로드](#upload-parts-step4)
+ [5단계: 멀티파트 업로드의 모든 부분 나열](#list-parts-step5)
+ [6단계: 멀티파트 업로드 완료](#complete-multipart-upload-step6)
+ [7단계: 객체가 버킷에 업로드되었는지 확인](#confirm-upload-step7)
+ [8단계: MD5 체크섬으로 객체 무결성 확인](#verify-object-integrity-step8)
+ [9단계: 추가 체크섬으로 객체 무결성 확인](#verify-object-integrity-sha256-step9)
+ [10단계: 리소스 정리](#clean-up-step10)

## 사전 조건
<a name="mpu-prerequisites"></a>
+ 이 튜토리얼을 시작하기 전에 업로드할 수 있는 Amazon S3 버킷에 대한 액세스 권한이 있는지 확인합니다. 자세한 내용은 [범용 버킷 생성](create-bucket-overview.md) 섹션을 참조하세요.
+  AWS CLI를 설치하고 구성해야 합니다. AWS CLI를 설치하지 않은 경우 *AWS Command Line Interface 사용 설명서*에서 [최신 버전의 AWS CLI 설치 또는 업데이트](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-install.html)를 참조하세요.
+ 또는 AWS CloudShell을 사용하여 콘솔에서 AWS CLI 명령을 실행할 수 있습니다. AWS CloudShell은 브라우저 기반의 사전 인증된 쉘로, AWS Management Console에서 직접 시작할 수 있습니다. 자세한 내용은 *AWS CloudShell 사용 설명서*에서 [CloudShell이란 무엇인가요?](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html) 및 [AWS CloudShell 시작하기](https://docs.aws.amazon.com//cloudshell/latest/userguide/getting-started.html)를 참조하세요.

## 1단계: 대용량 파일 생성
<a name="create-large-file-step1"></a>

업로드할 파일이 이미 있으면 이 튜토리얼에 해당 파일을 사용할 수 있습니다. 그렇지 않은 경우 다음 단계를 사용하여 15MB 파일을 생성합니다. 멀티파트 업로드와 관련된 제한은 [Amazon S3 멀티파트 업로드 제한](qfacts.md) 섹션을 참조하세요.

**대용량 파일을 생성하려면**

사용 중인 운영 체제에 따라 다음 명령 중 하나로 파일을 생성합니다.

**Linux 또는 macOS**  
15MB 파일을 생성하려면 로컬 터미널을 열고 다음 명령을 실행합니다.

```
dd if=/dev/urandom of=census-data.bin bs=1M count=15
```

이 명령은 크기가 15MB인 무작위 바이트로 채워진 `census-data.bin` 파일을 생성합니다.

**Windows**  
15MB 파일을 생성하려면 로컬 터미널을 열고 다음 명령을 실행합니다.

```
fsutil file createnew census-data.bin 15728640
```

이 명령은 크기가 15MB((15728640바이트)인 임의 데이터로 이루어진 `census-data.bin` 파일을 생성합니다.

## 2단계: 파일을 여러 파일로 분할
<a name="split-large-file-step2"></a>

멀티파트 업로드를 수행하려면 대용량 파일을 더 작은 부분으로 분할해야 합니다. 그런 다음 멀티파트 업로드 프로세스를 사용하여 작은 부분을 업로드할 수 있습니다. 이 단계에서는 [1단계](#create-large-file-step1)에서 생성한 대용량 파일을 작은 부분으로 분할하는 방법을 보여줍니다. 다음 예는 `census-data.bin`이라는 15MB 파일을 사용합니다.

**대용량 파일을 여러 부분으로 분할하려면**

**Linux 또는 macOS**  
대용량 파일을 5MB 부분으로 나누려면 `split` 명령을 사용합니다. 터미널을 열고 다음 명령을 실행합니다.

```
split -b 5M -d census-data.bin census-part
```

이 명령은 `census-data.bin`을 `census-part**`라는 5MB 부분으로 나뉩니다. 여기서 `**`는 `00`으로 시작하는 숫자 접미사입니다.

**Windows**  
대용량 파일을 분할하려면 PowerShell을 사용합니다. [PowerShell](https://learn.microsoft.com/en-us/powershell/)을 열고 다음 스크립트를 실행합니다.

```
$inputFile = "census-data.bin"
$outputFilePrefix = "census-part"
$chunkSize = 5MB

$fs = [System.IO.File]::OpenRead($inputFile)
$buffer = New-Object byte[] $chunkSize
$fileNumber = 0

while ($fs.Position -lt $fs.Length) {
$bytesRead = $fs.Read($buffer, 0, $chunkSize)
$outputFile = "{0}{1:D2}" -f $outputFilePrefix, $fileNumber
$fileStream = [System.IO.File]::Create($outputFile)
$fileStream.Write($buffer, 0, $bytesRead)
$fileStream.Close()
$fileNumber++
}

$fs.Close()
```

이 PowerShell 스크립트는 5MB 청크로 대용량 파일을 읽고 각 청크를 숫자 접미사가 있는 새 파일에 씁니다.

적절한 명령을 실행한 후에는 명령을 실행한 디렉터리에 해당 부분이 표시됩니다. 각 부분에는 부분 번호에 해당하는 접미사가 붙습니다. 예를 들면 다음과 같습니다.

```
census-part00 census-part01 census-part02
```

## 3단계: 추가 체크섬을 사용하여 멀티파트 업로드 생성
<a name="create-multipart-upload-step3"></a>

멀티파트 업로드 프로세스를 시작하려면 멀티파트 업로드 요청을 생성해야 합니다. 이 단계에는 멀티파트 업로드를 시작하고 데이터 무결성을 위한 추가 체크섬을 지정하는 작업이 포함됩니다. 다음 예에서는 SHA-256 체크섬을 사용합니다. 업로드할 객체에 메타데이터를 제공하려는 경우 멀티파트 업로드 시작 요청에서 메타데이터를 제공해야 합니다.

**참고**  
이 단계와 후속 단계에서 이 튜토리얼은 SHA-256 추가 알고리즘을 사용합니다. 필요에 따라 이러한 단계에 CRC32, CRC32C 또는 SHA-1을 비롯한 다른 추가 체크섬을 사용할 수도 있습니다. 다른 알고리즘을 사용하는 경우 튜토리얼 단계 전체에서 사용해야 합니다.

**멀티파트 업로드를 시작하려면**

터미널에서 다음 `create-multipart-upload` 명령을 사용하여 버킷의 멀티파트 업로드를 시작합니다. `amzn-s3-demo-bucket1`을 실제 버킷 이름으로 대체합니다. 또한 `census_data_file`을 선택한 파일 이름으로 바꿉니다. 업로드가 완료되면 이 파일 이름이 객체 키가 됩니다.

```
aws s3api create-multipart-upload --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --checksum-algorithm sha256
```

요청이 성공하면 다음과 같은 JSON 결과가 표시됩니다.

```
{
    "ServerSideEncryption": "AES256",
    "ChecksumAlgorithm": "SHA256",
    "Bucket": "amzn-s3-demo-bucket1",
    "Key": "census_data_file",
    "UploadId": "cNV6KCSNANFZapz1LUGPC5XwUVi1n6yUoIeSP138sNOKPeMhpKQRrbT9k0ePmgoOTCj9K83T4e2Gb5hQvNoNpCKqyb8m3.oyYgQNZD6FNJLBZluOIUyRE.qM5yhDTdhz"
}
```

**참고**  
멀티파트 업로드 시작 요청을 전송하면 Amazon S3는 멀티파트 업로드에 대한 고유 식별자인 업로드 ID와 함께 응답을 반환합니다. 부분 업로드, 부분 목록 확인, 업로드 완료 또는 업로드 중단 요청 시 항상 이 업로드 ID를 포함해야 합니다. 이후 단계에서 `UploadId`, `Key`, `Bucket` 값을 사용해야 하므로 이러한 값을 저장해 둡니다.  
추가 체크섬과 함께 멀티파트 업로드를 사용하는 경우 부분 번호는 연속된 번호여야 합니다. 연속되지 않은 부분 번호를 사용하는 경우 `complete-multipart-upload` 요청에서 HTTP `500 Internal Server Error`가 반환될 수 있습니다.

## 4단계: 멀티파트 업로드의 부분 업로드
<a name="upload-parts-step4"></a>

이 단계에서는 S3 버킷에 멀티파트 업로드의 부분들을 업로드합니다. `upload-part` 명령을 사용하여 각 부분을 개별적으로 업로드합니다. 이 프로세스를 수행하려면 업로드 ID, 부분 번호, 각 부분에 업로드할 파일을 지정해야 합니다.

**부분을 업로드하려면**

1. 부분을 업로드할 때 업로드 ID와 함께 `--part-number` 인수를 사용하여 부분 번호를 지정해야 합니다. 1부터 10,000까지 부분 번호를 지정할 수 있습니다. 부분 번호를 사용하여 업로드하는 객체에서 각 부분과 그 위치를 고유하게 식별합니다. 부분 번호는 연속 시퀀스로 선택해야 합니다(예: 1, 2 또는 3일 수 있음). 이전에 업로드한 부분과 동일한 부분 번호로 새 부분을 업로드할 경우 이전에 업로드한 부분을 덮어쓰게 됩니다.

1. `upload-part` 명령을 사용하여 멀티파트 업로드의 각 부분을 업로드합니다. `--upload-id`는 [3단계](#create-multipart-upload-step3)에서 `create-multipart-upload` 명령으로 생성된 출력과 동일합니다. 데이터의 첫 부분을 업로드하려면 다음 명령을 사용합니다.

   ```
   aws s3api upload-part --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --part-number 1 --body census-part00 --upload-id "cNV6KCSNANFZapz1LUGPC5XwUVi1n6yUoIeSP138sNOKPeMhpKQRrbT9k0ePmgoOTCj9K83T4e2Gb5hQvNoNpCKqyb8m3.oyYgQNZD6FNJLBZluOIUyRE.qM5yhDTdhz" --checksum-algorithm SHA256
   ```

   각 `upload-part` 명령을 완료하면 다음 예와 같은 출력이 표시됩니다.

   ```
   {
       "ServerSideEncryption": "AES256",
       "ETag": "\"e611693805e812ef37f96c9937605e69\"",
       "ChecksumSHA256": "QLl8R4i4+SaJlrl8ZIcutc5TbZtwt2NwB8lTXkd3GH0="
   }
   ```

1. 후속 부분의 경우 부분 번호를 적절히 증가시킵니다.

   ```
   aws s3api upload-part --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --part-number <part-number> --body <file-path> --upload-id "<your-upload-id>" --checksum-algorithm SHA256
   ```

   예를 들어, 다음 명령을 사용하여 두 번째 부분을 업로드합니다.

   ```
   aws s3api upload-part --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --part-number 2 --body census-part01 --upload-id "cNV6KCSNANFZapz1LUGPC5XwUVi1n6yUoIeSP138sNOKPeMhpKQRrbT9k0ePmgoOTCj9K83T4e2Gb5hQvNoNpCKqyb8m3.oyYgQNZD6FNJLBZluOIUyRE.qM5yhDTdhz" --checksum-algorithm SHA256
   ```

   Amazon S3는 업로드된 각 부분에 대한 엔터티 태그(ETag)와 추가 체크섬을 응답의 헤더로 반환합니다.

1. 객체의 모든 부분을 업로드할 때까지 `upload-part` 명령을 계속 사용합니다.

## 5단계: 멀티파트 업로드의 모든 부분 나열
<a name="list-parts-step5"></a>

멀티파트 업로드를 완료하려면 해당 멀티파트 업로드를 위해 업로드된 모든 부분의 목록이 필요합니다. `list-parts` 명령의 출력에는 버킷 이름, 키, 업로드 ID, 파트 번호, ETag, 추가 체크섬 등과 같은 정보가 제공됩니다. 멀티파트 업로드 프로세스를 완료할 때 다음 단계에서 사용할 수 있도록 이 출력을 파일에 저장하는 것이 좋습니다. 다음 방법을 사용하여 `parts.json`이라는 JSON 출력 파일을 생성할 수 있습니다.

**모든 부분이 나열된 파일을 생성하려면**

1. 업로드된 모든 부분의 세부 정보가 포함된 JSON 파일을 생성하려면 다음 `list-parts` 명령을 사용합니다. ***amzn-s3-demo-bucket1***을 실제 버킷 이름 및 **<your-upload-id>**([3단계](#create-multipart-upload-step3)에서 받은 업로드 ID)로 바꿉니다 `list-parts` 명령에 대한 자세한 내용은 *AWS Command Line Interface 사용 설명서*의 [https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html)를 참조하세요.

   ```
   aws s3api list-parts --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --upload-id <your-upload-id> --query '{Parts: Parts[*].{PartNumber: PartNumber, ETag: ETag, ChecksumSHA256: ChecksumSHA256}}' --output json > parts.json
   ```

   `parts.json`이라는 새 파일이 생성됩니다. 이 파일에는 업로드한 모든 부분에 대한 JSON 형식의 정보가 들어 있습니다. `parts.json` 파일에는 멀티파트 업로드 프로세스를 완료하는 데 필요한 부분 번호, 해당 ETag 값 등 멀티파트 업로드의 각 부분에 대한 필수 정보가 포함되어 있습니다.

1. 텍스트 편집기를 사용하거나 터미널을 통해 `parts.json`을 열 수 있습니다. 예시 출력은 다음과 같습니다.

   ```
   {
       "Parts": [
           {
               "PartNumber": 1,
               "ETag": "\"3c3097f89e2a2fece47ac54b243c9d97\"",
               "ChecksumSHA256": "fTPVHfyNHdv5VkR4S3EewdyioXECv7JBxN+d4FXYYTw="
           },
           {
               "PartNumber": 2,
               "ETag": "\"03c71cc160261b20ab74f6d2c476b450\"",
               "ChecksumSHA256": "VDWTa8enjOvULBAO3W2a6C+5/7ZnNjrnLApa1QVc3FE="
           },
           {
               "PartNumber": 3,
               "ETag": "\"81ae0937404429a97967dffa7eb4affb\"",
               "ChecksumSHA256": "cVVkXehUlzcwrBrXgPIM+EKQXPUvWist8mlUTCs4bg8="
           }
       ]
   }
   ```

## 6단계: 멀티파트 업로드 완료
<a name="complete-multipart-upload-step6"></a>

멀티파트 업로드의 모든 부분을 업로드하고 나열한 후, 마지막 단계는 멀티파트 업로드를 완료하는 것입니다. 이 단계는 업로드된 모든 부분을 S3 버킷의 단일 객체로 병합합니다.

**참고**  
요청에 `--checksum-sha256`을 포함하여 `complete-multipart-upload`를 직접적으로 호출하기 전에 객체 체크섬을 계산할 수 있습니다. 체크섬이 일치하지 않으면 Amazon S3가 요청에 실패합니다. 자세한 내용은 AWS Command Line Interface 사용 설명서**의 [https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html)를 참조하세요.

**멀티파트 업로드를 완료하려면**

멀티파트 업로드를 완료하려면 `complete-multipart-upload` 명령을 사용합니다. 이 명령에는 [5단계](#list-parts-step5)에서 생성한 `parts.json` 파일, 버킷 이름, 업로드 ID가 필요합니다. **<*amzn-s3-demo-bucket1*>**을 해당 버킷 이름으로 바꾸고 **<your-upload-id>**를 `parts.json`의 업로드 ID로 바꿉니다.

```
aws s3api complete-multipart-upload --multipart-upload file://parts.json --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --upload-id <your-upload-id>
```

예시 출력은 다음과 같습니다.

```
{
    "ServerSideEncryption": "AES256",
    "Location": "https://amzn-s3-demo-bucket1.s3.us-east-2.amazonaws.com/census_data_file",
    "Bucket": "amzn-s3-demo-bucket1",
    "Key": "census_data_file",
    "ETag": "\"f453c6dccca969c457efdf9b1361e291-3\"",
    "ChecksumSHA256": "aI8EoktCdotjU8Bq46DrPCxQCGuGcPIhJ51noWs6hvk=-3"
}
```

**참고**  
개별 부분 파일은 아직 삭제하지 마세요. 함께 병합된 객체의 무결성을 확인하기 위해 해당 부분에 대해 체크섬을 수행하려면 개별 부분이 필요합니다.

## 7단계: 객체가 버킷에 업로드되었는지 확인
<a name="confirm-upload-step7"></a>

멀티파트 업로드를 완료한 후 객체가 S3 버킷에 성공적으로 업로드되었는지 확인할 수 있습니다. 버킷의 객체를 나열하고 새로 업로드한 파일이 있는지 확인하려면 `list-objects-v2` 명령을 사용합니다.

**업로드된 객체를 나열하려면**

버킷의 객체를 나열하려면 `list-objects-v2` 명령을 사용합니다. ***amzn-s3-demo-bucket1***을 실제 버킷 이름으로 바꿉니다.

```
aws s3api list-objects-v2 --bucket amzn-s3-demo-bucket1
```

이 명령은 버킷의 객체 목록을 반환합니다. 객체 목록에서 업로드한 파일(예:`census_data_file`)을 찾아보세요.

자세한 내용은 *AWS Command Line Interface 사용 설명서*에서 `list-objects-v2` 명령에 대한 [예제](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-objects-v2.html) 섹션을 참조하세요.

## 8단계: MD5 체크섬으로 객체 무결성 확인
<a name="verify-object-integrity-step8"></a>

객체를 업로드할 때 Amazon S3에서 사용할 체크섬 알고리즘을 지정할 수 있습니다. 기본적으로 Amazon S3는 MD5 바이트 다이제스트를 객체의 ETag로 저장합니다. 멀티파트 업로드의 경우 ETag는 전체 객체의 체크섬이 아니라 각 개별 부분에 대한 체크섬의 복합체입니다.

**MD5 체크섬을 사용하여 객체 무결성을 확인하려면**

1. 업로드된 객체의 ETag를 검색하려면 `head-object` 요청을 수행합니다.

   ```
   aws s3api head-object --bucket amzn-s3-demo-bucket1 --key census_data_file
   ```

   예시 출력은 다음과 같습니다.

   ```
   {
       "AcceptRanges": "bytes",
       "LastModified": "2024-07-26T19:04:13+00:00",
       "ContentLength": 16106127360,
       "ETag": "\"f453c6dccca969c457efdf9b1361e291-3\"",
       "ContentType": "binary/octet-stream",
       "ServerSideEncryption": "AES256",
       "Metadata": {}
   }
   ```

   이 ETag의 끝에는 ‘-3’이 추가되어 있습니다. 이는 멀티파트 업로드를 사용하여 객체가 세 부분으로 업로드되었음을 나타냅니다.

1. 그런 다음 `md5sum` 명령을 사용하여 각 부분의 MD5 체크섬을 계산합니다. 부분 파일에 올바른 경로를 입력했는지 확인합니다.

   ```
   md5sum census-part*
   ```

   예시 출력은 다음과 같습니다.

   ```
   e611693805e812ef37f96c9937605e69 census-part00
   63d2d5da159178785bfd6b6a5c635854 census-part01
   95b87c7db852451bb38b3b44a4e6d310 census-part02
   ```

1. 이 단계에서는 MD5 해시를 수동으로 하나의 문자열로 결합합니다. 그러고 나서 다음 명령을 실행하여 문자열을 바이너리로 변환하고 바이너리 값의 MD5 체크섬을 계산합니다.

   ```
   echo "e611693805e812ef37f96c9937605e6963d2d5da159178785bfd6b6a5c63585495b87c7db852451bb38b3b44a4e6d310" | xxd -r -p | md5sum
   ```

   예시 출력은 다음과 같습니다.

   ```
   f453c6dccca969c457efdf9b1361e291 -
   ```

   이 해시 값은 `census_data_file` 객체의 무결성을 검증하는 [1단계](#create-large-file-step1)의 원래 ETag 값의 해시 값과 일치해야 합니다.

Amazon S3에게 추가 체크섬을 사용하도록 하면 Amazon S3가 각 부분에 대한 체크섬 값을 계산하고 저장합니다. 아직 진행 중인 멀티파트 업로드의 개별 부분에 대한 체크섬 값을 검색하려면 `list-parts`를 사용하면 됩니다.

멀티파트 업로드 객체를 통한 체크섬 작업에 대한 자세한 내용은 [Amazon S3에서 객체 무결성 확인](checking-object-integrity.md) 섹션을 참조하세요.

## 9단계: 추가 체크섬으로 객체 무결성 확인
<a name="verify-object-integrity-sha256-step9"></a>

이 단계에서 이 튜토리얼은 SHA-256을 추가 체크섬으로 사용하여 객체 무결성을 검증합니다. 다른 추가 체크섬을 사용한 경우 해당 체크섬 값을 대신 사용하세요.

**SHA256을 사용하여 객체 무결성을 확인하려면**

1. 터미널에서 `--checksum-mode enabled` 인수를 포함해 다음 명령을 실행하여 객체의 `ChecksumSHA256` 값을 표시합니다.

   ```
   aws s3api head-object --bucket amzn-s3-demo-bucket1 --key census_data_file --checksum-mode enabled
   ```

   예시 출력은 다음과 같습니다.

   ```
   {
       "AcceptRanges": "bytes",
       "LastModified": "2024-07-26T19:04:13+00:00",
       "ContentLength": 16106127360,
       "ChecksumSHA256": "aI8EoktCdotjU8Bq46DrPCxQCGuGcPIhJ51noWs6hvk=-3",
       "ETag": "\"f453c6dccca969c457efdf9b1361e291-3\"",
       "ContentType": "binary/octet-stream",
       "ServerSideEncryption": "AES256",
       "Metadata": {}
   }
   ```

1. 다음 명령을 사용하여 개별 부분의 `ChecksumSHA256` 값을 base64로 디코딩하고 `outfile`이라는 바이너리 파일에 저장합니다. 이러한 값은 `parts.json` 파일에서 찾을 수 있습니다. 예제 base64 문자열을 실제 `ChecksumSHA256` 값으로 바꿉니다.

   ```
   echo "QLl8R4i4+SaJlrl8ZIcutc5TbZtwt2NwB8lTXkd3GH0=" | base64 --decode >> outfile
   echo "xCdgs1K5Bm4jWETYw/CmGYr+m6O2DcGfpckx5NVokvE=" | base64 --decode >> outfile
   echo "f5wsfsa5bB+yXuwzqG1Bst91uYneqGD3CCidpb54mAo=" | base64 --decode >> outfile
   ```

1. 다음 명령을 실행하여 `outfile`의 SHA256 체크섬을 계산합니다.

   ```
   sha256sum outfile
   ```

   예시 출력은 다음과 같습니다.

   ```
   688f04a24b42768b6353c06ae3a0eb3c2c50086b8670f221279d67a16b3a86f9 outfile
   ```

   다음 단계에서는 해시 값을 가져와 이진 값으로 변환합니다. 이 이진 값은 [1단계](#create-large-file-step1)의 `ChecksumSHA256` 값과 일치해야 합니다.

1. [3단계](#create-multipart-upload-step3)의 SHA256 체크섬을 이진수로 변환한 다음 base64로 인코딩하여 [1단계](#create-large-file-step1)의 `ChecksumSHA256` 값과 일치하는지 확인합니다.

   ```
   echo "688f04a24b42768b6353c06ae3a0eb3c2c50086b8670f221279d67a16b3a86f9" | xxd -r -p | base64
   ```

   예시 출력은 다음과 같습니다.

   ```
   aI8EoktCdotjU8Bq46DrPCxQCGuGcPIhJ51noWs6hvk=
   ```

   이 출력은 base64 출력이 `head-object` 명령 출력의 `ChecksumSHA256` 값과 일치하는지 확인합니다. 출력이 체크섬 값과 일치하면 객체가 유효합니다.

**중요**  
Amazon S3에게 추가 체크섬을 사용하도록 하면 Amazon S3가 각 부분에 대한 체크섬 값을 계산하고 저장합니다.
아직 진행 중인 멀티파트 업로드의 개별 부분에 대한 체크섬 값을 검색하려면 `list-parts` 명령을 사용하면 됩니다.

## 10단계: 리소스 정리
<a name="clean-up-step10"></a>

이 튜토리얼에서 생성된 파일을 정리하려면 다음 방법을 사용합니다. S3 버킷에 업로드된 파일을 삭제하는 방법에 대한 지침은 [Amazon S3 객체 삭제](DeletingObjects.md) 섹션을 참조하세요.

**[1단계](#create-large-file-step1)에서 생성한 로컬 파일 삭제:**

멀티파트 업로드를 위해 생성한 파일을 제거하려면 작업 디렉터리에서 다음 명령을 실행합니다.

```
rm census-data.bin census-part* outfile parts.json
```

# Amazon S3 멀티파트 업로드 제한
<a name="qfacts"></a>

멀티파트 업로드를 사용하면 단일 객체를 여러 부분의 집합으로 업로드할 수 있습니다. 각 부분은 객체 데이터의 연속적인 부분입니다. 객체의 모든 부분이 업로드되면 Amazon S3가 이들 부분을 수집하여 객체를 생성합니다. 일반적으로 객체 크기가 100MB에 근접할 경우, 단일 작업에서 객체를 업로드하는 대신 멀티파트 업로드 사용을 고려해 봐야 합니다. 멀티파트 업로드에 대한 자세한 내용은 [Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사](mpuoverview.md) 섹션을 참조하십시오.

다음 표에 멀티파트 업로드의 주요 사양이 나와 있습니다. 여기에는 최대 객체 크기, 최대 부분 수, 최대 부분 크기 등이 포함됩니다. 멀티파트 업로드의 마지막 부분에는 최소 크기 제한이 없습니다.


| 항목 | 사양 | 
| --- | --- | 
| 최대 객체 크기 | 48.8TiB  | 
| 업로드당 최대 파트 개수 | 10,000개 | 
| 부분 번호 | 1 \$1 10,000(포함) | 
| 부분 크기 | 5MiB\$15GiB. 멀티파트 업로드의 마지막 부분에는 최소 크기 제한이 없습니다. | 
| 부분 목록 조회 요청에 대해 반환되는 최대 부분 개수 | 1000  | 
| 멀티파트 업로드 나열 요청에서 반환되는 최대 멀티파트 업로드 개수 | 1000  | 