리액트로 만든 SPA(Single Page Application)를 서비스에 배포할 때, 가장 많이 쓰이는 방법 중 하나가 AWS S3 + CloudFront로 배포하는 조합입니다.
정적 파일을 S3에 올리고, CloudFront로 캐싱과 HTTPS, 라우팅 처리를 하면 비용 대비 성능과 보안이 매우 좋습니다.
이 글에서는 다음과 같은 내용을 다룹니다.
React 빌드
AWS CLI로 S3에 업로드
CloudFront 배포 생성 및 SPA 라우팅 설정
리액트 프로젝트는 보통 아래 명령어로 빌드합니다.
npm run build
# 또는
yarn build
빌드 후 build 또는 dist 폴더가 생기는데, 이 폴더 안의 파일이 프로덕션용 정적 파일입니다.
이 폴더를 그대로 S3에 올리면 됩니다.
프로젝트 터미널에서 aws에 접근할 수 있도록 awscli를 설치합니다.
brew install awscli
aws --version
AWS 콘솔 → IAM → 사용자 생성
프로그래밍 방식 액세스 선택
AmazonS3FullAccess 또는 필요한 정책 부여
Access Key ID와 Secret Access Key 저장
발급받은 access key id와 secret access key를 등록해줍니다.
aws configure
Access Key ID
Secret Access Key
Region: ap-northeast-2 (서울)
Output format: json
S3 콘솔 → 버킷 생성 (예: my-react-app-2026)
퍼블릭 읽기 허용 또는 CloudFront OAC(Origin Access Control)로 접근 제어 설정
이 정책을 S3 버킷의 버킷 정책에 붙여넣기.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-react-app-2026/*"
}
]
}
이제 프로젝트 터미널에 들어가 프로젝트 루트에서 다음 명령어를 입력합니다.
로컬 빌드 폴더가 ./build인 경우 ./dist 대신 ./build를 작성하면 됩니다.
aws s3 sync ./dist s3://my-react-app-2026 --delete
./dist: 로컬 빌드 폴더
s3://my-react-app-2026: S3 버킷 이름
--delete: S3에 있지만 로컬에 없는 파일 삭제 (동기화용)
퍼블릭 읽기 필요 시
aws s3 sync ./build s3://my-react-app-2026 --delete --acl public-read
버킷에 들어가면 다음과 같은 폴더가 업로드된 것을 확인할 수 있습니다.

⚠️ CloudFront를 사용하지 않고 S3로만 배포할 경우 정적 웹 사이트 호스팅을 활성화해주세요!
버킷 > 속성 > 정적 웹 사이트 호스팅 > 편집


1. CloudFront 콘솔 → 배포 생성
2. 원본(Origin) 설정
원본 도메인: S3 버킷 선택
S3 버킷 액세스: Origin access control settings (recommended) 선택
기본 루트 객체: index.html
3. HTTPS 설정
Viewer protocol policy: Redirect HTTP to HTTPS
SSL certificate: CloudFront 기본 인증서
4. 배포 생성 후 Distribution Domain Name 복사
(예: d12345.cloudfront.net)
React Router를 쓰는 SPA는 모든 경로를 index.html로 보내야 합니다.
1. CloudFront 배포 선택 → 오류 페이지 탭
2. 403 에러에 대해:
HTTP 에러 코드: 403
커스텀 에러 응답: 예
HTTP 응답 코드: 200
응답 페이지 경로: /index.html
3. 404 에러도 동일하게 설정

이렇게 하면 /about, /user/123 같은 경로도 index.html을 내려주고, React Router가 라우팅을 처리합니다.
React 빌드 파일을 S3에 올리고 CloudFront로 캐싱과 HTTPS, 라우팅을 처리하면 SPA 배포가 매우 간단하고 안정적입니다.
특히 OAC를 사용하면 S3를 비공개로 유지하면서 CloudFront만 접근하게 할 수 있어 보안도 좋습니다.