develop

Github Action을 이용해서 자동배포하기

crab. 2023. 1. 20. 16:17

Github Action을 통한 자동배포

GitHub Action이란?

  • 이번에는 Github Action을 살펴보자! Github Action은 Github 저장소를 기반으로 소프트웨어 개발 Workflow를 자동화 할 수 있는 도구로, Github에서 직접 제공하는 CI/CD 도구이다.
  • github action은 Workflow를 기반으로 동작하며, Github 저장소에서 발생하는 build, test, package, release, deploy 등 다양한 이벤트를 기반으로 사용자는 직접 원하는 Workflow를 만들 수 있다.
  • 즉 우리는 Workflow를 만들고, 이를 통해 빌드 및 배포 프로세스를 자동화 할 수 있다!😎
  • 각각에 이벤트에 대해 더 자세한 내용이 궁금하신 분은 공식문서를 읽어 보시는 것도 좋을 것 같다.
  • Action은 기존에 있는 서비스 Circle CI, Travis CI, Jenkins와 같은 빌드/배포 자동화 서비스이며, 다른 서비스에 비해 매력적인 부분은, Github 내에서 소스 코드 관리부터 배포 자동화까지 한번에 처리할 수 있다는 점이다.
  • 애플리케이션에 기능을 더할 때마다 또는 유지/보수할 때마다 빌드 및 배포하는 작업들이 불편하게 느껴지지 않았나요? 그렇다면 Github actions를 사용해보세요!
  • 이벤트 발생에 따라 자동으로 빌드 및 배포하는 스크립트를 실행시켜줄 수 있습니다. 그 말 즉은 push 또는 pull request 이벤트가 있을때마다 Github actions이 build와 deploy를 하고 s3 배포까지 시켜줄 수 있다는 것이죠!

CI/CD란?

  • CI/CD는 애플리케이션 개발 단계를 자동화하여 애플리케이션을 보다 짧은 주기로 고객에게 제공하는 방법이다.
  • CI는 개발자를 위한 자동화 프로세스인 지속적인 통합(Continuous Integration)을 의미한다. CI를 성공적으로 구현할 경우 애플리케이션에 대한 새로운 코드 변경사항이 정기적으로 빌드 및 테스트되어 공유 리포지토리에 통합되므로 여러 명의 개발자가 동시에 애플리케이션 개발과 관련된 코드 작업을 할 경우 서로 충돌할 수 있는 문제를 해결할 수 있다.
  • CD는 지속적인 서비스 제공(Continuous Delivery) 또는 지속적인 배포(Continuous Deployment)를 의미하며 이 두 용어는 상호 교환적으로 사용된다. 두 용어 모두 파이프라인의 추가 단계에 대한 자동화를 뜻하지만 때로는 얼마나 많은 자동화가 이루어지고 있는지 설명하기 위해 별도로 사용되기도 한다.
  • 지속적인 제공은 개발자들이 애플리케이션에 적용한 변경 사항이 버그 테스트를 거쳐 리포지토리에 자동으로 업로드 되는 것을 뜻하며, 운영팀은 이 리포지토리에서 애플리케이션을 실시간 프로덕션 환경으로 배포할 수 있다.
  • 지속적인 배포는 개발자의 변경 사항을 리포지토리에서 고객이 사용 가능한 프로덕션 환경까지 자동으로 릴리스 하는 것을 의미한다. 이는 애플리케이션 제공 속도를 저해하는 수동 프로세스로 인한 운영팀의 프로세스 과부하 문제를 해결한다.

