개발자라면 누구나 반복적인 배포 작업에서 벗어나고 싶어합니다. 코드를 작성하고 테스트한 후 매번 수동으로 빌드하고 배포하는 과정은 지루하고 시간 소모적입니다. 특히 팀 단위로 개발할 때는 배포 실수로 인한 문제가 발생할 수도 있죠.
이 글에서는 GitHub Actions를 활용하여 프론트엔드 애플리케이션을 AWS S3에 자동으로 배포하고, CloudFront CDN의 캐시를 무효화하는 배포 파이프라인을 구축하는 방법을 상세히 알아보겠습니다.
자동화 배포의 필요성
프론트엔드 애플리케이션을 배포할 때 다음과 같은 과정을 반복하게 됩니다:
- 코드 변경
- 의존성 설치
- 빌드
- AWS S3에 파일 업로드
- CloudFront 캐시 무효화
이 과정을 매번 수동으로 진행한다면 많은 시간이 낭비되고, human error가 발생할 가능성도 높아집니다. GitHub Actions를 사용하면 이 모든 과정을 자동화할 수 있으며, 코드를 Push하거나 PR이 Merge될 때마다 배포가 자동으로 이루어지게 할 수 있습니다.
사전 준비
자동화 배포 파이프라인을 구축하기 위해 필요한 것들은 다음과 같습니다:
- GitHub 계정과 리포지토리: 배포할 코드가 저장된 GitHub 리포지토리
- AWS 계정: S3와 CloudFront 서비스를 사용하기 위한 계정
- 배포용 S3 버킷: 웹사이트 호스팅으로 설정된 S3 버킷
- CloudFront 배포: S3 버킷에 연결된 CloudFront 배포 설정
- IAM 사용자: GitHub Actions가 AWS 리소스에 접근하기 위한 IAM 사용자
AWS IAM 설정
GitHub Actions가 AWS 리소스에 접근하기 위해서는 적절한 권한을 가진 IAM 사용자가 필요합니다.
- AWS 콘솔에서 IAM 서비스로 이동합니다.
- '사용자 추가'를 클릭하여 새 사용자를 생성합니다 (예: github-actions).
- 프로그래밍 방식 액세스 (Access key - Programmatic access)를 선택합니다.
- 다음과 같은 권한 정책을 연결합니다:
AmazonS3FullAccess
: S3 버킷 접근 및 파일 업로드 권한CloudFrontFullAccess
: CloudFront 배포 관리 및 캐시 무효화 권한
참고: 보안을 강화하려면 전체 액세스 대신 특정 S3 버킷과 CloudFront 배포에만 제한된 커스텀 정책을 생성하는 것이 좋습니다.
사용자 생성이 완료되면 액세스 키 ID와 비밀 액세스 키가 제공됩니다. 이 정보는 GitHub Secret에 저장해야 합니다.
S3 버킷 설정
배포 대상이 되는 S3 버킷에서 다음 설정이 필요합니다:
- 정적 웹사이트 호스팅 활성화
- 객체 소유권 설정:
- S3 > 버킷 선택 > 권한 > 객체 소유권
- ACL 활성화 & 객체 소유권을 "버킷 소유자 선호"로 설정
이 설정은 GitHub Actions가 --acl public-read
옵션을 사용하여 파일을 업로드할 때 필요합니다.
GitHub Secrets 설정
GitHub Actions 워크플로우에서 AWS 계정 정보를 안전하게 사용하기 위해 GitHub Secrets를 설정합니다:
- GitHub 리포지토리 페이지로 이동합니다.
- Settings > Secrets > Actions로 이동합니다.
- 다음 비밀을 추가합니다:
AWS_ACCESS_KEY_ID
: IAM 사용자의 액세스 키 IDAWS_SECRET_ACCESS_KEY
: IAM 사용자의 비밀 액세스 키AWS_REGION
: AWS 리전 (예: ap-northeast-2)PROD_S3_BUCKET_NAME
: 배포 대상 S3 버킷 이름AWS_CLOUDFRONT_DISTRIBUTION_ID
: CloudFront 배포 ID
GitHub Actions 워크플로우 작성
먼저 프로젝트 루트 디렉토리에 .github/workflows
폴더를 생성하고, 그 안에 워크플로우 파일(예: deploy.yml
)을 작성합니다.
기본적인 워크플로우 파일은 다음과 같습니다:
name: CI dev
on:
workflow_dispatch: # 수동 트리거 가능
# 필요에 따라 push나 pull request 트리거 추가 가능
# push:
# branches: [ main ]
jobs:
build-dev:
name: Build Image
runs-on: ubuntu-20.04
strategy:
matrix:
node-version: [16.x]
steps:
- name: Check out branch
uses: actions/checkout@v2
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
path: node_modules
key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-
- name: Install Dependencies
run: npm install
- name: Build
run: npm run build
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Deploy to S3
run: |
aws s3 sync ./dist s3://${{ secrets.PROD_S3_BUCKET_NAME }} --acl public-read --delete
- name: Invalidate cache CloudFront
run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }} \
--paths "/*"
전체 워크플로우 설명
작성한 GitHub Actions 워크플로우는 다음과 같은 단계로 진행됩니다:
- 체크아웃: 최신 코드를 가져옵니다.
- 노드 모듈 캐싱: 빌드 시간을 단축하기 위해 node_modules를 캐싱합니다.
- 의존성 설치: npm install로 필요한 패키지를 설치합니다.
- 빌드: npm run build로 프로젝트를 빌드합니다.
- AWS 인증 설정: AWS 자격 증명을 설정합니다.
- S3 배포: 빌드된 파일을 S3 버킷에 동기화합니다.
--acl public-read
: 업로드된 파일을 공개적으로 읽을 수 있게 설정--delete
: S3 버킷에 있지만 로컬에 없는 파일 삭제
- CloudFront 캐시 무효화: 배포된 파일의 캐시를 무효화하여 최신 버전이 사용자에게 제공되도록 합니다.
문제 해결 및 팁
1. S3 업로드 권한 문제
An error occurred (AccessDenied) when calling the PutObject operation
위와 같은 오류가 발생하면 다음을 확인하세요:
- IAM 사용자에 필요한 권한이 있는지 확인
- S3 버킷의 객체 소유권 설정이 올바른지 확인
- 버킷 정책에서 해당 IAM 사용자의 액세스를 허용하는지 확인
2. 빌드 출력 경로 조정
워크플로우 파일에서 S3 동기화 명령어의 소스 경로(./dist
)가 프로젝트의 빌드 출력 디렉토리와 일치하는지 확인하세요. React는 보통 build
, Vue.js는 dist
, Next.js는 .next
등 프레임워크별로 다른 출력 경로를 사용합니다.
3. 배포 최적화
대규모 프로젝트에서는 전체 파일을 매번 동기화하는 대신 변경된 파일만 업로드하는 전략을 고려할 수 있습니다. 하지만 --delete
옵션을 사용하여 전체 동기화를 유지하는 것이 보통 더 안전합니다.
4. 비용 고려
CloudFront 캐시 무효화는 월별 특정 횟수 이상 사용 시 비용이 발생할 수 있습니다. 개발 중 빈번한 배포가 필요한 경우, 비용 절감을 위해 특정 경로만 무효화하는 방법을 고려하세요.
마무리
GitHub Actions를 활용한 AWS S3 및 CloudFront 배포 자동화 파이프라인 구축 방법에 대해 알아보았습니다. 이 자동화 프로세스를 통해 개발자는 반복적인 배포 작업에서 벗어나 더 중요한 코드 개발에 집중할 수 있습니다.
더 복잡한 시나리오에서는 다음과 같은 추가 기능을 고려해볼 수 있습니다:
- 환경별(개발, 스테이징, 프로덕션) 배포 설정
- 배포 전 자동 테스트 실행
- Slack 또는 이메일을 통한 배포 알림
- 배포 롤백 전략
CI/CD 파이프라인은 개발 생산성을 크게 향상시키는 중요한 도구입니다. 한 번 설정해두면 배포 과정의 일관성과 안정성이 크게 향상되므로, 팀 프로젝트에서는 반드시 고려해야 할 요소입니다.
참고 자료: