S3의 구조, 비용, 보안 판단 기준
S3를 버킷, 객체, Key 구조로 이해하고, 스토리지 클래스와 Lifecycle Policy, 보안 설정, 장애 증상을 실무 관점에서 정리한다. CloudFront 연동과 S3 Express One Zone의 선택 기준까지 함께 다룬다.
Script Companion
오디오와 함께 스크립트 보기
- 01
S3는 이미지, 로그, 백업, 정적 파일, 데이터 아카이브처럼 거의 모든 종류의 파일 저장에 쓰이는 AWS의 기본 서비스다. 핵심은 파일을 서버 디스크에 두는 방식이 아니라, 객체 스토리지로 다루는 것이다. 버킷은 파일을 담는 최상위 컨테이너이고, 버킷 이름은 전 세계적으로 고유해야 한다. 객체는 S3에 저장된 파일 하나이며, 파일 자체와 메타데이터로 구성된다. 이 객체는 Key로 식별되므로, 운영 중에는 버킷과 Key를 함께 정확히 추적하는 습관이 중요하다.
- 02
S3를 일반 파일시스템처럼 이해하면 자주 헷갈린다. S3는 폴더가 실제로 존재하는 구조가 아니라, 평탄한 Flat 구조를 가진다. 예를 들어 images 아래 profile 파일이 있는 것처럼 보이더라도, 실제로는 슬래시가 포함된 긴 Key를 가진 객체 하나다. AWS 콘솔이 슬래시를 기준으로 나누어 보여주기 때문에 폴더처럼 느껴질 뿐이다. 그래서 파일이 보이지 않거나 다른 위치에 올라간 것처럼 보일 때는 먼저 실제 저장된 Key가 무엇인지 확인해야 한다.
- 03
내구성 측면에서 S3는 데이터를 여러 AZ에 분산 저장하고, Erasure Coding으로 일부 디스크 손상에도 복구할 수 있게 설계되어 있다. 공식 내구성은 99.999999999%, 이른바 11-nine이다. 다만 이 높은 내구성과 별개로, 접근 권한이나 비용 정책은 사용자가 직접 판단해야 한다. 스토리지 클래스가 그 판단의 중심이다. Standard는 자주 접근하는 데이터의 기본값이고, Infrequent Access는 가끔 접근하는 데이터를 더 저렴하게 저장하지만 최소 30일 보관 요구가 있다. Glacier Instant Retrieval은 아카이브이면서 즉시 복원이 가능하고 최소 90일 보관이 필요하며, Glacier Deep Archive는 더 저렴하지만 복원에 12시간이 걸리고 최소 180일 보관이 필요하다.
- 04
비용 최적화의 핵심은 Lifecycle Policy다. 업로드한 지 30일이 지난 로그 파일은 Infrequent Access로 옮기고, 90일이 지나면 Glacier로 보내고, 365일이 지나면 삭제하는 식의 자동 파일 정리 규칙을 둘 수 있다. 문서에서는 일반적인 Lifecycle 전략으로 스토리지 비용을 30에서 70%까지 줄일 수 있다고 설명한다. 단, IA나 Glacier 계열로 전환한 뒤 최소 보관 기간 전에 삭제하면 남은 기간에 대한 요금이 부과될 수 있다. 접근 패턴을 예측하기 어렵다면 Intelligent-Tiering이 좋은 선택지다. Frequent Access, Infrequent Access, Archive Instant Access 세 계층을 자동으로 이동하며 별도 검색 비용은 없지만, 128KB 미만 객체는 자동 티어 이동이 안 되고 객체당 월 0.0025달러의 모니터링 요금이 붙는다.
- 05
보안에서는 기본값을 믿되, 공개 설정을 함부로 풀지 않는 것이 출발점이다. S3 버킷은 기본적으로 비공개이고, Block Public Access 설정이 기본으로 켜져 있다. 이 설정을 끄면 전 세계 누구나 버킷 내용에 접근할 수 있으므로, 개인정보, 로그, 백업이 있는 버킷은 절대 퍼블릭으로 열지 않는다. 접근 권한은 Bucket Policy와 IAM Policy를 함께 봐야 한다. 버킷 레벨 정책과 사용자 또는 역할 레벨 정책이 맞물려 누가 읽고 쓸 수 있는지 결정된다. 하드닝 항목으로는 HTTP 요청 차단을 통한 HTTPS 강제, Default Encryption을 통한 서버 사이드 암호화 강제, GuardDuty의 S3 위협 탐지가 제시된다.
- 06
비공개 버킷에서 특정 사용자에게만 임시 접근을 주고 싶을 때 Presigned URL을 쓴다. 문서의 비유로는 일회용 입장권에 가깝다. 버킷은 잠겨 있지만, 이 URL을 가진 사람은 지정된 시간 동안 특정 파일에 접근할 수 있다. 사용자가 파일을 업로드하거나 다운로드할 때 서버가 Presigned URL을 생성해 클라이언트에게 전달하고, 클라이언트는 S3에 직접 업로드하거나 다운로드한다. 이렇게 하면 서버를 거치지 않아 트래픽을 줄일 수 있다. 다만 2025년 AWS 보안 권고로는 Presigned URL의 유효 시간을 최대 15분으로 제한하는 것이 권장된다. 유출됐을 때 피해 범위를 줄이기 위해서다.
- 07
운영 중 자주 만나는 실패 모드도 S3 이해의 일부다. 대량 업로드나 다운로드 중 503 Slow Down이 반복되면, 동일한 prefix에 요청이 몰려 파티션이 포화된 상황일 수 있다. S3는 prefix 단위로 파티셔닝하며, 공식 기준으로 파티션당 초당 3,500 PUT, COPY, POST, DELETE와 5,500 GET, HEAD 처리 한도가 언급된다. 높은 요청률이 지속되면 내부적으로 파티션을 추가 분할하지만, 그 과정은 점진적이라 완료 전까지 503이 날 수 있다. 대량 삭제에서는 더 위험한 경우도 있다. 503 재시도 뒤 HTTP 200과 Deleted 빈 배열이 반환되어, 실제로는 0건 삭제됐는데 성공처럼 보인 버그가 보고된 적이 있다. 그래서 대량 삭제는 SDK 버전을 최신으로 고정하고, 응답의 Deleted 개수와 요청 개수를 항상 비교해야 한다.
- 08
접근 거부와 업로드 문제는 증상별로 원인을 좁혀야 한다. 403 Forbidden이나 AccessDenied가 나면 IAM Policy에 GetObject 또는 PutObject 권한이 없는지, Bucket Policy가 해당 IAM Role을 명시적으로 Deny하는지, 또는 Block Public Access가 켜진 버킷에 퍼블릭 접근을 시도하는지 확인한다. Presigned URL에서 Request has expired가 나오면 만료 시간 초과이고, SignatureDoesNotMatch는 서버 시계가 AWS와 5분 이상 차이 나거나 업로드 시 ContentType이 URL 생성 때와 다를 때 발생할 수 있다. 400 Bad Request는 Presigned URL 요청에 Authorization 헤더를 추가했을 때도 나온다. 브라우저에서 직접 업로드하거나 다운로드할 때 CORS 에러가 나면, 버킷 CORS 설정에 현재 도메인의 HTTP 메서드가 허용되어 있는지 봐야 한다.
- 09
프론트엔드 관점에서는 정적 파일 제공 구조를 S3와 CloudFront 조합으로 이해하면 좋다. Netlify나 Vercel이 알아서 CDN으로 정적 파일을 제공하는 경험을 AWS에서 직접 구성하면, S3 버킷은 비공개로 유지하고 CloudFront만 Origin Access Control로 접근 권한을 갖는 구조가 된다. S3 버킷을 퍼블릭으로 열어 직접 서빙하면 CloudFront 캐시가 없어서 S3 요청 비용이 직접 청구되고, 리전이 한국이면 해외 사용자는 느릴 수 있으며, 잘못된 버킷 정책으로 전체 데이터가 노출될 위험도 있다. CloudFront를 앞에 두면 캐시 히트율로 S3 요청 비용을 90% 줄일 수 있고, 전 세계 엣지 서버로 빠르게 응답하면서도 S3 버킷은 비공개로 유지할 수 있다.
- 10
S3 Express One Zone은 2024년 말 출시 후 2025년 4월에 가격이 대폭 낮아진 고성능 스토리지 클래스다. 스토리지는 31%, GET 요청은 85% 가격 인하가 언급되며, S3 Standard 대비 10배 빠른 접근 속도와 단일 자릿수 밀리초 지연시간, 초당 200만 요청의 최대 처리량을 제공한다. 대신 단일 AZ에 저장되므로 내구성 판단이 완전히 달라진다. DB 백업, 트랜잭션 로그, 소스 코드, 계약 문서처럼 재생산 불가능한 원본이나, 금융과 의료처럼 다중 AZ 보관 의무가 있는 데이터에는 쓰면 안 된다. 판단 기준은 AZ가 통째로 사라져도 재계산이나 재학습으로 재생산 가능한가이다. 핵심 데이터셋은 Standard에 두고, 핫 워킹셋만 Express One Zone으로 미러링하는 2-tier 패턴이 문서의 안전한 선택지다.
같은 레이어
L3에서 이어 듣기
- 오디오 파일
- /podcasts/l3-s3-basics.mp3