git action을 이용한 spa프로젝트 s3배포

JEON.HYEONG.JUN·2023년 3월 2일
1
post-thumbnail

최근 일복이 터져 react 프로젝트를 삼주간 매달려서 완성하였다.

바로 다음 프로젝트가 이어졌고, 처음으로 실전에서 개발 환경 구성을 진행하였다.

사실 회사에서도 devops의 개념이 처음 도입되면서, 백엔드 쪽은 다른 분이, 프론트는 내가 맡게 되었고, AWS 버킷생성도 못하는 신입의 입장에서는 굉장히 난감한 상황이었다.

처음에는 많은 경험과 스펙을 쌓을 수 있어 호기롭게 도전했지만 docker, k8s, aws설정방법등에 대해 공부하며 느낀 것은 개발과는 또다른 삽질의 연속이다. 어떻게 하란거지가 아니라 이게 대체 무슨 말이지라는 느낌이었다. 특히 컨테이너개념과 오케스트레이션은 개념은 이해해도 이게 왜 프론트에 필요한지 아직 이해가 되지않는다. 간단하게 s3에 올리고 캐시무효화하면 될 거 같은데 말이다.. 쉽지않은 분야인 것 같다.

아무튼 가장 간단한 방법인 S3에 업로드 -> cloudfront무효화의 과정을 git action을 통해 배포해 보기로 하였고, 과정을 간단하게 기록해보자.


기록용이니 정말 간단하게 정리하자면

  1. route53은 메인 도메인에서 서브도메인을 연결하였고, dev와 prod 두개를 생성한다.
  2. s3 bucket 역시 같은 용도로 2개, cloudfront도 2개 생성.
  • route53, s3 bucket, cloudfront의 생성방법은 구글링하면 잘 나와있으니 참고하자.

정적 웹페이지 배포는 어려울게 없으나, spa프로젝트는 신경써야 할 것이 좀 있다.
기록해두고 잘안될때는 한번씩 확인해보자.

  • 모든 퍼블릭 액세스 차단 여부
  • 버킷 정책 작성
  • cloudfront 오류 페이지 응답코드 200 반환 (spa특성상 index.html는 하나이기 때문)

  • cloudfront 원본 편집 탭에서 엑세스 제어 설정 (모든 퍼블릭 액세스를 차단했기 때문에 제어 설정을 꼭 해준다. 이거 안해서 3시간 삽질함..)

내가 작성한 git action workflow.
주석 잘 읽고 실수하지말자

name: CI/CD

on:
  pull_request:
    types:
      - closed #pr이 닫길때, 즉 merge가 될 때

jobs:
  if_merged:
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-18.04 #20.04 버전부터 바뀐 aws cli명령어가 있다. 그래서 버전을 지정해준다.
    steps:
      - run: |
          echo The PR was merged
      - name: Checkout source code
        uses: actions/checkout@master

      - name: Cache node modules # node modules 캐싱
        uses: actions/cache@v1
        with:
          path: node_modules
          key: ${{ runner.OS }}-master-build-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.OS }}-build-
            ${{ runner.OS }}-

      - name: Install Dependencies
        run: yarn
        env:
          CI: ''

      - name: Build
        run: npm run generate

      # 다음은 브랜치이름에 따라 s3업로드와 cloudfront무효화를 진행한다.
      # 브랜치이름을 변수명으로 만들어서 코드를 간소화 할 필요가 있다.

      - name: Deploy if develop
        if: github.base_ref == 'develop'
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-2
          AWS_EC2_METADATA_DISABLED: true
        run: |
          aws s3 sync ./dist s3://프로젝트이름

      - name: Invalidate CloudFront if develop
        if: github.base_ref == 'develop'
        uses: chetan/invalidate-cloudfront-action@v2
        env:
          DISTRIBUTION: ${{ secrets.DISTRIBUTION_ID_DEV }}
          PATHS: '/*'
          AWS_REGION: ap-northeast-2
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

      - name: Deploy if master
        if: github.base_ref == 'master'
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-2
          AWS_EC2_METADATA_DISABLED: true
        run: |
          aws s3 sync ./dist s3://프로젝트이름

      - name: Invalidate CloudFront if master
        if: github.base_ref == 'master'
        uses: chetan/invalidate-cloudfront-action@v2
        env:
          DISTRIBUTION: ${{ secrets.DISTRIBUTION_ID_PROD }}
          PATHS: '/*'
          AWS_REGION: ap-northeast-2
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

다른 부분은 이상없이 예상대로 잘 됐는데 가장 삽질한 부분은 s3에 업로드이다.

- name: Deploy
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        run: |
          aws s3 cp \
            --recursive \
            --region ap-northeast-2 \
            dist s3://프로젝트이름

처음 구글링 시에는 위와 같은 방법으로 시도를 했는데 dist는 .ignore에 포함되어 있기 때문에 dist폴더를 찾지 못해 deploy에 계속 실패하는 것이다. 여기서 또 4시간 삽질했다..

The user-provided path dist does not exist.

(이런 에러가 계속 떴다.)

결국 검색 후 aws s3 sync 를 사용하여 직접 나의 디렉토리 타깃경로와 s3를 동기화 하여 해결하였다. 아! 그리고 AWS REGION을 추가하고 AWS_EC2_METADATA_DISABLED : true를 꼭 추가하자. METADATA에 관한 부분은 문서를 읽고 있는데 무슨말인지 모르겠다.. 근데 안쓰면 에러가 나서 추가해줬다. AWS는 굉장히 심오하구나..

아무튼 정상적으로 자동 배포까지 성공하였고, merge된 브랜치에 따라 하나의 브랜치에만 deploy되는 것을 확인했다.
앞으로의 과제는 컨테이너 개념을 익히고, ecr push와 버전에 따른 deploy를 위해 tagging을 인식해 적용해볼 계획이다.

typescript도 공부해야하는데.. 하 이번 프로젝트 끝나면 개발공부도 꼭 다시 시작해야겠다. react-query도 공부해봐야지..

profile
💻😀👍🎁👏😁

0개의 댓글