S3 — 객체 저장소의 표준
S3 — 객체 저장소의 표준
S3 (Simple Storage Service) 는 AWS 가 2006 년 가장 먼저 GA 한 서비스로, 객체 저장소라는 카테고리를 대중화했습니다. 파일 시스템도 블록 스토리지도 아닌, "키로 접근하는 무한히 큰 버킷" 의 모델이 이후 클라우드 스토리지의 표준 모양이 됐습니다.
1. S3 에 대한 이야기
| 시기 | 사건 |
|---|---|
| 2006-03 | S3 GA — AWS 첫 GA 서비스. |
| 2010 | Versioning. |
| 2011 | Server-Side Encryption. |
| 2012 | Glacier (저장소 클래스). |
| 2018 | Intelligent-Tiering · Block Public Access. |
| 2020 | 강한 일관성 (read-after-write). |
S3 의 단위:
- Bucket — 객체의 상위 컨테이너. 전 세계에서 이름이 유일해야 하는 자리. 리전 종속.
- Object — 키 + 데이터 + 메타데이터. 5 TB 까지.
- Key — 객체의 식별자.
images/2025/cover.png처럼 슬래시를 포함한 문자열이지만 디렉터리는 아닙니다 (prefix 매칭).
2. 강한 일관성
오랫동안 S3 는 일부 동작에서 결과적 일관성 (eventually consistent) 모델이었지만 2020 년 12 월부터 모든 PUT/GET/DELETE 가 강한 일관성으로 동작합니다. 한 번 쓴 객체를 즉시 다시 읽을 수 있습니다.
3. Storage 클래스
| 클래스 | 성격 |
|---|---|
| Standard | 자주 접근. 기본값. |
| Intelligent-Tiering | 접근 패턴에 따라 자동 계층 이동. |
| Standard-IA | 드물게 접근, 즉시 검색. 저렴 + 검색 비용. |
| One Zone-IA | 단일 AZ. 비용 추가 절감, 가용성 낮음. |
| Glacier Instant Retrieval | 즉시 검색 가능한 아카이브. |
| Glacier Flexible Retrieval | 분~시간 단위 복원. |
| Glacier Deep Archive | 12 시간 단위 복원, 가장 저렴. |
같은 리전 안에서 클래스를 바꾸는 것은 객체의 메타데이터 변경. 데이터 자체는 옮기지 않습니다.
4. Lifecycle
객체의 나이·prefix·tag 에 따라 자동으로 클래스 전환·삭제하는 규칙. 로그·임시 파일을 일정 기간 후 Glacier 로 보내거나, 30 일 후 삭제하는 흐름.
{
"Rules": [{
"Status": "Enabled",
"Filter": { "Prefix": "logs/" },
"Transitions": [{ "Days": 30, "StorageClass": "GLACIER" }],
"Expiration": { "Days": 365 }
}]
}
5. Versioning · Replication
활성화하면 같은 키에 PUT 할 때마다 새 버전이 생깁니다. DELETE 는 "delete marker" 를 만들 뿐 데이터 자체는 남습니다. 의도적 복원 · 감사 · 랜섬웨어 대비의 자리. Lifecycle 로 옛 버전을 자동 정리하는 흐름이 흔합니다.
Replication:
- CRR (Cross-Region Replication) — 다른 리전 버킷으로 비동기 복제. DR · 지역 가까이 두기.
- SRR (Same-Region Replication) — 같은 리전, 다른 버킷. 분리·로그 적재.
Versioning 이 두 버킷에 모두 켜져 있어야 합니다.
6. Pre-signed URL
URL 자체에 임시 서명을 박아 잠시 동안 객체에 접근하게 하는 모델. 업로드용·다운로드용 모두 가능. 서버는 URL 만 발급하고, 클라이언트는 S3 에 직접 통신합니다.
url = s3.generate_presigned_url(
'put_object',
Params={'Bucket': 'my', 'Key': 'uploads/a.png', 'ContentType': 'image/png'},
ExpiresIn=600,
)
큰 파일을 서버를 거치지 않고 받아서 흐름을 가볍게 하는 자리에 흔히 쓰입니다.
7. Multipart Upload
100 MB 이상은 멀티파트 업로드가 권장됩니다. 5 MB ~ 5 GB 의 파트로 나눠 병렬 업로드, 마지막에 합칩니다. 실패한 파트만 재시도.
8. 정적 웹사이트 호스팅
버킷에 index.html · error.html 을 두고 정적 호스팅을 켜면 HTTP 로 노출됩니다. HTTPS 가 필요하면 앞에 CloudFront 를 둡니다 (S3 + CloudFront 조합이 사실상 표준).
9. 호환 서비스
| 서비스 | 메모 |
|---|---|
| MinIO | 자체 호스팅 가능한 S3 호환 서버. 온프레미스 · k8s. |
| Cloudflare R2 (2022) | egress 0 원이 강조되는 가격 모델. S3 호환 API. |
| Backblaze B2 | 저렴한 가격 + S3 호환 API. |
| Wasabi | 정액제 · egress 무료 모델. |
| Google Cloud Storage | S3 와 유사한 모델, API 는 다름. |
| Azure Blob Storage | Azure 대응. |
S3 API 가 사실상 객체 저장소의 lingua franca 가 되어, 같은 SDK 로 여러 백엔드를 가리키는 흐름이 흔합니다 (endpoint_url 변경).
10. CLI · 보안 기본값
aws s3 cp ./build s3://my-static/ --recursive
aws s3 sync ./build s3://my-static/ --delete
보안 기본값:
- Block Public Access 를 계정·버킷 양쪽에서 켭니다. 명시적으로 공개가 필요한 자리만 풀어 사용.
- 버킷 정책 으로 접근 제어. ACL 은 가능한 한 사용을 줄이는 흐름 (2023 부터 신규 버킷의 ACL 기본 비활성).
- KMS 암호화 (
aws:kms) 또는 SSE-S3 (AES256). 2023 부터 모든 객체가 기본 SSE-S3 로 암호화. - Object Lock — WORM (Write Once Read Many). 컴플라이언스.
- VPC Endpoint (Gateway) — VPC 내부에서 인터넷을 거치지 않고 S3 에 도달.
11. 비용 구조
- 저장 용량 — GB · 월. 클래스에 따라 큰 차이.
- 요청 — PUT · GET · LIST 의 단위 가격이 다름.
- 전송 (Egress) — 같은 리전 안 같은 AWS 서비스로 무료, 인터넷·다른 리전으로 나가면 GB 단위.
요청 비용이 의외의 자리에서 커집니다. 작은 객체를 매우 많이 다루면 LIST · GET 비용이 저장 비용보다 클 수 있습니다.
12. 자주 걸리는 자리
공개 노출 사고 — 옛 버킷이 ACL public-read 로 풀려 있는 사례가 종종 보고됩니다. Block Public Access + Access Analyzer 로 점검.
Glacier 의 복원 시간 — Deep Archive 는 12 시간 이상. 즉시 사용 가능한 자리에 두면 운영 사고.
Lifecycle 의 누적 비용 — 옛 버전을 정리하지 않으면 Versioning 활성 버킷의 비용이 계속 누적.
Pre-signed URL 의 만료·서명 헤더 — 만료 시간이 짧거나 클라이언트가 추가 헤더를 붙이면 서명이 깨집니다.
CORS 누락 — 브라우저에서 직접 S3 에 PUT 하려면 버킷의 CORS 설정 필요.
요청 비용 폭주 — LIST 를 자주 호출하는 코드가 의외로 비싸집니다. 캐시 · DB 인덱스로 대체.
하고픈 말
S3 는 객체 저장소의 사실상 표준입니다. 작은 운영에서는 Cloudflare R2 의 egress 무료 모델이나 자체 MinIO 가 비용에 유리할 수 있습니다. 보안은 Block Public Access 가 첫 단계 — 옛 버킷의 공개 노출 사고가 가장 흔한 사고 패턴입니다.
Next
- rds
- cloudfront
S3 사용자 가이드 · S3 가격 · Object Lock · MinIO · Cloudflare R2 · Backblaze B2 · s3cmd · rclone 을 참고합니다.