CSR 배포 전략 with S3, Cloud Front, Github Actions

noopy·2022년 4월 11일
6

🔁 배포와 자동화

목록 보기
4/4

이전 글에서 AWS의 S3, EC2, Cloud Front에 대해 간략히 알아보았다. 이번에는 기존에 만들어놓았던 리액트 프로젝트를 S3와 Cloud Front로 배포하고 Github Actions를 통해 간단히 자동화해볼 것이다.

📝 CSR 배포 전략

CSR은 보통 HTML, CSS, JavaScript + 정적 리소스들을 바탕으로 수행되곤 한다.
S3는 정적 리소스를 대규모로 저장하는데 특화되어 있고, CloudFront는 캐싱기능과 전 세계 다양한 사용자들에게 빠른 속도로 전달하거나 https를 이용할 수 있기 때문에 S3 + CloudFront 로 CSR을 배포하기에 적절하다고 생각한다.

CI/CD를 구축하기 위해 github-actions도 사용해보자.

Amplify

요즘은 AWS Amplify라는 기능으로 간단하게 CI/CD를 구축하고 클릭 몇번으로 배포를 자동화할 수 있다고 한다. 다만 추상화 레벨이 높기 때문에 디테일적인 부분을 처리하기에 불편함이 있기도 하고, AWS의 전체적인 흐름을 이해하기 위해선 Amplify보단 직접 인스턴스를 구축하는 것이 좋을 것이라 생각된다.

S3 + CloudFront

github actions에서 사용할 aws credentials를 위해 IAM 계정을 생성해야 한다.

S3, CloudFront 접근 권한 추가

주소창에 IAM을 검색 후 엑세스관리의 사용자 메뉴에서 사용자 추가 버튼을 누른다.

임의의 이름을 설정 후 엑세스 유형을 엑세스 키 - 프로그래밍 방식 엑세스로 선택한다.

사용자 추가에서 기존 정책 직접 연결 탭을 누른다.
S3, CloudFront 를 사용할 것이므로 AmazonS3FullAccess, CloudFrontFullAcess 권한을 추가한다.


검토 > 사용자 만들기 이후에 엑세스 키 ID비밀 엑세스 키가 생성된다.

두 키를 깃허브 레포지토리의 Secrets에 저장해주면 workflow에서 접근할 수 있다.

S3 버킷 생성

S3에서 버킷을 생성하기 위해 고유한 이름을 입력하고 리전을 선택한다.

현재 버킷의 엑세스 권한을 내 계정에서만 주기 위해 ACL을 비활성화한다.

퍼블릭 엑세스를 허용하게 되면 S3를 통해 정적 호스팅이 가능하다. 우리는 CloudFront를 통해 캐시된 CDN 서버에 데이터를 요청할 것이기 때문에 모든 퍼블릭 엑세스 차단으로 체크한다.

  • 버킷 버전 관리: 업로드한 파일들의 versioning이 필요할 때 활성화한다.
  • 태그: 결제 대시보드에서 비용 추적을 할 수 있는 이름을 작성해줄 수 있다.
  • 기본 암호화: 업로드한 파일들을 암호화하여 저장할 때 활성화한다.
    ⚠️ 암호화 / 복호화 과정에 시간이 소요되며, 정적 파일을 배포하기 때문에 암호화할 필요가 없다.

버킷 만들기를 눌러 버킷을 생성하자.

추가로 고급 설정객체 잠금 기능은 중요한 파일이 버킷에 저장될 경우 객체가 삭제되거나 덮어쓰기 되지 않도록 할 수 있다.

S3 버킷에 정적 파일 업로드

파일을 올리고 업로드를 누른다.

S3 호스팅 설정

속성 탭의 페이지 최하단에서 정적 웹 사이트 호스팅 탭으로 이동해 활성화로 바꾼다.

CloudFront 배포 설정

S3에 업로드한 정적 파일들을 CDN을 생성해 배포하기 위해 CloudFront 검색 후 배포 생성을 누른다.

만들었던 S3 버킷 이름의 도메인을 추천으로 보여준다. 선택!

CloudFront로만 배포할 수 있도록 S3에서 모든 퍼블릭 액세스 차단을 차단했기 때문에 S3 버킷 액세스의 OAI 사용을 체크한다.
CloudFront가 S3에 접근하는데 사용되는 권한 객체OAI라는 걸 생성할 수 있다. CloudFront의 배포 도메인이 S3의 특정한 버킷에 접근하려 할 경우, 해당 배포 도메인이 버킷이 허용하는 OAI를 가지고 있는지를 검사하여 파일을 줄지말지 결정하게 된다.

새 OAI 생성을 눌러 원본 액세스 ID를 새로 만든다.

예, 버킷 정책 업데이트를 눌러 OAI에 대한 읽기 액세스를 허용하도록 버킷 정책을 업데이트한다.

Origin Shield를 활성화 하고 리전을 선택한다.

Origin Shield는 CDN과 origin server 사이에 추가적인 캐싱 레이어를 두고 그곳에 컨텐츠를 캐싱한다.
CDN - Origin Shield - Origin Server 구조로, S3에 직접적으로 요청할 확률이 더 줄어든다. Origin에 대한 모든 요청이 Origin Shield를 거쳐가기 때문에 캐시 적중률도 높아지고, 동일한 객체에 대한 요청을 통합해 동시 요청 수를 줄인다는 장점이 있다.

