[Github Actions] 깃허브 액션으로 SpringBoot 프로젝트 CI/CD 적용하기

예름·2025년 3월 5일

Github Actions

목록 보기
2/4
post-thumbnail

📍 깃허브 액션을 프로젝트에 어떻게 적용할 수 있을까?

깃허브 액션이란? (feat. CI/CD) 을 읽으시면 이해가 2배 더 잘 됩니다

📌 구현

🛠️ 세팅

깃허브 액션을 실행하기 위해 워크플로우를 작성해야 한다.

프로젝트에 .github 폴더를 만들고 그안에 workflows 폴더를 만든다.
그리고 워크플로우를 yml 스크립트에 작성하면 된다.

.github
└── workflows
    ├── be-cd.yml
    └── be-ci.yml

⚙️ CI

먼저 CI부터 살펴보겠다.

name
워크플로우의 이름을 설정한다.

name: Backend CI

on
어느 조건(push/pull request, 어떤 브랜치)에서 실행할지 정한다.

on:
  pull_request:
    branches: [ "main" ]

jobs
워크플로우에서 실행되는 개별 작업 단위이다.

jobs:
  build:
    runs-on: ubuntu-latest

runs-on: ubuntu-latest 는 Ubuntu 최신 환경에서 실행한다는 의미이다.
다른 환경에서도 실행할 수 있다.

steps

    steps:
      - name: Checkout Code # 저장소에 있는 코드 가져오기
        uses: actions/checkout@v4

      - name: Set up JDK 17 # JDK 설치
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Set up Gradle # Gradle 설정, 종속성 및 빌드 캐시를 자동으로 관리
        uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
        with:
          cache-read-only: false # 캐시 읽기 및 쓰기 활성화

      - name: Grant Execute Permission For Gradlew # Gradlew 실행 권한 부여
        run: chmod +x gradlew

      - name: Build with Gradle # Gradle 빌드 실행
        run: | # 실패 즉시 중단
          set -e
          ./gradlew clean build

      - name: Test with Gradle # 테스트 실행
        run: |
          set -e
          ./gradlew test

❓ Set Up Gradle에서 cache-read-only: false 는 왜 필요할까?

캐시를 읽고 쓰면서 빌드 속도를 최적화하는 역할을 한다.

최종 be-ci.yml 파일

name: Backend CI

on:
  pull_request:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code # 저장소에 있는 코드 가져오기
        uses: actions/checkout@v4

      - name: Set up JDK 17 # JDK 설치
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Set up Gradle # Gradle 설정, 종속성 및 빌드 캐시를 자동으로 관리
        uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
        with:
          cache-read-only: false # 캐시 읽기 및 쓰기 활성화

      - name: Grant Execute Permission For Gradlew # Gradlew 실행 권한 부여
        run: chmod +x gradlew

      - name: Build with Gradle # Gradle 빌드 실행
        run: | # 실패 즉시 중단
          set -e
          ./gradlew clean build

      - name: Test with Gradle # 테스트 실행
        run: |
          set -e
          ./gradlew test

⚙️ CD

위의 부분은 CI 스크립트와 비슷하다.

