S3 파일 삭제 복구: 버전 관리로 이전 버전 찾고 되살리기

S3에서 파일을 실수로 삭제했을 때, 버킷에 버전 관리(Versioning)가 활성화되어 있었다면 데이터는 실제로 사라진 게 아니다. AWS S3 버전 관리는 삭제 작업을 '삭제 마커(Delete Marker)' 삽입으로 처리하기 때문에, 이전 버전 객체는 여전히 스토리지에 남아 있다. 이 글은 그 버전을 찾아서 복원하는 정확한 절차를 다룬다.

TL;DR — S3 삭제 복구 핵심 요약

단계작업핵심 포인트
1버전 목록 조회list-object-versions로 삭제 마커와 이전 버전 확인
2삭제 마커 제거삭제 마커의 VersionId를 지정해 delete-object 실행
3복원 검증head-object로 객체 접근 가능 여부 확인
대안특정 버전 복사원하는 VersionIdcopy-object로 현재 버전으로 승격

S3 버전 관리가 삭제를 처리하는 방식

버전 관리가 활성화된 버킷에서 aws s3 rm 또는 DeleteObject API를 VersionId 없이 호출하면, S3는 해당 객체를 물리적으로 제거하지 않는다. 대신 동일한 키(Key)에 '삭제 마커'라는 특수 버전을 추가한다. 이후 일반적인 GetObject 요청은 405 Method Not Allowed가 아닌 404 NoSuchKey를 반환하는데, 이게 실제 삭제처럼 보이는 이유다.

삭제 마커 자체도 고유한 VersionId를 가진다. 이 마커를 제거하면 이전 버전이 다시 '현재 버전'으로 노출된다. 즉, 복원의 핵심은 데이터를 되살리는 게 아니라 삭제 마커를 지우는 것이다.

sequenceDiagram participant User as 사용자 participant S3 as S3 버킷 Note over S3: 버전 관리 활성화 User->>S3: PutObject (file.txt) S3-->>User: VersionId: v1 User->>S3: PutObject (file.txt 수정) S3-->>User: VersionId: v2 (현재 버전) User->>S3: DeleteObject (VersionId 없음) S3-->>User: 삭제 마커 생성 (VersionId: dm1) Note over S3: v1, v2 데이터 보존 User->>S3: GetObject (file.txt) S3-->>User: 404 NoSuchKey User->>S3: DeleteObject (VersionId: dm1) Note over S3: 삭제 마커 제거 S3-->>User: v2가 현재 버전으로 승격 User->>S3: GetObject (file.txt) S3-->>User: 200 OK (v2 반환)
  1. 정상 상태: 버전 관리 활성화 버킷에 객체 v1, v2가 존재하며 v2가 현재 버전.
  2. 삭제 요청 (VersionId 없음): S3는 삭제 마커(DM)를 최신 버전으로 삽입. v1, v2는 스토리지에 그대로 유지.
  3. GetObject 요청: 현재 버전이 삭제 마커이므로 404 반환. 데이터는 존재하지만 접근 불가.
  4. 복원 (삭제 마커 제거): 삭제 마커의 VersionId를 지정해 삭제하면 v2가 다시 현재 버전이 됨.

사전 조건 확인: 버전 관리 활성화 여부

복원을 시도하기 전에 해당 버킷의 버전 관리 상태를 확인한다. 버전 관리가 한 번도 활성화된 적 없는 버킷이라면 삭제된 객체는 복구 불가능하다.

aws s3api get-bucket-versioning \
  --bucket your-bucket-name

응답에서 "Status": "Enabled"가 확인되어야 한다. Suspended 상태라면 버전 관리가 일시 중단된 것으로, 중단 이전에 업로드된 버전은 여전히 존재할 수 있다.

S3 삭제 파일 복구: 단계별 절차

1단계: 삭제된 객체의 버전 목록 조회

삭제 마커와 이전 버전을 모두 확인한다. list-object-versions는 현재 버전뿐 아니라 모든 히스토리를 반환하기 때문에, 일반 list-objects로는 보이지 않는 삭제 마커도 여기서 확인할 수 있다.