[기본 캐시 동작]의 자동으로 객체 압축Yes로 설정한다. 컨텐츠의 파일 크기를 굉장히 줄일 수 있다고 한다.

[뷰어 프로토콜 정책]에서 HTTP를 HTTPS로 리다이렉트 시켜주기 위해 Redirect HTTP to HTTPS로 변경한다.

정적 리소스 배포이므로 GET, HEAD HTTP 메서드만 허용해도 된다.

[뷰어 엑세스 권한]은 NO로 설정한다.

[캐시 키 원본 요청]은 Cache policy and origin request policyCachingOptimized를 선택한다.

⚠️ AWS의 Cloudfront의 캐싱 정책은 보통 24시간 동안의 웹 컨텐츠를 캐싱한다. 즉 배포 후 24시간 이내 한번 더 배포가 이루어진다면 변경 사항을 확인하기까지 24시간이 걸린다는 뜻이다. 따라서 변경사항을 바로바로 확인해야한다면, Caching Optimized가 아닌 Caching Disabled로 설정하면 된다.

[가격 분류]는 모든 엣지 로케이션에서 사용을 보통 선택한다. 다만 비용을 감소시키거나 특정 리전에서만 사용하고 싶을 때 다른 옵션을 선택할 수 있다.

[대체 도메인 이름]과 [사용자 정의 SSL 인증서]는 현재는 사용하지 않을 것이므로 따로 설정하지 않지만, 설정하고 싶다면 AWS CloudFront CNAME 설정하기를 참고해도 좋을 것 같다 👍.

[기본값 루트 객체]에 index.html 을 입력한다.

나머지 설정은 그대로 두고 배포 생성을 클릭하여 배포 생성을 마친다.

SPA이기 때문에 Redirect fallback 설정을 추가로 해준다. SPA는 하나의 index.html을 갖고 JS로 동적 라우팅이 이루어지기 때문에 S3에서 페이지를 찾지 못할 경우 403 Forbidden 를 응답한다.

[오류 페이지] 탭에서 사용자 정의 오류 응답 생성을 클릭한다.

S3가 403 오류코드를 전송할 때 응답 페이지를 /index.html로 리다이렉트 시킨 뒤 200 확인 상태코드로 응답한다.

https로 생성된 배포 도메인 이름으로 들어가 배포가 무사히 된 것을 확인했다. 🎉 확실히 기존 Fass 서비스보다 속도가 훨씬 빠르다는 게 느껴졌다 ㄷㄷ.

CloudFront 캐시 무효화


컨텐츠를 새로 업데이트할 때 CloudFront의 [무효화] 탭에서 기존의 캐시를 무효화하고 새로 캐싱할 수 있다.

Workflow 설정

매번 S3에 수동으로 파일을 올리고 배포할 수 없기 때문에 CI/CD를 위해 깃허브 Actions 탭에서 새로운 workflow를 생성한다.

S3, CloudFront 접근 권한 추가 에서 액세스 키와 비밀 액세스 키를 받아서 github Secrets에 등록했으므로 버킷의 리전 정보와 CloudFront 배포 ID(distribution id)를 추가로 업데이트한다.

버킷의 리전 정보는 버킷의 [속성] 탭에서 확인할 수 있다.


Distribution id는 CloudFront의 배포 ID에서 확인할 수 있다.



name: CD


on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]


jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source code
        uses: actions/checkout@v2 # workflow에서 액세스할 수 있도록 저장소를 체크아웃
        
      - name: Install dependencies
        run: yarn install
        
      - name: Build
        run: yarn build

      - name: S3 Deploy
        run: aws s3 sync ./build s3://csr-test-1-bucket/ --acl bucket-owner-full-control # 현재 build된 폴더에 접근 후 s3 버킷인 csr-test-1-bucket에 파일 업로드
        env: 
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_REGION: ${{ secrets.AWS_REGION }}
      - name: Invalidate CloudFront Cache # 새로 리소스를 업데이트할 때 기존 캐시 무효화
        uses: chetan/invalidate-cloudfront-action@master
        env:
          AWS_DISTRIBUTION: ${{ secrets.AWS_DISTRIBUTION_ID }}
          PATHS: '/index.html'
        continue-on-error: true

.github/workflow/deploy.yml 파일을 생성함과 동시에 worflow가 실행됐다.

배포가 실패해서 확인해보니 요론 문제가 있어서 수정사항을 push 했다.

두구두구두구... 🥺

네.
그 이후에도 수많은 짜잘한 오류를 마주해서 하나하나 해결하고 성공했읍니다~!~! 🎉

실제로 업로드된 파일의 마지막 수정 날짜가 최근으로 변경되어 CD가 잘 적용됐다는 걸 알 수 있었다. 👍

💡 참고

AWS S3 + CloudFront로 정적 웹 사이트 배포하기
우테코 프로젝트에서 Github Actions를 이용한 배포 자동화

profile
💪🏻 아는 걸 설명할 줄 아는 개발자 되기

0개의 댓글