jobs - build

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code # 저장소에 있는 코드 가져오기
        uses: actions/checkout@v4

      - name: Set up JDK 17 # JDK 설치
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Set up Gradle # Gradle 설정, 종속성 및 빌드 캐시를 자동으로 관리
        uses: gradle/actions/setup-gradle@v4 # v4.0.0
        with:
          cache-read-only: false # 캐시 읽기 및 쓰기 활성화

      - name: Grant Execute Permission For Gradlew # Gradlew 실행 권한 부여
        run: chmod +x gradlew

      - name: Build with Gradle # Gradle 빌드 실행
        run: ./gradlew clean build -x test --no-daemon

      - name: Test with Gradle # 테스트 실행
        run: ./gradlew test

      - name: Rename Build File # 빌드된 JAR 파일 이름 변경
        run: mv $(ls ./build/libs/*.jar | head -n 1) ./cdtest.jar

#      - name: Debug Secrets # Secrets 디버깅
#        run: |
#          echo "EC2_HOST: '${{ secrets.EC2_HOST }}'"
#          echo "EC2_USERNAME: '${{ secrets.EC2_USERNAME }}'"
#          echo "EC2_SSH_KEY length: $(echo "${{ secrets.EC2_SSH_KEY }}" | wc -c)"

      - name: Transfer Build File to EC2 via SCP # JAR 파일을 EC2로 전송
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_SSH_KEY }}
          source: cdtest.jar
          target: /home/ubuntu

CI 부분과 다른 점은 JAR 파일의 이름을 변경해서 EC2에 전송하는 작업이 추가됐다.

❓ Build with Gradle에서 -x test로 실행하는 이유?

CI 작업에서 이미 테스트를 수행했기 때문에 CD 작업에서는 테스트를 생략해도 된다.

jobs - deploy
배포를 위한 작업이다.
needs: build 는 build 작업을 먼저 실행해야한다는 의미이다.

  deploy:
    runs-on: ubuntu-latest
    needs: build

    steps:
      - name: Deploy to EC2 via SSH # EC2 서버에서 JAR 실행
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_SSH_KEY }}
          port: ${{ secrets.EC2_PORT }}
          script: |
            sudo fuser -k -n tcp 8080 || true
            sudo nohup java -jar cdtest.jar > ./output.log 2>&1 &
            mv output.log output_$(date +%Y%m%d-%H%M%S).log
          debug: true

중요한 키들은 깃허브 액션의 Secrets에 저장했다.

💡 Secrets 설정하는 법


깃허브에서 RepositorySettingsSecrets and variablesActionsRepository secrets에서 설정해주면 된다.

주의할 점은 Environment secrets 와 착각하면 안된다‼️

❓ jobs.build vs jobs.deploy

build에서는 JAR 파일을 생성하고 EC2로 전송하는 역할, deploy에서는 배포하는 역할이다.

최종 be-cd.yml 파일

name: Backend CD

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

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code # 저장소에 있는 코드 가져오기
        uses: actions/checkout@v4

      - name: Set up JDK 17 # JDK 설치
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Set up Gradle # Gradle 설정, 종속성 및 빌드 캐시를 자동으로 관리
        uses: gradle/actions/setup-gradle@v4 # v4.0.0
        with:
          cache-read-only: false # 캐시 읽기 및 쓰기 활성화

      - name: Grant Execute Permission For Gradlew # Gradlew 실행 권한 부여
        run: chmod +x gradlew

      - name: Build with Gradle # Gradle 빌드 실행
        run: ./gradlew clean build -x test --no-daemon

      - name: Test with Gradle # 테스트 실행
        run: ./gradlew test

      - name: Rename Build File # 빌드된 JAR 파일 이름 변경
        run: mv $(ls ./build/libs/*.jar | head -n 1) ./cdtest.jar

      - name: Transfer Build File to EC2 via SCP # JAR 파일을 EC2로 전송
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_SSH_KEY }}
          source: cdtest.jar
          target: /home/ubuntu

  deploy:
    runs-on: ubuntu-latest
    needs: build

    steps:
      - name: Deploy to EC2 via SSH # EC2 서버에서 JAR 실행
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_SSH_KEY }}
          port: ${{ secrets.EC2_PORT }}
          script: |
            sudo fuser -k -n tcp 8080 || true
            sudo nohup java -jar cdtest.jar > ./output.log 2>&1 &
            mv output.log output_$(date +%Y%m%d-%H%M%S).log
          debug: true

✅ 실행 결과

여러 번의 시행착오 끝에 ci/cd 모두 성공적으로 실행시켰다.

profile
안정적인 쳇바퀴를 돌리는 삶

0개의 댓글