LLM WikiAccess-protected knowledge portal

WIKI

오브젝트 스토리지 운영: S3 라이프사이클, 멀티파트, 성능 패턴

오브젝트 스토리지는 파일시스템이 아니라 운영 계약이다 S3 같은 오브젝트 스토리지는 POSIX 파일시스템처럼 열고, 조금 고치고, 닫는 저장소가 아니다. 기본 단위는 object 이고, object는 key, metadata, storage class, version, tag, encryption 상태 같은 운영 속성과 함께 관리된다. 데이터 플랫폼에서는 이 차이를 제대로 이해해야 비용과 성능 사고를 줄일 수 있다. 가장 자주

경로human/study/content/storage-and-io/05-object-storage-s3-lifecycle-multipart-performance.md
카테고리Study
태그#lifecycle #multipart #object #performance #storage #study

오브젝트 스토리지는 파일시스템이 아니라 운영 계약이다

S3 같은 오브젝트 스토리지는 POSIX 파일시스템처럼 열고, 조금 고치고, 닫는 저장소가 아니다. 기본 단위는 object이고, object는 key, metadata, storage class, version, tag, encryption 상태 같은 운영 속성과 함께 관리된다. 데이터 플랫폼에서는 이 차이를 제대로 이해해야 비용과 성능 사고를 줄일 수 있다.

가장 자주 생기는 문제는 세 가지다.

이 장에서는 S3를 기준으로 라이프사이클, 멀티파트 업로드, 성능 패턴을 운영자 관점에서 정리한다. 다른 클라우드의 object storage도 이름은 다르지만 대부분 같은 판단 구조를 갖는다.


라이프사이클: 비용 정책을 코드처럼 다루기

S3 Lifecycle은 특정 object 집합에 대해 자동으로 두 가지 일을 한다.

  1. Transition: 더 낮은 비용의 storage class로 이동
  2. Expiration: 보존 기간이 지난 object 삭제

중요한 점은 라이프사이클이 단순 정리 스크립트가 아니라 bucket에 걸린 데이터 보존 정책이라는 것이다. 한 번 켜면 기존 object에도 적용될 수 있다. 예를 들어 “생성 후 30일이 지난 object 삭제” 규칙을 오늘 추가하면, 이미 30일이 넘은 object도 삭제 대상이 된다. 운영자는 규칙을 배포하기 전에 prefix, tag, object size, versioning 상태를 반드시 검토해야 한다.

S3 Standard 자주 접근 30일 이후 Standard-IA 드문 접근 90일 이후 Glacier 계열 아카이브 보존 기간 만료 Expiration 삭제 또는 delete marker 운영 검토 지점 prefix/tag 범위 · versioning · 최소 보관 기간 복구 요구사항 · 전환 요청 비용 · small object
S3 object lifecycle 운영 흐름

Transition 판단: 싸지는 것이 항상 좋은 것은 아니다

Storage class 전환은 “GB당 저장 비용”만 보면 쉬워 보인다. 하지만 실제 비용은 다음 요소가 함께 결정한다.

판단 항목운영 질문
접근 빈도최근 30일/90일 동안 실제 GET이 있었는가?
복구 시간Glacier 계열로 이동해도 복구 지연을 허용할 수 있는가?
최소 보관 기간조기 삭제 또는 조기 전환 비용이 생기지 않는가?
object 크기작은 object를 대량 전환할 때 요청 비용이 절감액보다 커지지 않는가?
규정 요구감사·법적 보존 기간과 충돌하지 않는가?

AWS 문서 기준으로 S3 Standard-IA와 One Zone-IA로 전환하려면 object가 최소 30일은 저장되어 있어야 한다. 또한 2024년 9월 이후 새 lifecycle 동작에서는 기본적으로 128KB 미만 object가 어떤 storage class로도 transition되지 않는다. 작은 object는 storage 절감액보다 transition request 비용이나 metadata성 비용이 더 커질 수 있기 때문이다.

따라서 데이터 플랫폼에서는 보통 다음처럼 구간을 나눈다.

Expiration은 삭제 자동화가 아니라 복구 가능성의 포기다

