조건부 쓰기를 통해 객체 덮어쓰기를 방지하는 방법 - Amazon Simple Storage Service

조건부 쓰기를 통해 객체 덮어쓰기를 방지하는 방법

조건부 쓰기를 사용하면 쓰기 요청에 헤더를 추가하여 S3 작업에 사전 조건을 지정할 수 있습니다. 이렇게 하면 버킷에 이미 같은 키 이름을 가진 기존 객체가 없는지 확인하여 기존 데이터를 덮어쓰지 않도록 방지할 수 있습니다. 조건부 쓰기는 범용 버킷과 디렉터리 버킷에 대한 API 요청을 대상으로 작동합니다.

Amazon S3에 객체를 업로드할 때 키 이름을 지정합니다. 키 이름은 버킷에 있는 객체의 고유한 대소문자 구분 식별자입니다. 버전이 지정되지 않았거나 버전이 일시 중단된 버킷에 동일한 키 이름을 가진 객체를 업로드하면 해당 객체가 덮어쓰여집니다. 버전이 지정된 버킷에서는 가장 최근에 업로드한 객체가 최신 버전이 됩니다.

조건부 쓰기는 WRITE 작업 중에 객체의 존재 여부를 확인합니다. 버킷에 동일한 키 이름이 있는 경우 WRITE 작업이 실패합니다. 조건부 쓰기를 사용하면 기존 객체를 덮어쓸 가능성 없이 여러 클라이언트가 동일한 버킷에 쓰도록 할 수 있습니다.

조건부 쓰기를 수행하려면 s3:PutObject 권한이 있어야 합니다. 이 권한을 통해 호출자는 버킷에 객체가 있는지 확인할 수 있습니다. AWS SDK에서 미리 서명된 URL과 함께 조건부 쓰기를 사용할 수 있습니다.

참고

조건부 쓰기를 사용하려면 HTTPS(TLS)를 통해 요청을 수행하거나 AWS Signature Version 4를 사용하여 요청에 서명해야 합니다.

지원되는 API

다음 S3 API는 조건부 쓰기 사용을 지원합니다.

다음 헤더를 사용하여 객체 키 이름에 따라 객체를 쓸 수 있습니다. 객체 키 이름에 대한 정보는 Amazon S3 객체 이름 지정 섹션을 참조하세요.

PutObject

  • If-None-Match - 지정된 버킷에 동일한 키 이름을 가진 기존 객체가 이미 없는 경우에만 객체를 업로드합니다. 이 파라미터에는 *(별표) 값을 사용해야 합니다.

다음 put-object 예제 명령은 AWS CLI를 통해 if-none-match 파라미터를 사용하여 조건부 쓰기 헤더가 있는 객체를 업로드하는 방법을 보여줍니다.

aws s3api put-object --bucket amzn-s3-demo-bucket --key dir-1/my_images.tar.bz2 --body my_images.tar.bz2 --if-none-match "*"

자세한 정보는 AWS CLI 명령 참조put-object 섹션을 참조하세요.

AWS CLI에 대한 자세한 내용은 AWS Command Line Interface 사용 설명서AWS Command Line Interface란 무엇입니까?를 참조하세요.

이 헤더에 대한 자세한 내용은 Amazon Simple Storage Service API 참조의 PutObject 섹션을 참조하세요.

CompleteMultipartUpload

  • If-None-Match - 지정된 버킷에 동일한 키 이름을 가진 기존 객체가 이미 없는 경우에만 업로드를 완료합니다. 이 파라미터에는 *(별표) 값을 사용해야 합니다.

다음 complete-multipart-upload 예제 명령은 AWS CLI를 통해 if-none-match 파라미터를 사용하여 조건부 쓰기 헤더가 있는 멀티파트 업로드를 완료하는 방법을 보여줍니다.

aws s3api complete-multipart-upload --multipart-upload file://mpustruct --bucket amzn-s3-demo-bucket --key dir-1/my_images.tar.bz2 --upload-id uploadID --if-none-match "*"

자세한 정보는 AWS CLI 명령 참조complete-multipart-upload 섹션을 참조하세요.

AWS CLI에 대한 자세한 내용은 AWS Command Line Interface 사용 설명서AWS Command Line Interface란 무엇입니까?를 참조하세요.

이 헤더에 대한 자세한 내용은 Amazon Simple Storage Service API 참조의 CompleteMultipartUpload 섹션을 참조하세요.

조건부 쓰기 동작