IAM

  • 우선, GitHub Action이 S3에 접근하여 배포 과정을 진행할 수 있도록 접근 권한이 있는 가상 유저를 생성하여 Github에 등록해 주어야 한다.
  • AWS에 IAM에서 신규 사용자를 생성하자!😁

  • 사용자 이름을 입력 해 주고, 생성할 유저의 권한 설정을 해준다!
  • S3를 검색하고 Full Access 권한을 부여한다.

  • 이때 주의해야 할 점은 마지막에 보이는 Secret key는 다시 볼 수 없으니 꼭! 다른 곳에 저장해 놓아야 한다.
  • 이제 AWS쪽 설정은 모두 완료 되었다. 이제 깃허브로 이동해서, 배포할 저장소의 settings -> secret으로 이동하여 앞서 저장해 놓은 key를 등록한다.
  • Action을 등록 하기 위하여 bucket name과 region등에 대한 정보도 필요하기 때문에, 같이 secret key로 등록하는 것을 추천한다!
  • 해당 키는 외부에 절대 노출되어서는 안된다!!

Github Actions의 Secrets

  • Github Repository의 Actions Secrets은 환경 변수를 암호화해서 저장할 수 있는 기능입니다.
  • 해당 기능은 Actions를 트리거할 때, 환경 변수를 가져오기 위해 사용할 수 있습니다.
  • 그럼 로컬 개발 환경에서는 .env 파일을 통해 환경 변수에 접근하고, Github Actions에서 배포할 때에는 Actions Secrets을 통해 환경 변수에 접근할 수 있지 않을까요?

  • 그래서 저희는 .env 파일에 존재하는 환경 변수 중, 프로덕션 단계에서 필요한 변수를 Actions Secrets에 추가하고 Action이 트리거 될 때 자동으로 프로덕션 환경을 위한 환경 변수 파일을 생성해주도록 하겠습니다.

Action에서 Secrets으로 환경 변수 파일 생성하기

먼저 저희에게 다음과 같은 환경 변수가 있다고 가정해봅시다.

# .env 파일에 저장된 환경 변수 REACT_APP_DOMAIN=https://domain.co.kr REACT_APP_DEBUG=false

  • 저희는 위의 환경 변수를 프로젝트의 라이브러리를 설치하기 전에 추가해보겠습니다.
  • 그러기 위해서 Github Repository의 Secrets으로 위의 환경 변수를 추가해줘야 합니다.
  • 아래 사진과 같이 두 개의 Secret을 생성해준 다음, Action 파일을 수정해보겠습니다.

  • 다음 단계로 진행하기 위해서는 간단한 리눅스 명령어의 사용법을 알아야 합니다.
  • 여기서 사용할 명령어는 echo 인데요, 해당 명령어는 콘솔 창에 인수로 받은 문자열을 출력하는 아주 단순한 명령어입니다.
  • 하지만 옵션을 추가하면 인수로 받은 문자열을 콘솔 창이 아닌 파일에 저장할 수 있습니다.
  • 아래의 커맨드는 문자열을 test.txt 파일에 저장하는 커맨드입니다.
  • echo "Hello, World!" >> test.txt
  • 만약 test.txt 파일이 존재하지 않는다면, 파일을 생성한 후 문자열을 입력하게 됩니다.
  • 저희는 이 명령어를 통해 Generate Environment Variables File for Production 단계에서 환경 변수 파일을 생성해보겠습니다.
  • 기본적으로 echo 명령어를 통해 변수를 출력하려면 변수명 앞에 $를 붙여줘야 하는데, 만약 다음과 같이 env 옵션을 설정하지 않는다면 Runner는 해당 변수를 찾지 못해 올바르게 환경 변수를 설정할 수 없습니다.
  • 따라서 해당 옵션을 통해 어떤 변수에 어떤 값이 들어갈지 설정해줘야 합니다.
  • 이렇게 .env 파일의 업로드 없이, 환경 변수를 설정한 상태에서 배포가 가능합니다.
name: Automatically Deployment

on: [push]

