0611 AWS 운영 실무 기초 (4/N): S3와 CloudFront 정적 파일 운영
✅ 1. S3란 무엇인가?
- S3(Simple Storage Service)는 AWS에서 제공하는 객체 스토리지 서비스입니다.
- 이미지, 첨부파일, 백업 파일, 로그 파일, React 빌드 결과물 같은 정적 파일을 저장할 수 있습니다.
- EC2 서버 디스크에 파일을 직접 저장하는 대신 S3를 사용하면 파일 관리, 백업, 확장성, 서버 교체 측면에서 유리합니다.
➕ 1-1. S3를 사용하는 이유
-
서버 디스크 부담 감소
- 이미지와 첨부파일을 EC2에 저장하면 서버 용량이 빠르게 찰 수 있습니다.
- S3에 저장하면 EC2는 애플리케이션 실행에 집중할 수 있습니다.
-
서버 교체에 유리
- EC2 서버를 새로 만들거나 교체해도 S3에 있는 파일은 유지됩니다.
-
대량 파일 저장에 적합
- 상품 이미지, 이벤트 배너, 사용자 업로드 파일처럼 파일이 계속 늘어나는 서비스에 적합합니다.
-
CloudFront와 연결 가능
- S3에 저장된 파일을 CDN으로 빠르게 제공할 수 있습니다.
✅ 2. S3의 기본 개념
➕ 2-1. 버킷
- 버킷(Bucket)은 S3에서 파일을 담는 최상위 저장 공간입니다.
- 하나의 프로젝트나 서비스 단위로 버킷을 나누어 관리할 수 있습니다.
예시:
togethermall-prod-assets
togethermall-dev-assets
togethermall-backups
- 운영과 개발 환경의 파일이 섞이지 않도록 버킷 또는 경로를 분리하는 것이 좋습니다.
➕ 2-2. 객체
- 객체(Object)는 S3에 저장되는 실제 파일입니다.
- 이미지, PDF, 엑셀, ZIP, 로그 파일 등이 객체가 될 수 있습니다.
banners/galaxy-s25-main.webp
products/iphone-16/detail-01.png
uploads/consults/attachment.pdf
backups/db/backup_20260611.sql
➕ 2-3. Key
- Key는 S3 안에서 파일을 식별하는 경로입니다.
- 일반 파일 시스템의 폴더처럼 보이지만, 실제로는 문자열 기반의 객체 경로입니다.
banners/2026/galaxy-s25-main.webp
| 구분 | 의미 |
|---|
banners | 파일 분류 |
2026 | 연도 또는 캠페인 |
galaxy-s25-main.webp | 파일명 |
- DB에는 전체 URL보다 S3 key를 저장해두면 나중에 CDN 도메인이 바뀌어도 유연하게 대응할 수 있습니다.
✅ 3. S3에 저장하기 좋은 파일
➕ 3-1. 이미지 파일
- 상품 이미지
- 이벤트 배너
- 상세페이지 이미지
- 관리자 업로드 이미지
- 프로필 이미지
- 리뷰 이미지
➕ 3-2. 문서와 첨부파일
- 신청서
- 계약 관련 문서
- 엑셀 업로드 파일
- 관리자 다운로드 파일
- PDF 안내 자료
➕ 3-3. 백업 파일
- DB 덤프 파일
- 서버 설정 백업
- 로그 아카이브
- 업로드 파일 압축본
주의:
개인정보가 포함된 백업 파일은 공개 접근을 절대 허용하면 안 됩니다.
✅ 4. S3 버킷 공개 설정
- S3를 사용할 때 가장 조심해야 하는 부분은 공개 접근 설정입니다.
- 파일을 보여줘야 한다고 해서 버킷 전체를 public으로 열면 위험합니다.
➕ 4-1. 공개 파일과 비공개 파일 구분
| 파일 종류 | 공개 여부 |
|---|
| 상품 이미지 | 공개 가능 |
| 이벤트 배너 | 공개 가능 |
| React 정적 파일 | 공개 가능 |
| 사용자 개인정보 첨부파일 | 비공개 |
| DB 백업 파일 | 비공개 |
| 관리자 내부 문서 | 비공개 |
- 공개되어도 되는 파일과 절대 공개되면 안 되는 파일을 경로부터 분리하는 것이 좋습니다.
public/products/
public/banners/
private/consults/
private/backups/
private/documents/
➕ 4-2. 버킷 전체 Public은 피하기
위험한 방식:
S3 버킷 전체 public 허용
권장 방식:
필요한 파일만 CloudFront 또는 제한된 정책으로 제공
- 운영에서는 S3 버킷을 직접 public으로 열기보다 CloudFront를 앞에 두고 접근을 제어하는 구조가 더 안전합니다.
✅ 5. S3 권한 관리
- S3 파일 접근은 IAM 정책, 버킷 정책, ACL, CloudFront 설정 등으로 제어할 수 있습니다.
- 권한 설정이 복잡해질 수 있으므로 처음부터 단순하고 명확하게 설계하는 것이 좋습니다.
➕ 5-1. IAM 권한
- 백엔드 서버가 S3에 파일을 업로드하려면 S3 접근 권한이 필요합니다.
- 이때 모든 S3 권한을 주는 것보다 필요한 버킷과 작업만 허용해야 합니다.
필요한 권한 예시:
s3:PutObject
s3:GetObject
s3:DeleteObject
s3:ListBucket
- 운영 원칙은 최소 권한입니다.
- 파일 업로드만 필요한 서버에 모든 AWS 관리자 권한을 주면 안 됩니다.
➕ 5-2. Access Key 주의
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=ap-northeast-2
AWS_S3_BUCKET=togethermall-prod-assets
- Access Key는 서버 환경변수나 Secret Manager에서 관리해야 합니다.
- 프론트엔드 코드에 넣으면 절대 안 됩니다.
- GitHub에 올라가면 즉시 폐기하고 새로 발급해야 합니다.
✅ 6. 백엔드에서 S3 업로드 흐름
- 파일 업로드는 보통 백엔드 서버를 거쳐 S3로 저장합니다.
프론트엔드
↓ 파일 선택
백엔드 API
↓ 파일 검증
S3 업로드
↓ key/url 반환
DB에 메타데이터 저장
↓
프론트엔드에 결과 응답
➕ 6-1. 백엔드에서 처리할 것
- 로그인/관리자 권한 확인
- 파일 존재 여부 확인
- 파일 크기 제한
- MIME 타입 검증
- 안전한 파일명 생성
- S3 key 생성
- S3 업로드
- DB에 파일 정보 저장
- 실패 시 로그 기록
✅ 7. S3 Key 설계
- S3 key는 나중에 파일을 찾고 정리하기 쉽게 설계해야 합니다.
- 처음부터 아무렇게나 저장하면 시간이 지날수록 관리가 어려워집니다.
➕ 7-1. 좋은 Key 예시
banners/2026/06/galaxy-s25-main-uuid.webp
products/galaxy-s25/detail-uuid.webp
uploads/consults/2026/06/uuid.pdf
backups/db/2026/06/11/backup.sql
➕ 7-2. Key 설계 기준
- 파일 종류별로 구분
- 날짜 또는 캠페인 기준으로 구분
- 원본 파일명을 그대로 사용하지 않기
- UUID 또는 해시값 사용
- 공개 파일과 비공개 파일 경로 분리
피해야 할 예시:
최종.png
banner.png
홍길동_신분증.png
../../../app.js
✅ 8. CloudFront란 무엇인가?
- CloudFront는 AWS의 CDN 서비스입니다.
- S3나 서버에 있는 파일을 사용자와 가까운 캐시 서버에서 빠르게 제공해줍니다.
- 이미지가 많은 사이트, 이벤트 페이지, 쇼핑몰, 정적 프론트엔드 배포에 자주 사용됩니다.
➕ 8-1. CloudFront를 사용하는 이유
- 이미지 로딩 속도 개선
- S3 직접 접근 최소화
- 트래픽 분산
- 캐싱을 통한 비용 절감
- HTTPS 적용
- 사용자 위치에 가까운 서버에서 콘텐츠 제공
사용자
↓
CloudFront
↓
S3
✅ 9. S3 단독 사용과 CloudFront 사용 비교
| 구분 | S3 단독 | S3 + CloudFront |
|---|
| 속도 | 리전에 따라 차이 있음 | CDN 캐시로 빠름 |
| HTTPS | 가능하지만 도메인 구성 제한 | 커스텀 도메인 HTTPS 구성 쉬움 |
| 보안 | 버킷 public 설정 주의 | S3 직접 접근 제한 가능 |
| 캐싱 | 제한적 | 세밀한 캐시 정책 가능 |
| 비용 | 단순 구조 | 트래픽에 따라 더 효율적일 수 있음 |
- 작은 테스트는 S3 단독으로도 가능하지만, 운영 서비스에서는 CloudFront를 붙이는 것이 더 안정적입니다.
✅ 10. CloudFront 캐싱
- CloudFront는 원본 파일을 캐시 서버에 저장해두고, 다음 요청부터 더 빠르게 응답합니다.
- 캐싱은 성능에 좋지만, 파일 변경 반영이 늦어질 수 있습니다.
➕ 10-1. 캐싱이 잘 맞는 파일
main.a1b2c3.js
style.x9y8z7.css
banner.0f4b7f8e.webp
product-detail.uuid.webp
- 파일명에 해시나 UUID가 들어가면 장기 캐싱에 적합합니다.
- 파일 내용이 바뀌면 파일명도 바뀌기 때문입니다.
Cache-Control: public, max-age=31536000, immutable
➕ 10-2. 캐싱을 짧게 해야 하는 파일
index.html
robots.txt
sitemap.xml
index.html은 새 배포 시 빠르게 바뀌어야 합니다.
- 너무 길게 캐싱하면 사용자가 오래된 JS/CSS를 바라볼 수 있습니다.
Cache-Control: no-cache
✅ 11. CloudFront Invalidation
- Invalidation은 CloudFront 캐시를 강제로 비우는 작업입니다.
- 원본 파일을 바꿨는데 사용자에게 이전 파일이 계속 보일 때 사용할 수 있습니다.
➕ 11-1. Invalidation 예시
/*
/index.html
/assets/*
/banners/galaxy-s25-main.webp
/*는 전체 캐시 무효화입니다.
- 편하지만 너무 자주 사용하면 비용과 운영 부담이 생길 수 있습니다.
➕ 11-2. 더 좋은 전략
파일을 덮어쓰기보다 새 파일명으로 업로드하기
기존:
banner.webp
변경:
banner.20260611.uuid.webp
- 파일명이 바뀌면 캐시 무효화를 자주 하지 않아도 됩니다.
- 특히 배너나 상품 이미지는 UUID 기반 파일명을 사용하는 것이 안전합니다.
✅ 12. React 정적 파일을 S3 + CloudFront로 배포
- React/Vite 프로젝트는 빌드하면 정적 파일이 생성됩니다.
- 이 파일을 S3에 업로드하고 CloudFront로 제공할 수 있습니다.
➕ 12-1. 배포 흐름
React 프로젝트
↓ npm run build
dist 폴더 생성
↓
S3 업로드
↓
CloudFront 배포
↓
도메인 연결
➕ 12-2. AWS CLI 업로드 예시
npm run build
aws s3 sync dist/ s3://togethermall-prod-front/ --delete
--delete는 S3에만 남아 있는 오래된 파일을 삭제합니다.
- 실수하면 필요한 파일도 삭제될 수 있으므로 배포 경로를 정확히 확인해야 합니다.
✅ 13. SPA 라우팅과 CloudFront
- React Router를 사용하는 SPA에서는
/event/galaxy 같은 경로로 직접 접속할 수 있어야 합니다.
- S3/CloudFront는 기본적으로 해당 경로의 실제 파일을 찾기 때문에 설정이 없으면 403 또는 404가 발생할 수 있습니다.
➕ 13-1. 문제 상황
https://www.example.com
→ 정상
https://www.example.com/event/galaxy
→ 새로고침 시 404 또는 403
➕ 13-2. 해결 개념
- 없는 경로 요청이 들어오면
index.html을 반환하게 해야 합니다.
- 그러면 React Router가 브라우저에서 해당 경로를 처리합니다.
/event/galaxy 요청
↓
CloudFront/S3가 index.html 반환
↓
React Router가 /event/galaxy 화면 렌더링
✅ 14. 이미지 최적화와 S3
- S3에 이미지를 저장할 때 원본 이미지를 그대로 제공하면 용량이 너무 클 수 있습니다.
- 이미지 최적화는 사용자 경험, SEO, 광고 랜딩 속도에 영향을 줍니다.
➕ 14-1. 이미지 최적화 기준
- WebP 또는 AVIF 사용
- 모바일/PC용 크기 분리
- 썸네일 생성
- 원본 이미지 보관 여부 결정
- 파일명에 해시 또는 UUID 포함
alt 텍스트 관리
- CloudFront 캐싱 적용
➕ 14-2. 예시 구조
products/galaxy-s25/original/uuid.png
products/galaxy-s25/optimized/320_uuid.webp
products/galaxy-s25/optimized/768_uuid.webp
products/galaxy-s25/optimized/1200_uuid.webp
- 실제 화면 크기에 맞는 이미지를 내려주면 트래픽과 로딩 속도를 개선할 수 있습니다.
✅ 15. S3 Lifecycle 정책
- Lifecycle 정책은 S3 객체를 일정 기간 후 자동으로 이동하거나 삭제하는 기능입니다.
- 백업 파일, 임시 파일, 오래된 로그 파일 관리에 유용합니다.
➕ 15-1. Lifecycle이 필요한 경우
- 오래된 DB 백업 삭제
- 임시 업로드 파일 자동 삭제
- 로그 파일 장기 보관 스토리지로 이동
- 사용하지 않는 파일 정리
- 비용 절감
➕ 15-2. 예시 정책
backups/db/
- 30일 후 Glacier로 이동
- 180일 후 삭제
tmp/uploads/
- 7일 후 삭제
logs/
- 90일 후 삭제
- 운영 데이터 삭제 정책은 신중해야 합니다.
- 개인정보나 계약 관련 파일은 법적 보관 기간도 고려해야 합니다.
✅ 16. Presigned URL
- Presigned URL은 일정 시간 동안만 접근 가능한 임시 URL입니다.
- 비공개 S3 파일을 안전하게 다운로드하거나 업로드할 때 사용할 수 있습니다.
➕ 16-1. 필요한 상황
- 관리자만 첨부파일 다운로드
- 개인정보 파일 제한 접근
- 임시 업로드 URL 발급
- 비공개 문서 다운로드
- 일정 시간 후 만료되는 파일 링크
➕ 16-2. 예시 흐름
관리자
↓ 다운로드 요청
백엔드
↓ 권한 확인
S3 Presigned URL 생성
↓
관리자에게 임시 URL 반환
↓
일정 시간 후 URL 만료
- 비공개 파일을 public으로 열지 않고도 필요한 사용자에게만 접근을 허용할 수 있습니다.
✅ 17. S3 운영 중 자주 발생하는 문제
➕ 17-1. 이미지가 안 보임
-
가능한 원인:
- S3 객체가 없음
- key가 잘못 저장됨
- 버킷 정책 문제
- CloudFront 캐시 문제
- 파일 MIME 타입 문제
- URL 인코딩 문제
➕ 17-2. 업로드 실패
-
가능한 원인:
- IAM 권한 부족
- Access Key 오류
- 버킷 이름 오류
- 리전 불일치
- 파일 크기 제한 초과
- 백엔드 환경변수 누락
➕ 17-3. 예전 이미지가 계속 보임
-
가능한 원인:
- CloudFront 캐시가 남아 있음
- 브라우저 캐시가 남아 있음
- 같은 파일명으로 덮어쓰기
- Cache-Control이 너무 길게 설정됨
✅ 18. 실무 체크리스트
➕ 18-1. S3 설계 체크리스트
- 운영/개발 버킷 또는 경로가 분리되어 있는가?
- 공개 파일과 비공개 파일 경로가 분리되어 있는가?
- S3 key 규칙이 정해져 있는가?
- 원본 파일명을 그대로 저장 경로에 쓰지 않는가?
- 오래된 파일 정리 정책이 있는가?
- DB에는 URL보다 key를 저장하는 구조인가?
➕ 18-2. 보안 체크리스트
- 버킷 전체 public 설정을 피했는가?
- Access Key가 프론트엔드에 노출되지 않았는가?
- IAM 권한이 최소 권한으로 되어 있는가?
- 비공개 파일은 Presigned URL을 사용하는가?
- 백업 파일이 public 경로에 있지 않은가?
- 개인정보 파일 접근 로그를 확인할 수 있는가?
➕ 18-3. CloudFront 체크리스트
- S3 앞에 CloudFront를 연결했는가?
- HTTPS 인증서가 연결되어 있는가?
- 캐시 정책이 파일 종류별로 적절한가?
- SPA 라우팅 새로고침 문제가 해결되어 있는가?
- 캐시 무효화 전략이 있는가?
- 이미지 파일명에 UUID 또는 해시를 사용하는가?
✅ 19. AI를 활용해 S3/CloudFront 문제를 해결할 때 질문법
- S3와 CloudFront 문제는 권한, 캐시, key, 도메인, MIME 타입이 섞여서 발생합니다.
- AI에게 질문할 때는 “파일이 어디에 있고, 어떤 URL로 접근했고, 어떤 에러가 나는지”를 같이 알려줘야 합니다.
➕ 19-1. 좋은 질문 예시
AWS S3 + CloudFront로 상품 이미지를 제공하고 있는데 이미지가 브라우저에서 안 보여.
상황:
1. 이미지는 S3에 업로드되어 있음
2. DB에는 S3 key를 저장함
3. CloudFront 도메인으로 이미지 URL을 만들고 있음
4. 브라우저에서는 403 Forbidden 발생
5. S3 버킷은 public access block이 켜져 있음
6. CloudFront를 통해서만 접근시키고 싶음
확인해야 할 설정과 가능한 원인을 알려줘.
S3 버킷 정책, CloudFront 원본 접근 설정, key 확인 순서로 설명해줘.
➕ 19-2. AI 답변 검증 기준
- 무조건 버킷을 public으로 열라고 하지 않는가?
- S3 key와 실제 객체 존재 여부를 확인하는가?
- CloudFront 캐시 문제를 고려하는가?
- OAC/OAI 같은 원본 접근 제어 개념을 설명하는가?
- Access Key를 프론트엔드에 넣으라고 하지 않는가?
- 공개 파일과 비공개 파일을 구분하는가?
- Presigned URL이 필요한 상황을 구분하는가?
📌 요약
- S3는 이미지, 첨부파일, 백업, 정적 파일을 저장하는 AWS 객체 스토리지입니다.
- S3에서는 버킷, 객체, key 개념을 이해해야 하며, DB에는 URL보다 key를 저장하는 구조가 유연합니다.
- 운영에서는 S3 버킷 전체를 public으로 열기보다 CloudFront를 통해 필요한 파일만 제공하는 구조가 안전합니다.
- CloudFront는 S3 파일을 CDN으로 빠르게 제공하고, HTTPS와 캐싱 전략을 적용할 수 있게 해줍니다.
- 파일명에 UUID나 해시를 붙이면 캐시 문제를 줄이고 장기 캐싱을 적용하기 쉽습니다.
- React SPA를 S3 + CloudFront로 배포할 때는 새로고침 시
index.html이 반환되도록 설정해야 합니다.
- 비공개 파일은 public URL 대신 Presigned URL을 사용해 일정 시간 동안만 접근하게 만들 수 있습니다.
- S3/CloudFront 운영의 핵심은 권한, 캐시, key 설계, 파일 공개 범위, 비용 정리 정책을 명확히 관리하는 것입니다.