2026. 6. 5. 16:39ㆍCloud/AWS
"개발팀이 S3 버킷에 로그를 쌓고 있는데, 3개월 만에 저장 비용이 월 $200을 넘었습니다. 오래된 파일은 자동으로 정리하고 싶은데, 실수로 삭제한 파일은 복원할 수 있어야 합니다." — 이 상황에서 필요한 것이 S3의 수명 주기 규칙과 버전 관리입니다.
핵심 요약
- S3 버킷 정책(Bucket Policy)은 버킷 단위의 접근 제어 규칙으로, 크로스 계정 접근이나 특정 조건부 허용에 사용됩니다.
- 버전 관리(Versioning)를 활성화하면 객체를 덮어쓰거나 삭제해도 이전 버전이 보존되어 복원이 가능합니다.
- 수명 주기(Lifecycle) 규칙으로 객체를 저렴한 스토리지 클래스로 자동 전환하거나 만료 삭제할 수 있습니다.
- 세 가지 기능을 조합하면 "데이터 보호 + 비용 최적화 + 접근 제어"를 동시에 설계할 수 있습니다.
- 모든 설정에는 비용 trade-off가 있으며, 데이터 접근 패턴에 맞게 조정해야 합니다.
1. S3 버킷 정책 (Bucket Policy)
1.1 IAM Policy와 Bucket Policy의 차이
S3 접근 제어에는 IAM Policy와 Bucket Policy 두 가지 경로가 있습니다. 둘 다 JSON 형식이지만, 적용 관점이 다릅니다.
| 구분 | IAM Policy | Bucket Policy |
|---|---|---|
| 부착 대상 | IAM User, Role, Group | S3 Bucket |
| 관점 | "이 사용자가 무엇을 할 수 있는가" | "이 버킷에 누가 접근할 수 있는가" |
| 크로스 계정 | 자기 계정 내에서만 효력 | 다른 계정의 Principal 허용 가능 |
| 익명 접근 | 불가 | "Principal": "*" 로 퍼블릭 허용 가능 |
| 크기 제한 | 6,144자 (관리형), 10,240자 (인라인) | 20KB |
실무 판단 기준: - 같은 계정 내 접근 제어 → IAM Policy로 충분합니다. - 크로스 계정 접근, IP 제한, VPC Endpoint 제한 → Bucket Policy가 필요합니다. - 둘 다 설정한 경우, 명시적 Deny가 항상 우선합니다.
1.2 Bucket Policy 구조
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCrossAccountRead",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:root"
},
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-data-bucket",
"arn:aws:s3:::my-data-bucket/*"
]
}
]
}
주의할 점: - Resource에 버킷 ARN(arn:aws:s3:::bucket)과 객체 ARN(arn:aws:s3:::bucket/*)을 구분해야 합니다. ListBucket은 버킷 수준, GetObject는 객체 수준 권한입니다. - Principal을 "*"로 설정하면 퍼블릭 접근이 허용됩니다. 의도치 않은 데이터 노출의 가장 흔한 원인입니다.
1.3 실무 시나리오: VPC Endpoint에서만 접근 허용
운영 환경에서 S3 버킷이 인터넷을 통해 접근되면 안 되는 경우가 있습니다. 예를 들어 개인정보가 포함된 로그 버킷은 VPC 내부에서만 접근하도록 제한해야 합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyAccessExceptFromVPCE",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::sensitive-logs-bucket",
"arn:aws:s3:::sensitive-logs-bucket/*"
],
"Condition": {
"StringNotEquals": {
"aws:sourceVpce": "vpce-0abc1234def567890"
}
}
}
]
}
이 정책은 지정된 VPC Endpoint를 경유하지 않는 모든 요청을 거부합니다. AWS 콘솔에서도 접근이 차단되므로, 관리용 예외 조건을 추가하는 것이 일반적입니다.
1.4 Block Public Access 설정
AWS는 2023년 4월 28일부터 새로 생성되는 모든 버킷에 Block Public Access가 기본 활성화됩니다. 이 설정은 Bucket Policy나 ACL을 통한 퍼블릭 접근을 계정/버킷 수준에서 일괄 차단합니다.
| 설정 | 효과 |
|---|---|
| BlockPublicAcls | 퍼블릭 ACL 추가 차단 |
| IgnorePublicAcls | 기존 퍼블릭 ACL 무시 |
| BlockPublicPolicy | 퍼블릭 Bucket Policy 추가 차단 |
| RestrictPublicBuckets | 퍼블릭 정책이 있어도 계정 외부 접근 차단 |
운영 권장: 4가지 모두 활성화 상태를 유지하고, 정적 웹 호스팅처럼 퍼블릭 접근이 필요한 경우에만 선택적으로 해제합니다. 그 경우에도 CloudFront OAC(Origin Access Control)를 통한 간접 접근을 우선 검토할 수 있습니다.
2. 버전 관리 (Versioning)
2.1 버전 관리가 필요한 이유
S3 버전 관리를 활성화하지 않으면, 같은 Key로 객체를 업로드할 때 기존 파일이 즉시 덮어씌워집니다. 삭제도 즉시 영구 삭제됩니다. 이는 다음 상황에서 문제가 됩니다.
- 배포 스크립트가 잘못된 설정 파일을 덮어쓴 경우
- 운영자가 실수로 중요한 데이터를 삭제한 경우
- 랜섬웨어가 기존 파일을 암호화된 파일로 덮어쓴 경우
2.2 동작 원리
버전 관리를 활성화하면 S3는 모든 PUT/DELETE 요청에 대해 이전 상태를 보존합니다.
PUT (덮어쓰기) 시: 1. 기존 객체는 "이전 버전(Noncurrent Version)"으로 보존됩니다. 2. 새 객체가 "현재 버전(Current Version)"이 됩니다. 3. 각 버전은 고유한 Version ID를 가집니다.
DELETE 시: 1. 객체가 물리적으로 삭제되지 않습니다. 2. "Delete Marker"가 추가되어 일반 GET 요청 시 404를 반환합니다. 3. Version ID를 지정하면 이전 버전에 직접 접근할 수 있습니다.
복원 방법:
# 특정 버전 확인
aws s3api list-object-versions --bucket my-bucket --prefix config/app.json
# 이전 버전을 현재 버전으로 복원 (해당 버전을 복사)
aws s3api copy-object \
--bucket my-bucket \
--key config/app.json \
--copy-source my-bucket/config/app.json?versionId=abc123
2.3 버전 관리의 비용 영향
버전 관리의 핵심 trade-off는 데이터 보호 vs 저장 비용 증가입니다.
| 항목 | 영향 |
|---|---|
| 저장 비용 | 모든 이전 버전이 저장되므로 비용 증가 (버전 수 × 객체 크기) |
| 삭제 불가 | 버전 관리가 활성화되면 "Suspend"는 가능하지만, 기존 버전은 삭제하기 전까지 유지 |
| 복원 가능성 | 실수, 악의적 삭제, 애플리케이션 버그로부터 보호 |
비용 사례: - 10MB 파일이 하루 1회 업데이트되고, 버전 관리 활성화 + 정리 규칙 없음 - 30일 후: 10MB × 30 = 300MB 저장 (원본 대비 30배) - 이 때문에 버전 관리와 수명 주기 규칙은 반드시 함께 설계해야 합니다.
2.4 버전 관리 상태
| 상태 | 의미 | 전환 가능 여부 |
|---|---|---|
| Unversioned | 기본값, 버전 관리 없음 | → Enabled |
| Enabled | 모든 객체에 버전 부여 | → Suspended |
| Suspended | 새 객체에 null Version ID 부여, 기존 버전 유지 | → Enabled |
주의: 한 번 Enabled로 설정하면 Unversioned 상태로 되돌릴 수 없습니다. Suspend해도 기존 버전은 삭제되지 않습니다. 기존 버전을 정리하려면 수명 주기 규칙이나 수동 삭제가 필요합니다.
3. 수명 주기 (Lifecycle) 규칙
3.1 스토리지 클래스와 비용 구조
S3는 접근 빈도에 따라 여러 스토리지 클래스를 제공합니다. 저장 비용이 낮을수록 검색(Retrieval) 비용과 최소 보관 기간 제약이 커집니다.
| 스토리지 클래스 | 저장 비용 (서울, GB/월) | 최소 보관 기간 | 검색 시간 | 적합한 데이터 |
|---|---|---|---|---|
| Standard | $0.025 | 없음 | 즉시 | 자주 접근하는 운영 데이터 |
| Standard-IA | $0.0138 | 30일 | 즉시 | 월 1~2회 접근 데이터 |
| One Zone-IA | $0.011 | 30일 | 즉시 | 재생성 가능한 데이터 |
| Glacier Instant Retrieval | $0.005 | 90일 | 밀리초 | 분기 1회 접근, 즉시 필요 |
| Glacier Flexible Retrieval | $0.0045 | 90일 | 분~시간 | 연 1~2회, 몇 시간 대기 가능 |
| Glacier Deep Archive | $0.002 | 180일 | 12~48시간 | 규정 준수용 장기 보관 |
| Intelligent-Tiering | $0.025 + 모니터링 $0.0025/1000객체 | 없음 | 즉시 | 접근 패턴 예측 불가 |
아래 가격은 AWS 공식 요금 페이지 기준 근사치입니다. 리전별, 시기별로 변동될 수 있으므로 정확한 비용 산정 시 AWS S3 Pricing 페이지를 확인하시기 바랍니다.
3.2 수명 주기 규칙 설계
수명 주기 규칙은 객체의 나이(생성 후 경과 일수)에 따라 자동으로 스토리지 클래스를 전환하거나 삭제하는 정책입니다.
규칙 유형:
| 액션 | 대상 | 설명 |
|---|---|---|
| Transition | Current Version | 현재 버전을 다른 스토리지 클래스로 이동 |
| Transition | Noncurrent Version | 이전 버전을 다른 스토리지 클래스로 이동 |
| Expiration | Current Version | 현재 버전 삭제 (Delete Marker 추가) |
| NoncurrentVersionExpiration | Noncurrent Version | 이전 버전 영구 삭제 |
| AbortIncompleteMultipartUpload | Multipart Upload | 미완료 멀티파트 업로드 정리 |
| DeleteMarkerExpiration | Delete Marker | 만료된 Delete Marker 자동 제거 |
3.3 실무 시나리오: 애플리케이션 로그 버킷
월 500GB의 로그가 쌓이는 버킷을 설계한다고 가정합니다.
요구사항: - 최근 7일 로그: 즉시 접근 가능 (장애 분석용) - 30일~90일 로그: 가끔 접근 (월간 리포트, 감사) - 90일 이후: 규정 준수 목적으로 1년 보관 - 1년 이후: 삭제
수명 주기 설정:
{
"Rules": [
{
"ID": "LogRetentionPolicy",
"Status": "Enabled",
"Filter": {
"Prefix": "logs/"
},
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER"
}
],
"Expiration": {
"Days": 365
}
},
{
"ID": "CleanupIncompleteUploads",
"Status": "Enabled",
"Filter": {},
"AbortIncompleteMultipartUpload": {
"DaysAfterInitiation": 7
}
}
]
}
비용 절감 효과 (월 500GB 기준):
| 기간 | 클래스 | 데이터량 | 월 비용 |
|---|---|---|---|
| 0~30일 | Standard | 500GB | $12.50 |
| 30~90일 | Standard-IA | 1,000GB | $13.80 |
| 90~365일 | Glacier | 4,500GB(누적) | $20.25 |
| 합계 | ~$46.55 | ||
| 전부 Standard 유지 시 | 6,000GB | $150.00 |
수명 주기 규칙 하나로 월 $100 이상 절감이 가능한 사례입니다.
3.4 버전 관리 + 수명 주기 조합 설계
버전 관리가 활성화된 버킷에서는 이전 버전이 계속 쌓이므로, 수명 주기 규칙으로 이전 버전을 정리하는 것이 필수입니다.
권장 설정 패턴:
{
"Rules": [
{
"ID": "ManageCurrentVersions",
"Status": "Enabled",
"Filter": {},
"Transitions": [
{
"Days": 90,
"StorageClass": "STANDARD_IA"
}
]
},
{
"ID": "ManageNoncurrentVersions",
"Status": "Enabled",
"Filter": {},
"NoncurrentVersionTransitions": [
{
"NoncurrentDays": 30,
"StorageClass": "GLACIER"
}
],
"NoncurrentVersionExpiration": {
"NoncurrentDays": 90
}
},
{
"ID": "CleanupDeleteMarkers",
"Status": "Enabled",
"Filter": {},
"Expiration": {
"ExpiredObjectDeleteMarker": true
}
}
]
}
설계 의도: - 현재 버전은 90일 후 Standard-IA로 전환 (접근 빈도 감소) - 이전 버전은 30일 동안 Standard로 유지 (실수 복원 기간) - 이전 버전은 30일 후 Glacier로 이동, 90일 후 영구 삭제 - Delete Marker가 유일한 버전이 되면 자동 정리
"이전 버전 30일 보존"의 근거: 대부분의 실수는 당일~1주일 이내에 발견됩니다. 30일은 월간 정산이나 감사 시점에서 발견되는 문제까지 커버하는 보수적인 설정입니다. 비용이 부담되면 7~14일로 줄일 수 있습니다.
4. 실무 설계 시나리오
4.1 시나리오: SaaS 서비스의 사용자 업로드 파일
B2B SaaS 서비스에서 고객이 업로드한 문서 파일을 관리해야 합니다.
요구사항: - 고객이 업로드한 원본 파일은 삭제 실수로부터 보호 - 3개월 이내 파일은 즉시 다운로드 가능 - 계약 종료 후 6개월 보관 의무 (규정 준수) - 다른 AWS 계정(파트너)에서 특정 폴더 읽기 접근 필요 - 월 저장 비용 $50 이내 목표
설계 결정:
| 항목 | 결정 | 이유 |
|---|---|---|
| 버전 관리 | 활성화 | 삭제 실수 복원, 랜섬웨어 방어 |
| 이전 버전 보존 | 14일 | 대부분의 실수는 2주 내 발견 |
| 현재 버전 전환 | 90일 → Standard-IA | 3개월 지나면 접근 빈도 급감 |
| 만료 | 생성 후 365일 | 6개월 보관 의무 + 여유 |
| 크로스 계정 접근 | Bucket Policy | IAM으로는 다른 계정 허용 불가 |
| 퍼블릭 접근 | Block Public Access 전체 활성화 | 고객 데이터 노출 방지 |
4.2 시나리오: CI/CD 파이프라인의 빌드 아티팩트
CI/CD 파이프라인이 빌드할 때마다 아티팩트를 S3에 저장합니다.
특성: - 하루 10~50회 빌드, 아티팩트 평균 200MB - 최근 빌드만 롤백 용도로 필요 (최대 5개) - 오래된 아티팩트는 재빌드 가능
설계 결정:
| 항목 | 결정 | 이유 |
|---|---|---|
| 버전 관리 | 비활성화 | 아티팩트는 Key 자체가 고유 (빌드 번호 포함) |
| 수명 주기 | 7일 후 삭제 | 롤백 필요 시 최근 7일이면 충분 |
| 스토리지 클래스 | Standard (변환 없음) | 7일 내 삭제되므로 전환 비용이 오히려 비효율 |
| 접근 제어 | IAM Role (CI/CD Role) | 같은 계정 내 파이프라인만 접근 |
이 경우 버전 관리를 활성화하지 않는 이유는 아티팩트 Key에 이미 빌드 번호가 포함되어 있기 때문입니다 (예: artifacts/build-1234/app.jar). Key 자체가 버전 역할을 하므로 S3 버전 관리는 불필요한 비용만 추가합니다.
5. 보안 고려사항
5.1 데이터 보호 계층
S3 데이터를 보호하는 계층을 정리하면 다음과 같습니다.
| 계층 | 기능 | 방어 대상 |
|---|---|---|
| Block Public Access | 퍼블릭 노출 차단 | 설정 실수로 인한 데이터 유출 |
| Bucket Policy | 접근 조건 제한 | 권한 없는 계정/IP/서비스 |
| IAM Policy | 사용자/Role별 권한 | 내부 사용자 과잉 권한 |
| Versioning | 삭제/덮어쓰기 보호 | 실수, 악의적 삭제 |
| MFA Delete | 삭제 시 MFA 요구 | 계정 탈취 시 데이터 파괴 방지 |
| Object Lock | 변경 불가 보존 | 규정 준수 (WORM) |
| SSE-S3 / SSE-KMS | 저장 시 암호화 | 디스크 물리 접근, AWS 내부 침해 |
5.2 MFA Delete
MFA Delete를 활성화하면 버전 관리 비활성화(Suspend)와 객체 버전 영구 삭제 시 MFA 인증을 요구합니다. 랜섬웨어나 계정 탈취 시나리오에서 데이터 파괴를 방지하는 마지막 방어선입니다.
# MFA Delete 활성화 (루트 계정만 가능)
aws s3api put-bucket-versioning \
--bucket my-critical-bucket \
--versioning-configuration Status=Enabled,MFADelete=Enabled \
--mfa "arn:aws:iam::123456789012:mfa/root-mfa-device 123456"
제약사항: - 루트 계정으로만 활성화/비활성화 가능 - IAM 사용자로는 설정 불가 - 일상적인 객체 삭제가 번거로워지므로, 핵심 데이터 버킷에만 적용하는 것이 현실적입니다.
5.3 서버 측 암호화
S3는 2023년 1월 5일부터 모든 새 객체에 SSE-S3(AES-256) 암호화를 기본 적용합니다. 별도 설정 없이도 저장 시 암호화됩니다.
| 암호화 방식 | 키 관리 | 비용 | 적합한 경우 |
|---|---|---|---|
| SSE-S3 | AWS 관리 | 무료 | 기본 암호화로 충분한 경우 |
| SSE-KMS | AWS KMS | KMS API 호출 비용 | 키 사용 감사, 키 교체 제어 필요 시 |
| SSE-C | 고객 관리 | 무료 (키 관리 비용 별도) | 키를 직접 통제해야 하는 규정 |
운영 환경에서는 SSE-KMS를 선택하는 경우가 많습니다. CloudTrail에서 키 사용 이력을 감사할 수 있고, 키 비활성화로 데이터 접근을 즉시 차단할 수 있기 때문입니다. 다만 KMS API 호출 비용($0.03/10,000 요청)이 발생하므로, 대량 읽기가 빈번한 경우 비용을 확인해야 합니다.
6. 비용 최적화 전략
6.1 비용 구성 요소
S3 비용은 저장만이 아닙니다. 요청 수, 데이터 전송, 검색 비용이 모두 합산됩니다.
| 비용 항목 | Standard | Standard-IA | Glacier |
|---|---|---|---|
| 저장 (GB/월) | $0.025 | $0.0138 | $0.0045 |
| PUT/POST (1,000건) | $0.005 | $0.01 | $0.05 |
| GET (1,000건) | $0.0004 | $0.001 | $0.0004 |
| 검색 (GB) | 없음 | $0.01 | $0.03~$0.09 |
| 최소 객체 크기 | 없음 | 128KB | 40KB |
| 최소 보관 기간 | 없음 | 30일 | 90일 |
흔한 실수: - 작은 파일(수 KB)을 Standard-IA로 전환 → 128KB 최소 과금으로 오히려 비용 증가 - 전환 후 30일 이내 삭제 → 30일분 저장 비용이 과금됨 - Glacier에서 대량 검색 → 검색 비용이 저장 절감분을 초과
6.2 Intelligent-Tiering 활용
접근 패턴을 예측하기 어려운 경우, S3 Intelligent-Tiering이 대안이 될 수 있습니다.
동작 방식: - 30일 접근 없음 → Infrequent Access 계층 (Standard-IA 수준) - 90일 접근 없음 → Archive Instant Access 계층 (Glacier Instant 수준) - 180일 접근 없음 → Archive Access 계층 (선택 활성화)
비용: - 저장 비용은 Standard와 동일하게 시작 - 모니터링 비용: $0.0025/1,000객체/월 추가 - 검색 비용 없음 (자동 전환 시)
적합한 경우: 객체 수가 수백만 개 이상이고, 접근 패턴이 시간에 따라 변하는 데이터 레이크. 객체 수가 적으면 모니터링 비용 대비 절감 효과가 미미합니다.
6.3 S3 Storage Lens로 현황 파악
비용 최적화의 첫 단계는 현재 사용 현황을 파악하는 것입니다. S3 Storage Lens는 무료 대시보드를 제공하며, 다음을 확인할 수 있습니다.
- 버킷별 저장 용량과 객체 수
- 스토리지 클래스별 분포
- 불완전 멀티파트 업로드 용량
- 이전 버전이 차지하는 용량 비율
이 데이터를 기반으로 수명 주기 규칙의 전환 시점과 만료 기간을 결정합니다.
7. 설계 체크리스트
접근 제어
- [ ] Block Public Access 4가지 모두 활성화 상태인가
- [ ] Bucket Policy에
"Principal": "*"가 의도치 않게 포함되어 있지 않은가 - [ ] 크로스 계정 접근 시 최소 권한 원칙을 적용했는가
- [ ] 민감 데이터 버킷에 VPC Endpoint 제한을 설정했는가
버전 관리
- [ ] 중요 데이터 버킷에 버전 관리가 활성화되어 있는가
- [ ] 이전 버전 정리를 위한 수명 주기 규칙이 설정되어 있는가
- [ ] 핵심 데이터에 MFA Delete를 검토했는가
수명 주기
- [ ] 데이터 접근 패턴에 맞는 전환 규칙이 설정되어 있는가
- [ ] 최소 보관 기간과 최소 객체 크기 제약을 확인했는가
- [ ] 미완료 멀티파트 업로드 정리 규칙이 있는가
- [ ] 비용 절감 효과를 정량적으로 검증했는가
암호화
- [ ] 기본 암호화가 활성화되어 있는가 (SSE-S3 또는 SSE-KMS)
- [ ] 규정 준수가 필요한 경우 SSE-KMS + 키 정책을 설정했는가
8. 정리
S3는 단순한 파일 저장소가 아니라, 접근 제어(Bucket Policy), 데이터 보호(Versioning), 비용 관리(Lifecycle)를 설계해야 하는 스토리지 플랫폼입니다.
설계 우선순위: 1. 보안 먼저 — Block Public Access 활성화, 최소 권한 정책 2. 데이터 보호 — 중요 데이터에 Versioning 활성화 3. 비용 최적화 — 접근 패턴 분석 후 Lifecycle 규칙 적용 4. 모니터링 — Storage Lens로 비용 추세 확인
이 순서를 무시하고 비용 최적화부터 시작하면, 보안 사고나 데이터 유실이 발생할 수 있습니다. 보안과 보호를 먼저 확보한 후, 비용을 줄이는 방향으로 설계하는 것이 운영 환경에서의 올바른 접근입니다.
관련 글
'Cloud > AWS' 카테고리의 다른 글
| AWS Lambda 기본 구조: 서버리스 아키텍처와 Cold Start 이해하기 (0) | 2026.06.07 |
|---|---|
| AWS ECS vs EKS 차이: 컨테이너 오케스트레이션 선택 기준 (0) | 2026.06.06 |
| ALB와 NLB 차이: 언제 어떤 Load Balancer를 선택할까 (0) | 2026.06.01 |
| AWS 3-Tier 아키텍처 설계 예시: Web, App, DB 계층 분리와 운영 전략 (0) | 2026.06.01 |
| Security Group과 NACL 차이: Stateful vs Stateless, 적용 범위, 운영 전략 (0) | 2026.05.31 |