aws s3api list-object-versions \
  --bucket your-bucket-name \
  --prefix path/to/your-file.txt

출력 예시:

🔽 응답 JSON 예시 펼치기
{
    "Versions": [
        {
            "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
            "Size": 1024,
            "StorageClass": "STANDARD",
            "Key": "path/to/your-file.txt",
            "VersionId": "abc123XYZ_previousVersion",
            "IsLatest": false,
            "LastModified": "2024-01-10T09:00:00.000Z"
        }
    ],
    "DeleteMarkers": [
        {
            "Owner": { "DisplayName": "myaccount" },
            "Key": "path/to/your-file.txt",
            "VersionId": "def456UVW_deleteMarker",
            "IsLatest": true,
            "LastModified": "2024-01-15T14:30:00.000Z"
        }
    ]
}

DeleteMarkers 배열에서 IsLatest: true인 항목의 VersionId를 메모한다. Versions 배열에서 복원하려는 버전의 VersionId도 함께 확인한다.

2단계: 삭제 마커 제거 (권장 복원 방법)

삭제 마커의 VersionId를 명시적으로 지정해 삭제한다. VersionId를 지정하지 않으면 새로운 삭제 마커가 또 생성된다는 점이 가장 흔한 실수다.

aws s3api delete-object \
  --bucket your-bucket-name \
  --key path/to/your-file.txt \
  --version-id def456UVW_deleteMarker

이 명령이 성공하면 직전 버전(abc123XYZ_previousVersion)이 자동으로 현재 버전으로 승격된다. 추가 복사 작업 없이 즉시 접근 가능해진다.

3단계: 복원 검증

삭제 마커 제거 후 객체가 실제로 접근 가능한지 확인한다. head-object는 데이터를 다운로드하지 않고 메타데이터만 조회하므로 빠른 검증에 적합하다.

aws s3api head-object \
  --bucket your-bucket-name \
  --key path/to/your-file.txt

200 OK와 함께 ContentLength, LastModified 등이 반환되면 복원 완료다. 여전히 404가 반환된다면 1단계로 돌아가 삭제 마커가 완전히 제거됐는지 재확인한다.

대안: 특정 이전 버전을 현재 버전으로 복원

삭제 마커 제거로 복원되는 버전이 원하는 버전이 아닐 수 있다. 예를 들어, 파일을 잘못 수정한 후 삭제된 경우라면 삭제 직전 버전보다 더 이전 버전이 필요할 수 있다. 이 경우 원하는 버전을 동일한 키로 복사해 현재 버전으로 만든다.

aws s3api copy-object \
  --bucket your-bucket-name \
  --copy-source your-bucket-name/path/to/your-file.txt?versionId=abc123XYZ_previousVersion \
  --key path/to/your-file.txt

이 작업은 지정한 버전의 내용을 가진 새로운 버전을 생성한다. 기존 버전 히스토리는 그대로 유지되며, 새 버전이 현재 버전이 된다.

버전 관리 버킷에서의 복원은 '타임머신'이 아니라 '현재 뷰 변경'에 가깝다. 이전 버전을 복원해도 그 사이의 버전들은 삭제되지 않고 히스토리에 남는다. 스토리지 비용이 누적될 수 있으므로 수명 주기 정책(Lifecycle Policy)으로 오래된 버전을 자동 정리하는 것이 좋다.

실수로 VersionId를 지정해 삭제한 경우 — 복구 불가 시나리오

운영 중 가장 위험한 패턴은 이것이다. delete-object에 특정 버전의 VersionId를 명시해서 삭제하면, 그 버전은 영구적으로 제거된다. 삭제 마커가 생성되지 않고 해당 버전 데이터 자체가 사라진다.

증상은 list-object-versions 결과에서 해당 VersionId가 아예 보이지 않는 것이다. 이 경우 S3 버전 관리로는 복구할 수 없다. S3 버킷에 S3 Replication이나 AWS Backup이 구성되어 있었다면 그쪽에서 복구를 시도해야 한다.

이 두 가지 삭제 방식의 차이를 명확히 이해하는 것이 S3 버전 관리 운영의 핵심이다.

graph TD A[DeleteObject 호출] --> B{VersionId 지정?} B -- 아니오 --> C[삭제 마커 생성
이전 버전 보존] B -- 예 --> D{대상 버전 유형?} D -- 일반 버전 --> E[해당 버전 영구 삭제
복원 불가] D -- 삭제 마커 --> F[삭제 마커 제거
이전 버전 승격 = 복원] C --> G[복원 가능: 삭제 마커 VersionId로
delete-object 실행] E --> H[S3 버전 관리로 복구 불가
Replication/Backup 확인 필요] F --> I[복원 완료: head-object로 검증]
  1. VersionId 없이 삭제: 삭제 마커 생성. 이전 버전 데이터 보존. 복원 가능.
  2. VersionId 지정 삭제 (일반 버전): 해당 버전 영구 삭제. 복원 불가.
  3. VersionId 지정 삭제 (삭제 마커): 삭제 마커 제거. 이전 버전이 현재 버전으로 승격. 이것이 복원 방법.

필요한 IAM 권한

위 작업을 수행하는 IAM 주체(사용자 또는 역할)에는 최소한 다음 권한이 필요하다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucketVersions",
        "s3:GetBucketVersioning"
      ],
      "Resource": "arn:aws:s3:::your-bucket-name"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion",
        "s3:DeleteObjectVersion",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::your-bucket-name/*"
    }
  ]
}

s3:DeleteObjectVersion은 특정 VersionId를 지정한 삭제(삭제 마커 제거 포함)에 필요한 권한이다. s3:DeleteObject와 별개의 권한이므로 누락하지 않도록 주의한다.

S3 파일 복구 관련 마무리 및 다음 단계

버전 관리가 활성화된 S3 버킷에서 삭제된 파일 복구는 삭제 마커의 VersionId를 확인하고 제거하는 것으로 완료된다. 핵심은 list-object-versions로 전체 버전 히스토리를 먼저 파악하고, delete-object에 반드시 VersionId를 명시하는 것이다.

향후 유사한 사고를 방지하려면 다음을 검토한다:

  • MFA Delete 활성화: 버전 삭제 및 버전 관리 비활성화에 MFA 인증을 요구하도록 설정 (AWS 공식 문서)
  • S3 Object Lock: WORM(Write Once Read Many) 정책으로 특정 기간 동안 버전 삭제 자체를 차단
  • 수명 주기 정책: 오래된 버전과 삭제 마커를 자동 정리해 스토리지 비용 관리 (AWS 공식 문서)
  • S3 버전 관리 공식 문서: Using versioning in S3 buckets

핵심 용어 정리

용어설명
삭제 마커 (Delete Marker)버전 관리 버킷에서 VersionId 없이 삭제 시 생성되는 특수 버전. 실제 데이터 없이 '현재 버전이 삭제됨'을 나타내는 플레이스홀더.
VersionIdS3가 각 버전에 부여하는 고유 식별자. 버전 관리 활성화 후 업로드된 모든 객체에 자동 할당됨.
현재 버전 (Current Version)특정 키에 대해 VersionId 없이 GetObject 요청 시 반환되는 최신 버전. IsLatest: true인 버전.
s3:DeleteObjectVersion특정 VersionId를 지정해 버전을 영구 삭제하는 데 필요한 IAM 권한. s3:DeleteObject와 별개.
MFA Delete버전 영구 삭제 및 버전 관리 상태 변경 시 MFA 인증을 강제하는 버킷 보안 설정.

댓글

이 블로그의 인기 게시물

EC2 SSH 연결 타임아웃 완전 해결 가이드: Security Group 인바운드 규칙부터 라우팅까지

EC2 SSH 연결 시간 초과: 확인해야 할 보안 그룹(Security Group) 규칙

IAM User vs IAM Role 차이점 완전 정리 — EC2에서 S3 접근 시 무엇을 써야 하는가