AWS S3 + CloudFront로 Next.js 정적 사이트 배포하고 GitHub Actions 자동화하기
Next.js 기반 공개 사이트를 AWS에 올리면서, 비용은 낮게 유지하고 SEO와 운영 편의성은 챙기는 방향으로 배포 구성을 정리했다. 최종적으로는 castcanvaslab.com 본 사이트, www.castcanvaslab.com 리
다이렉트, GitHub Actions 자동 배포, robots.txt/sitemap.xml/OG 이미지까지 한 번에 마무리했다.
목표
- Next.js 공개 사이트를 S3 + CloudFront + Route 53 + ACM 구조로 운영 가능한 상태로 배포하기
- GitHub Actions를 통해
main브랜치 푸시 시 자동 배포되도록 구성하기
핵심 구현 포인트
1) Next.js를 정적 export 기반으로 고정
이 프로젝트는 퍼블릭 소개 사이트라서 서버 렌더링보다 정적 배포가 더 적합했다. next.config.ts에서 output: 'export'를 사용하고, 빌드 결과를 out/으로 생성하도록 구성했다.
로컬 환경에서는 Turbopack 빌드가 멈추는 문제가 있어서 next build --webpack으로 빌드 스크립트를 고정했다.
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'export',
trailingSlash: true,
images: {
unoptimized: true,
},
};
export default nextConfig;
2) AWS 배포 구조를 역할별로 분리
본 사이트는 private S3 bucket + CloudFront OAC 조합으로 구성했고, www는 별도 S3 website redirect bucket과 별도 CloudFront distribution으로 구성했다. 이 방식으로 castcanvaslab.com은 실제 콘텐츠를 서빙하고, www.castcanvaslab.com은 apex로 리다이렉트되도록 만들었다.
# GitHub Actions deploy workflow
name: Deploy Site
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm build
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
aws-region: ap-northeast-2
- run: aws s3 sync out/ s3://castcanvaslab.com --delete
- run: aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*"
———
트러블슈팅 / 고민 포인트
CloudFront 리다이렉트 배포에서 504 발생
- 원인: www 리다이렉트용 CloudFront origin을 S3 website endpoint로 연결했는데, origin protocol policy가 HTTPS only로 설정되어 있었다. S3 website endpoint는 HTTPS origin으로 붙는 구조가 아니라 HTTP origin으로 접근해야 한다.
- 해결: www용 CloudFront distribution의 origin type을 Other로 두고, S3 website endpoint를 사용한 뒤 Origin protocol policy를 HTTP only로 변경했다.
———
결과
- castcanvaslab.com은 S3 + CloudFront를 통해 정적 사이트로 정상 배포됐다.
- www.castcanvaslab.com은 별도 redirect distribution을 통해 https://castcanvaslab.com으로 리다이렉트되도록 구성됐다.
———
다음 개선 아이디어
- 실제 서비스 화면 기반의 OG 이미지로 교체해서 공유 미리보기 완성도 높이기
- Search Console에서 sitemap 제출과 인덱싱 요청까지 완료해 검색 노출 속도 개선하기