Skip to content

백엔드 CI CD 파이프라인

시원 edited this page Jul 25, 2025 · 4 revisions

CI(Continuous Integration)

우리가 서버를 배포하기 위해서는, 변경된 코드를 빌드해야하고, 정상 동작하는지 알기 위해 테스트를 수행하는 과정을 거쳐야 한다. 그 과정을 자동화해주는 것이 CI 이고, 코드를 통합할 때마다 배포하기 위한 준비 단계(빌드, 테스트)를 수행한다.

  • 버그 조기 발견
    • 급하게 PR을 올리려다가 테스트 실패한지도 모르는 경우를 대비할 수 있다.
  • 효율성 증가
    • 수동으로 빌드, 테스트 하지 않아도 된다.

CD(Continuous Deployment)

수동 승인 없이 자동으로 배포하는 것을 의미한다. CI를 통해 빌드 및 테스트에 성공하면, 그 내용을 자동으로 배포할 수 있다.

  • 효율성 증가
    • 변경사항 있을 때마다 서버에 접속해서 실행 명령어를 수행하는 것은 번거롭다.

CI / CD 파이프라인 구축 방법 - Github Actions

  • Github에서 자체적으로 제공하는 Github Actions를 통해 CI/CD 파이프라인을 구축한다. Github Actions를 선택한 이유는 아래와 같다.
    • 코드 저장소를 github으로 선택했기에, github actions를 통해 워크플로우를 쉽게 설정할 수 있다. 또한 github repository에서 push, merge 등 다양한 상황을 트리거로 삼아 워크플로우를 수행할 수 있다.
    • .github 디렉터리에 워크플로우를 작성해서 넣어주면, Github에서 가상 머신 등을 제공해주기 때문에, 간편하게 이용할 수 있다.

CI / CD 워크플로우

  • CI/CD 워크플로우는 아래의 링크를 통해 확인할 수 있다.
on:
  push:
    branches: [ develop ] # push 될 때 CI, CD
    paths:
      - 'backend/**' # backend 디렉터리의 변경에 대해 실행하도록 함
  pull_request:
    branches: [ develop ] # PR 날릴 때 CI
    paths:
      - 'backend/**'
  • develop 브랜치에 PR을 보낼 때, push될 때 CI 워크플로우가 수행된다. backend 디렉터리의 변경에 대해서만 수행된다.
jobs:
  build_and_test: # CI 과정
     runs-on: ubuntu-latest # github가 관리하는 가상 머신에서 CI 실행
  • CI 과정은 github가 제공해주는 가상 머신에서 수행한다.
       
     steps: 
     - name: Checkout code
       uses: actions/checkout@v4 # 현재 이 워크플로우가 실행되는 가상 머신에 repository 코드를 clone 받도록 함

     - name: Set up Gradle
       uses: gradle/actions/setup-gradle@v3
             
     - name: Grant execute permission for gradlew
       run: chmod +x gradlew

     - name: Set up JDK 21
       uses: actions/setup-java@v4
       with:
         java-version: '21'
         distribution: 'temurin'
         cache: 'gradle'
       
     - name: Build with Gradle # 빌드 없이 테스트
       run: ./gradlew clean build -x test

     - name: Run Unit Tests # 테스트
       run: ./gradlew test

     - name: Upload Jar # GitHub Actions 아티팩트 저장소에 실행 가능한 jar파일 업로드
       uses: actions/upload-artifact@v4
       with:
         name: turip
         path: backend/build/libs/*SNAPSHOT.jar
  • 가상 머신에서 레포지토리 코드를 clone받고, 빌드와 테스트를 위한 gradle, jdk 세팅을 한 후, 빌드와 테스트를 한다.
  • 빌드 결과로 얻은 실행 가능한 jar파일을 GitHub Actions 아티팩트 저장소에 업로드한다.
  deploy: # CD 과정
    needs: build_and_test # build_and_test(CI) 과정이 끝난 이후 실행
    runs-on: self-hosted # EC2에 설치된 github runners가 실행
    if: github.event_name == 'push' # PR 날릴 때 말고, merge 될 때만 실행
  • CD 과정은 PR이 merge되는 경우에만 수행된다.
  • 빌드 과정과 달리, Github가 띄워주는 가상 머신을 이용하지 않고, 우리 서버에서 직접 실행한다. 이를 위해 서버에 github runners 환경을 설정해줘야 한다.
    • 이유는, 우리는 서버를 ec2에 띄우려 하는데, 생성한 ec2의 네트워크 보안 설정 상 github 가상 머신에서 ec2 서버에 접속할 수 없었다.(ec2에서 서버를 실행하는 명령어를 수행할 수 없었다.) 따라서 애초부터 ec2에서 CD과정을 수행하도록 한다.
    steps:
      - name: Download artifact from CI workflow
        uses: actions/download-artifact@v4 # 스냅샷 Jar 올렸던 GitHub Actions 아티팩트 저장소
        with:
          name: turip
          path: ./downloaded-artifact

      - name: Get JAR file name # Jar 파일명 구하기
        id: get_jar_name
        run: |
          JAR_FILE=$(find ./downloaded-artifact -name "*.jar" | head -n 1)
          if [ -z "$JAR_FILE" ]; then # 원하는 Jar파일 없으면 에러
            echo "Error: JAR file not found in downloaded-artifact directory."
            exit 1
          fi
          echo "JAR_NAME=$(basename $JAR_FILE)" >> $GITHUB_OUTPUT
          echo "JAR file located at: $JAR_FILE"

      - name: Kill Existing Server On Port 80 # 기존 80포트에 돌아가던 서버 내리기
        run: |
          PID=$(sudo lsof -t -i :80 || true)
          if [ -n "$PID" ]; then
            echo "Killing existing process: $PID"
            sudo kill -9 $PID
          fi
    
      - name: Run App On Port 80 # 80포트로 서버 올리기
        run: |
          JAR_NAME="${{ steps.get_jar_name.outputs.JAR_NAME }}"
          DOWNLOADED_JAR="./downloaded-artifact/$JAR_NAME"
          TARGET_JAR="/home/ubuntu/app/$JAR_NAME"

          echo "Moving new JAR to $TARGET_JAR"
          mv "$DOWNLOADED_JAR" "$TARGET_JAR"
          chmod +x "$TARGET_JAR"

          echo "Starting application..."
          sudo nohup java -jar "$TARGET_JAR" --server.port=80 > /dev/null 2>&1 &
  • CI 과정에서 올렸던 jar 파일을 다운로드하고, 기존 80포트에서 돌고 있던 서버를 내리고, jar 파일을 실행시켜 서버를 다시 80포트에 띄운다.

Clone this wiki locally