Expiration rule은 비용을 줄이는 데 강력하지만, 운영 사고도 강력하게 만든다. 특히 versioning이 켜진 bucket에서는 현재 버전 삭제와 noncurrent version 삭제의 의미가 다르다. 일반적인 “오래된 파일 삭제” 정책을 versioning bucket에 그대로 적용하면 delete marker만 생기고 실제 과금 대상인 noncurrent version은 남을 수 있다. 반대로 noncurrent version expiration을 과격하게 잡으면 실수 삭제 복구 기간이 사라진다.

운영 기준은 다음 순서가 안전하다.

  1. prefix와 tag로 대상 범위를 좁힌다.
  2. Storage Lens, Inventory, Athena 등으로 대상 object 수와 크기를 추정한다.
  3. dry-run에 해당하는 목록 조회를 먼저 남긴다.
  4. lifecycle rule을 적용한 뒤 전환·삭제 지표를 모니터링한다.
  5. versioned bucket은 current version과 noncurrent version 정책을 분리해서 검토한다.

멀티파트 업로드: 큰 object를 여러 실패 단위로 나누기

S3 Multipart Upload는 하나의 큰 object를 여러 part로 나누어 업로드한 뒤 마지막에 조립하는 방식이다. AWS는 100MB 이상 object에는 단일 PUT 대신 multipart upload를 사용하는 것을 권장한다.

멀티파트의 운영상 장점은 명확하다.

멀티파트 업로드 절차

1. Initiate
upload id 발급
metadata·checksum 결정
2. Upload parts
part 1
ETag 기록
part 2
ETag 기록
part N
실패 시 이 part만 retry
3. Complete
part number + ETag 제출
object 조립
Multipart upload의 실패 단위

S3는 part number 오름차순으로 part를 연결한다. 각 part upload 응답의 ETag와 part number는 CompleteMultipartUpload 요청에 필요하므로 클라이언트는 반드시 기록해야 한다. 또 완료 후 object의 ETag는 단순히 전체 파일의 MD5라고 가정하면 안 된다. 멀티파트, 암호화, checksum 설정에 따라 의미가 달라질 수 있다.

미완료 multipart upload는 비용 누수다

멀티파트를 시작하고 part를 하나 이상 올린 뒤 complete도 abort도 하지 않으면, 업로드된 part는 저장 비용을 발생시킨다. 이 part는 정상 object 목록에는 보이지 않아 운영자가 놓치기 쉽다. 그래서 S3 Lifecycle에는 AbortIncompleteMultipartUpload action이 있다. 예를 들어 7일이 지나도 완료되지 않은 multipart upload를 자동 abort하면, 관련 part가 삭제되고 비용 누수를 줄일 수 있다.

{
  "Rules": [
    {
      "ID": "abort-incomplete-multipart-after-7-days",
      "Status": "Enabled",
      "Filter": { "Prefix": "" },
      "AbortIncompleteMultipartUpload": {
        "DaysAfterInitiation": 7
      }
    }
  ]
}

이 action은 완료된 object를 삭제하지 않는다. 미완료 multipart upload에만 적용된다. 따라서 대용량 업로드를 쓰는 bucket에는 거의 기본 안전장치로 보는 편이 좋다.


성능 패턴: prefix, 병렬성, retry, locality

S3는 단일 디스크가 아니라 대규모 분산 시스템이다. 성능 튜닝도 “디스크 큐 길이”가 아니라 “요청 분산과 병렬성” 관점으로 접근해야 한다.

1. prefix별 요청률과 점진적 확장

AWS 문서 기준으로 S3는 prefix당 최소 초당 3,500 PUT/COPY/POST/DELETE 또는 5,500 GET/HEAD 요청을 지원한다. bucket 안 prefix 수에는 제한이 없으므로 여러 prefix로 읽기·쓰기를 병렬화하면 처리량을 확장할 수 있다. 다만 새로운 높은 요청률에 맞춰 S3 내부가 scale-out되는 과정은 즉시 완료되지 않을 수 있고, 이때 일시적인 503 Slow Down이 보일 수 있다.

운영자는 다음을 구분해서 봐야 한다.

2. 많은 connection으로 수평 확장

고처리량 업로드·다운로드는 단일 HTTP connection에 기대지 않는다. 여러 connection에서 병렬 GET/PUT을 발행해 aggregate bandwidth를 만든다. 대용량 파일 업로드는 multipart upload, 대용량 파일 다운로드는 byte-range GET을 활용할 수 있다. 특히 multipart로 올린 object는 동일한 part 크기나 part boundary에 맞춰 range GET을 하면 재시도와 병렬 처리에 유리하다.