조건부 쓰기는 버킷의 기존 객체를 기준으로 평가합니다. 버킷에 동일한 키 이름을 가진 기존 객체가 없는 경우 쓰기 작업이 성공하여 200 응답이 반환됩니다. 기존 객체가 있는 경우 쓰기 작업이 실패하여 412 Precondition Failed 응답이 반환됩니다. 버전 관리가 활성화된 버킷의 경우 S3는 조건부 평가의 일환으로 이름이 같은 현재 객체 버전이 있는지 확인합니다. 이름이 같은 현재 객체 버전이 없거나 현재 객체 버전이 삭제 마커인 경우 쓰기 작업이 성공합니다. 그렇지 않으면 412 Precondition Failed 응답과 함께 쓰기 작업이 실패하게 됩니다.

동일한 객체 이름에 대해 조건부 쓰기가 여러 번 발생하는 경우 가장 먼저 완료되는 쓰기 작업이 성공합니다. 그러면 Amazon S3는 412 Precondition Failed 응답과 함께 후속 쓰기에 실패합니다.

요청이 동시에 발생하는 경우에도 객체에 대한 조건부 쓰기 작업이 완료되기 전에 객체에 대한 삭제 요청이 성공하면 409 Conflict 응답이 반환될 수 있습니다. 삭제 요청이 이전에 시작된 조건부 쓰기 작업보다 우선하기 때문입니다. PutObject와 함께 조건부 쓰기를 사용하는 경우 409 오류가 발생한 후 업로드가 재시도될 수 있습니다. CompleteMultipartUpload를 사용하는 경우 409 오류가 발생한 후 객체를 다시 업로드하려면 CreateMultipartUpload로 멀티파트 업로드를 다시 시작해야 합니다.

두 클라이언트가 같은 버킷에서 작업을 실행하는 다음 시나리오를 생각해 보세요.

412 Precondition Failed 응답

진행 중인 멀티파트 업로드 요청은 아직 완전히 쓴 객체가 아니므로 조건부 쓰기는 진행 중인 멀티파트 업로드 요청을 고려하지 않습니다. 클라이언트 1이 멀티파트 업로드를 사용하여 객체를 업로드하는 다음 예를 살펴보세요. 멀티파트 업로드 중에 클라이언트 2는 조건부 쓰기 작업을 통해 동일한 객체를 성공적으로 쓸 수 있습니다. 이후 클라이언트 1이 조건부 쓰기를 사용하여 멀티파트 업로드를 완료하려고 하면 객체가 이미 존재하므로 업로드가 실패합니다.

동일한 키 이름으로 항목을 쓰는 두 클라이언트의 예시입니다. 하나는 MPU용 UploadPart를 사용하고 다른 하나는 PutObject와 조건부 쓰기를 사용합니다. 이후에 시작되는 CompleteMultipartUpload 작업은 실패합니다.
409 Conflict 응답

조건부 쓰기 요청이 완료되기 전에 삭제 요청이 성공하면 Amazon S3는 쓰기 작업에 대한 409 Conflict 응답을 반환합니다. 이전에 시작된 삭제 요청이 조건부 쓰기 작업보다 우선하기 때문입니다. puppy.txt 파일이 버킷에 있는 다음 예를 살펴보세요. 클라이언트 1은 조건부 쓰기로 멀티파트 업로드를 완료하기 위해 puppy.txt라는 동일한 이름을 가진 다른 파일의 멀티파트 업로드를 시작합니다. 업로드 중에 클라이언트 2는 버킷에서 puppy.txt를 삭제합니다. 클라이언트 1이 CompleteMultipartUpload를 사용하여 조건부 쓰기로 자체 puppy.txt 파일을 업로드하려고 하면 409 Conflict 응답과 함께 실패합니다. 이 경우 새 멀티파트 업로드를 시작해야 합니다.

멀티파트 업로드를 사용하는 클라이언트와 MPU가 시작된 후 삭제 요청을 보내는 클라이언트 두 개의 예입니다. 조건부 쓰기가 시작되기 전에 삭제 요청이 완료됩니다.
참고

스토리지 비용을 최소화하려면 AbortIncompleteMultipartUpload 작업을 사용하여 특정 기간이 지나면 불완전한 멀티파트 업로드를 삭제하는 수명 주기 규칙을 구성하는 것이 좋습니다. 불완전한 멀티파트 업로드를 삭제하기 위한 수명 주기 규칙을 만드는 방법과 관련하여 자세한 내용은 불완전한 멀티파트 업로드를 삭제하도록 버킷 수명 주기 구성 설정을 참조하십시오.