본문 바로가기

⛳️ 공동구매 서비스 총대마켓

CI/CD란 | Github Actions 사용해보기

요구 사항

작년 여름 참여했던 북링크 프로젝트에서, 백엔드 코드에 변경 사항이 발생할 때마다 깃허브 pull, 빌드, 서버 내리고 올리기 과정을 반복했다. 모든 자잘한 작업들이 수동이었기 때문에 명령어를 입력할 때 실수가 자주 발생했고, 가끔은 서버 업데이트를 잊어 프론트엔드에게 미안한 상황도 종종 발생했다. CI/CD에 무지했기 때문에 발생했던 불편함이었다. 이번 프로젝트에서는 그럴 일이 없도록 CI/CD를 적용해보자!

 

용어 정리

컴파일: 소스코드 → 기계어 (ex. 영어 글 → 한글 글)

빌드: 소스코드 → 컴퓨터에서 실행 가능한 소프트웨어 산출물, 빌드에 컴파일이 포함되어있음 (ex. 글 → 책)

배포: 빌드 결과물을 사용자가 접근할 수 있는 환경에 배치 (ex. 책을 서점에 배치)

 

CI/CD

  • 테스트, 통합, 배포 등의 반복 과정을 자동화
  • 일반적인 흐름: 개발 → 커밋 → 빌드 → 테스트 → 릴리즈 배포
  • 장점
    • 소프트웨어 개발 라이프사이클 간소화 및 가속화
    • 지속적인 소프트웨어 개발 및 업데이트 주기 유지
    • 작은 단위로 배포가 진행되어 빠른 에러 해결 가능
    • 실수 방지, 빠른 결과 보고

CI

  • Continuous Integration, 지속적 통합
  • 동일한 프로젝트에서의 모든 작업자가 정기적으로 코드의 변경 사항을 중앙 저장소에 병합하도록 하는 방식

CD

  • Continuous Delivery, 지속적 제공
  • CI 이후의 코드 변경 사항을 프로덕션 환경으로 릴리즈 준비 상태 (스테이징을 자동화)
    • Q) 여기서 스테이징이란?
    • A) 운영 서버에서 사용되는 데이터를 가지고 실제 배포하기 전 테스트하는 과정을 의미한다. 어플리케이션이 커지면 별도의 스테이징 서버(테스트 서버, QA 서버)를 두기도 한다. 우리 서비스의 경우는 아직 필요하지 않다고 판단했다.
  • Continuous Deployment, 지속적 배포
  • 지속적 통합 및 지속적 제공에 이어 프로덕션 배포까지 자동화

CI와 CD의 구분은 아래의 그림으로 확인할 수 있다.

출처: [10분 테코톡] 찬, 레넌의 CI/CD와 무중단 배포

 

 

CI/CD를 적용하기 위해 여러 툴이 제공된다. 그 중 러닝 커브가 가장 낮다고 판단되는 Github Actions를 학습해보았다.


Github Actions

  • 소프트웨어 workflow를 자동화할 수 있도록 돕는 도구
  • 빌드, 테스트 및 배포 파이프라인을 자동화할 수 있는 지속적인 통합 및 지속적인 배포 (CI/CD) 플랫폼
  • 레포지토리에서 특정 이벤트가 발생할 때 워크플로우를 실행(트리거)할 수 있도록 한다.

 

Github Actions에서 사용되는 몇가지 개념들을 알아보자.

Workflow

  • 하나 이상의 작업(job)을 실행하는 구성 가능한 자동화된 프로세스
  • 레포지토리의 이벤트에 의해 트리거될 때 실행되거나 수동으로 또는 정의된 일정에 따라 트리거될 수 있다.
  • ./github/workflows 경로에 워크플로우 파일(YAML 파일)을 위치시켜야한다.

Event

  • workflow 실행을 트리거하는 저장소의 특정 활동

Job

 

  • 동일한 runner에서 실행되는 workflow의 step 집합
  • 기본적으로 작업 간 종속성은 없고 서로 병렬로 실행, 종속성을 취할 수도 있다.

Step

  • 실행될 셸 스크립트나 동작
  • 순서대로 실행되며 서로 종속된다.
  • 동일한 runner에서 실행되므로 단계 간 데이터 공유가 가능하다.

