Vuejs 기반 static page AWS CloudFront + S3로 배포
2020년 07월 17일

aws s3

vuejs 같은 경우는 static page로써 lambda에 배포하기에는 부적절합니다.

리서치해본 결과 aws s3에 많이 배포한다고 합니다. Vuejs 공식 문서에도 언급되어 있습니다.

Deployment | Vue CLI

또한 AWS 공식 문서에도 s3 버킷을 이용하여 static website를 관리하는 방법이 잘 나와있습니다.

Amazon S3 버킷에서 호스팅하는 웹 사이트로 트래픽 라우팅

체크할 점으로는 버킷명이 도메인명과 동일해야 한다는 점입니다.

그 후 업로드 자체는 정말 쉽습니다. 빌드 후 aws s3 sync만 하면 되기 때문입니다.

# github action yml 일부 ... - 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: ap-northeast-2 - name: sync to s3 run: aws s3 sync ./dist s3://버킷명 --delete ...

cloudfront

업로드가 성공했으니 이제 route53 도메인 연결, TLS 인증서 적용만 해주면 됩니다.

리서치해보면 인증서 적용을 위해서는 s3와 route53 사이에 cloudfront를 두어야 한다고 합니다.

CloudFront를 사용하여 Amazon S3에서 호스팅되는 정적 웹 사이트 제공

문서를 따라해보면 여기까지도 어렵지 않습니다. 다만 실제 배포를 해보면 코드가 바로 반영되지 않는데, 그 이유는 cloudfront 단에서 기본적으로 캐싱을 하기 때문입니다.

해결 방법으로는

  1. 옵션에서 TTL을 일괄 0으로 설정
  2. 배포 직후 invalidation이라는 일종의 캐시 무효화 작업을 생성
  3. s3 객체(파일)에 메타데이터를 추가하여 캐싱이 되지 않도록 하는 방법

이 있는데 저 invalidation 작업이 생각보다 시간이 오래 소요되어 피하고 싶고, 일부 파일은 캐싱을 시키고 싶었기 때문에 3번 방법을 택했습니다.

즉 s3에 파일 업로드 시 캐싱을 원하지 않는 파일에만 metadata를 추가해 배포하면 이슈가 해결됩니다.

aws s3 sync ./dist s3://dev.just1s.xyz --exclude "*.js*" --delete aws s3 sync ./dist s3://dev.just1s.xyz --exclude "*" --include "*.js*" --metadata-directive COPY --cache-control max-age=0,no-cache,no-store,must-revalidate --delete

위와 같이 하면 static asset 등 js가 아닌 파일은 그대로 배포, js 파일 들은 cache-control metadata 가 추가된 채로 배포가 됩니다.

결론

최종 development branch 배포 github action yaml은 다음과 같습니다.

name: Deploy to Development on: push: branches: - development jobs: build_vue: name: Build Vue runs-on: ubuntu-latest env: NODE_ENV: "development" steps: - name: checkout uses: actions/checkout@master - name: setup node uses: actions/setup-node@v1 with: node-version: "12" - name: Cache node modules uses: actions/cache@v2 with: path: | **/node_modules key: ${{ runner.OS }}-build-${{ hashFiles('**/package-lock.json') }} - name: npm install run: npm install - name: Build run: npm run build:development - 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: ap-northeast-2 - name: sync to s3 exclude js run: aws s3 sync ./dist s3://dev.just1s.xyz --exclude "*.js*" --delete - name: sync to s3 js with disabled cache run: aws s3 sync ./dist s3://dev.just1s.xyz --exclude "*" --include "*.js*" --metadata-directive COPY --cache-control max-age=0,no-cache,no-store,must-revalidate --delete