대용량 object 다운로드 예시

나쁜 패턴:
  1개 worker가 500GB object 전체 GET
  → 중간 실패 시 긴 재시도, 단일 connection 병목

좋은 패턴:
  object를 range로 나누어 16~64개 worker가 병렬 GET
  → 느린 range만 재시도, aggregate throughput 증가

3. retry는 장애 은폐가 아니라 분산 시스템 프로토콜이다

S3는 SDK 수준에서 retry와 exponential backoff를 제공한다. latency-sensitive workload에서는 timeout과 retry 정책을 명시적으로 조정해야 한다. AWS 문서는 큰 요청은 느린 하위 비율을 추적해 재시도하고, 작은 요청은 예를 들어 2초 후 1회, 추가 4초 후 2회처럼 빠른 재시도를 고려하라고 설명한다.

하지만 retry는 무제한으로 늘리면 안 된다. retry storm은 downstream 장애를 키울 수 있다. 운영 기준은 다음과 같다.

4. compute와 bucket region을 맞춘다

S3와 EC2/Spark/Flink worker가 서로 다른 region에 있으면 latency와 egress cost가 동시에 증가한다. 데이터 레이크 작업은 같은 region에 compute를 두는 것이 기본이다. 전 세계 사용자가 다운로드하는 정적 콘텐츠라면 CloudFront cache를 앞에 두고, 먼 거리 대용량 업로드가 많다면 Transfer Acceleration을 검토한다. 운영 DB 백업이나 데이터 파이프라인 랜딩존에는 보통 “같은 region + private endpoint/VPC endpoint + 제한된 IAM” 조합이 더 중요하다.


데이터 플랫폼에서의 설계 패턴

Raw zone과 processed zone은 lifecycle이 다르다

데이터 레이크 bucket을 하나로 보더라도 prefix별 데이터 성격은 다르다.

Zone예시운영 정책
rawsource dump, CDC landing, original log재처리 근거이므로 보존 기간 길게, 삭제 신중
staging임시 변환 결과, failed batch output짧은 expiration, multipart abort 필수
processedParquet/ORC, curated table filestable format의 snapshot/vacuum 정책과 충돌 금지
auditmanifest, checksum, run ledger작지만 중요함. transition보다 무결성과 조회성 우선

특히 Iceberg, Delta Lake, Hudi 같은 table format을 쓰는 prefix에 lifecycle expiration을 직접 걸 때는 조심해야 한다. table format은 자체 metadata와 snapshot retention 정책을 갖는다. S3 lifecycle이 임의로 data file이나 metadata file을 먼저 삭제하면 table의 time travel, rollback, query가 깨질 수 있다. table format이 관리하는 경로는 해당 엔진의 expire_snapshots, vacuum, cleaner, compaction 절차를 우선한다.

작은 파일 문제와 object storage 비용

S3는 많은 작은 object도 저장할 수 있지만, 데이터 처리 비용은 크게 나빠질 수 있다.

따라서 데이터 플랫폼에서는 “압축률”만 보지 말고 file size target을 잡아야 한다. Spark나 Flink sink는 너무 작은 파일을 계속 만들지 않도록 compaction, checkpoint interval, partition 수, writer parallelism을 조정한다. object storage 운영은 스토리지 정책만으로 끝나지 않고, upstream writer의 파일 생성 방식까지 포함한다.


운영 체크리스트

Bucket 생성·정책 단계

대용량 업로드 단계

성능 운영 단계


마무리

오브젝트 스토리지 운영의 핵심은 “싸고 무한한 저장소”라는 인상을 버리는 것이다. S3는 매우 높은 내구성과 확장성을 제공하지만, 비용·성능·복구 가능성은 object 단위 정책과 클라이언트 접근 패턴이 결정한다.

운영자는 다음 세 가지 질문을 반복해야 한다.

  1. 이 object는 언제까지, 어떤 storage class에 있어야 하는가?
  2. 큰 object 업로드·다운로드의 실패 단위는 충분히 작게 나뉘어 있는가?
  3. 요청률과 retry는 S3의 분산 시스템 특성에 맞게 설계되었는가?

이 질문에 답할 수 있으면 object storage는 단순 백업 저장소를 넘어 데이터 플랫폼의 안정적인 landing zone, archive layer, serving layer가 된다.

References