Runner

  • 트리거될 때 workflow를 실행하는 서버
  • 한 번에 하나의 작업을 실행한다.
  • GitHub은 Ubuntu Linux, Microsoft Windows, macOS 러너를 제공한다.

아래는 workflow 파일의 간단한 예시이다.

# workflow 이름
name: Github Actions 실행시키기

# event
on:
  push:
    branches:
      - main

jobs:
  My-Deploy-Job: # job 이름
    runs-on: ubuntu-latest # ubuntu 환경 + 최신 버전

    steps:
      - name: Hello World 출력하기
        run: echo "Hello World"

      - name: 여러 명령어 문장 작성하기
        run: |
          echo "good "
          echo "evening"
          
      - name: Github Actions에 저장되어있는 변수 사용해보기
        run: |
          echo $GITHUB_SHA # 해당 commit 고유값
          echo $GITHUB_REPOSITORY
          
      - name: 노출시키고 싶지 않은 값
        run:
          echo ${{ secrets.SECRET_HOBBY }}

 

해당 파일을 커밋한 후 깃허브에 푸쉬하면 아래와 같이 스크립트가 실행되고 실패 시 사용자에게 결과를 보고한다.

 

이제 서버 배포 과정을 자동화해보자!

 

박재성님의 강의 영상을 참고하여 나는 아래 스크립트로 서버 배포를 자동화하였다.

 

돈이 없는 나는 AWS 프리티어에서 제공하는 EC2의 t2.micro 인스턴스를 사용하였는데, 코드가 조금만 방대해져도 서버가 불안정해졌다. 따라서 최소한의 코드만을 사용하여 배포 자동화를 테스트하는 것을 추천한다.

name: Github Actions 실행시키기

on:
  push:
    branches:
      - main

jobs:
  Deploy:
    runs-on: ubuntu-latest
    
    steps:
      - name: SSH로 EC2에 원격 접속
        uses: appleboy/ssh-action@v1.0.3 # (1)
        env: # (2)
          APPLICATION_PROPERTIES: ${{ secrets.APPLICATION_PROPERTIES }}
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_PRIVATE_KEY }}
          envs: APPLICATION_PROPERTIES # (3)
          script_stop: true
          script: |
            cd /home/ubuntu/github-actions-practice
            rm -rf src/main/resources/application.yml
            git pull origin main
            echo "$APPLICATION_PROPERTIES" > src/main/resources/application.yml # (4)
            ./gradlew clean build
            sudo fuser -k -n tcp 8080 || true # (5)
            nohup java -jar build/libs/*SNAPSHOT.jar > ./output.log 2>&1 &

 

위 workflow 파일에 대한 설명

 

(1) SSH로 EC2에 원격 접속하기 위해 appleboy님이 오픈소스로 제공하는 라이브러리를 사용했다. 하위는 해당 라이브러리의 문법으로 작성한다.

(2) 환경 변수를 선언한다. secrets 값은 repo > Settings > Secrets and variables > Actions에서 설정 가능하다.

(3) 하위에서 사용하기 위해 변수를 선언한다. (라이브러리 문법)

(4) secret 값으로 설정해두었던 APPLICATION_PROPERTIES 값이 application.yml 파일로 생성된다. ⇒ .gitignore에 담은 파일을 EC2에서 관리 가능하게 된다.

(5) 명령어 실행 과정에서, 서버가 존재하지 않을 경우 에러가 발생하면 true를 반환하도록 한다.

 

 

연습을 위한 코드는 아래를 참고하면 된다.

https://github.com/helenason/github-actions-practice

 

GitHub - helenason/github-actions-practice

Contribute to helenason/github-actions-practice development by creating an account on GitHub.

github.com

 


참고

CI/CD

[10분 테코톡] 루카의 CI/CD

[10분 테코톡] 찬, 레넌의 CI/CD와 무중단 배포

CI/CD(CI CD, 지속적 통합/지속적 배포): 개념, 툴, 구축, 차이

 

Github Actions

GitHub Actions 이해 - GitHub Docs

CI/CD 입문·실전 - 2.5. Spring Boot 프로젝트에 CI/CD 구축 (일반 프로젝트용)