jobs:
  deployment:
    runs-on: ubuntu-latest

    # 해당 Job의 이름을 아래와 같이 설정하여 Actions 탭에서 확인할 수 있게 설정합니다.
    name: Deploying to surge

    steps:
      # 해당 레포지토리로 check-out하는 Action을 불러왔습니다.
      - uses: actions/checkout@v2

      # Node 환경을 설정하여 npm 커맨드를 사용할 수 있도록 하는 Action을 불러옵니다.
      # 여기에서는 14 버전을 사용하고 있습니다.
      - uses: actions/setup-node@v2
        with:
          node-version: '14'

      # Github Repository Secrets를 통해 환경 변수 파일을 생성합니다.
      - name: Generate Environment Variables File for Production
        run: |
          echo "REACT_APP_DOMAIN=$REACT_APP_DOMAIN" >> .env.production
          echo "REACT_APP_DEBUG=$REACT_APP_DEBUG" >> .env.production
        env:
          REACT_APP_DOMAIN: ${{ secrets.REACT_APP_DOMAIN }}
          REACT_APP_DEBUG: ${{ secrets.REACT_APP_DEBUG }}

      # 해당 프로젝트에서 사용하는 모든 라이브러리와 Surge를 설치합니다.
      - name: Install Dependencies and Surge
        run: |
          npm install
          npm install surge --global

      # React 프로젝트를 빌드합니다.
      - name: Build React Application
        run: npm run build

      # Surge에 빌드된 파일을 배포합니다.
      - name: Deploy React Application to Surge
        run: surge ./build ${{ secrets.SURGE_DOMAIN }} --token ${{ secrets.SURGE_TOKEN }}

자동배포에서의 응용

이제 마지막으로, 배포 과정을 진행해 줄 workflow 파일을 작성하자!

배포 단계는 아래와 같다.

  1. Source: 특정 브랜치에 코드가 커밋되면
  2. Build: github actions의 YAML파일에 적힌 명령어를 토대로 Webpack을 이용해 빌드를 진행하고
  3. Deploy: s3로 빌드 결과를 업로드한다.

프로젝트의 루트 디렉토리에 .github/workflows 폴더를 생성하고, 아래와 같이 main.yaml 파일을 생성한다.

# master-deploy-work.yml
name: main

on:
  push:
    branches:
      - main # main 브랜치에서 push 이벤트가 일어났을 때 실행
  pull_request:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout source code
        uses: actions/checkout@main

      - name: Generate Environment Variables File for Production # Github Repository Secrets를 통해 변수 파일을 생성
        run: |
          echo "REACT_APP_AUTH_SERVER=$REACT_APP_AUTH_SERVER" >> .env.production
          echo "REACT_APP_API_SERVER=$REACT_APP_API_SERVER" >> .env.production

        env:
          REACT_APP_AUTH_SERVER: ${{ secrets.REACT_APP_AUTH_SERVER }}
          REACT_APP_API_SERVER: ${{ secrets.REACT_APP_API_SERVER }}

      # 실행 속도를 빠르게 하기 위해 설치된 Node 모듈을 캐시하도록 설정합니다.
      - name: Cache node modules
        uses: actions/cache@v2
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-
      - name: Install Dependencies
        run: yarn

      - name: Build
        run: yarn build
        env:
          CI: ""

      - 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 \
          build s3://admin.pops.show
  • 프로젝트 이름에는 전의 포스팅에서의 버킷이름을 그대로 적어준다.
  • 나의 경우는 build s3://admin.pops.show 이다.

정리

  • 사실 크게 별거없다.
  • 하지만 저 코드안의 내용들 하나하나는 조금 복잡하다.
  • 보안과 직결되는만큼 꼼꼼하게 잘해야한다.
  • IAM에서 액세스키와 시크릿키를 가져오고
  • github actions에서 시크릿을 설정한 후에
  • 루트 디렉토리에 .github/workflows 폴더를 생성하고
  • echo와 secret을 이용해 main.yaml 파일을 생성한다.

출처

https://cheri.tistory.com/201

https://ji5485.github.io/post/2021-06-26/create-env-with-github-actions-secrets/

https://velog.io/@seeh_h/AWS와-github-action을-이용해-배포-자동화-하기

https://velog.io/@1nthek/GitHub-Action으로-AWS-S3에-배포-자동화

https://velog.io/@2pandi/CICD와-github-Actions를-통한-클라이언트-배포feat.-AWS-s3