Jenkins를 6년 쓰다가 GitHub Actions로 갈아탄 이유는 간단하다. Jenkins 서버가 금요일 저녁마다 죽었기 때문이다. 매주 금요일, 퇴근하려는 순간 슬랙에 '빌드 서버 다운'이라는 알림이 뜨면 느꼈던 그 절망감. 결국 GitHub Actions로 전환하고 나서 금요일 저녁이 자유로워졌다.
GitHub Actions를 선택한 이유
Jenkins, GitLab CI, CircleCI 등 다양한 CI/CD 도구가 있지만, GitHub Actions를 선택한 이유가 있었습니다:
- GitHub 통합: 별도의 서버 없이 GitHub 리포지토리에서 바로 사용 가능
- 무료 티어: public 리포지토리는 무제한, private도 월 2,000분 무료
- 마켓플레이스: 커뮤니티가 만든 수천 개의 재사용 가능한 Action 존재
- 매트릭스 빌드: 여러 OS, JDK 버전 조합을 병렬로 테스트 가능
기본 CI 워크플로우 구성
PR이 생성되면 자동으로 빌드와 테스트를 실행하는 워크플로우입니다.
name: CI Pipeline
on:
pull_request:
branches: [ main, develop ]
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Grant execute permission
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- name: Run tests
run: ./gradlew test
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: build/reports/tests/
Gradle 캐싱의 효과
캐싱을 적용하면 의존성 다운로드 시간을 크게 줄일 수 있습니다. 실제 프로젝트에서 측정한 결과, 첫 빌드는 약 3분이 소요되지만 캐시가 적용된 이후에는 약 45초로 단축되었습니다.
테스트 커버리지 리포트
JaCoCo를 활용하여 테스트 커버리지를 측정하고 PR에 자동으로 리포트를 작성하는 설정입니다.
- name: Generate JaCoCo report
run: ./gradlew jacocoTestReport
- name: Add coverage to PR
uses: madrapps/jacoco-report@v1.6
with:
paths: build/reports/jacoco/test/jacocoTestReport.xml
token: ${{ secrets.GITHUB_TOKEN }}
min-coverage-overall: 60
min-coverage-changed-files: 80
변경된 파일의 최소 커버리지를 80%로 설정하면, 새로 작성하는 코드에 대한 테스트 작성을 강제할 수 있습니다.
환경별 배포 워크플로우
개발, 스테이징, 운영 환경으로 단계적으로 배포하는 워크플로우입니다. GitHub Environments를 활용하여 각 환경에 대한 승인 프로세스를 추가할 수 있습니다.
name: Deploy Pipeline
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.tag }}
steps:
- uses: actions/checkout@v4
- name: Get version
id: version
run: echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
- name: Setup JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Build
run: ./gradlew bootJar
- name: Build Docker image
run: |
docker build -t myapp:${{ steps.version.outputs.tag }} .
docker save myapp:${{ steps.version.outputs.tag }} | gzip > image.tar.gz
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: docker-image
path: image.tar.gz
deploy-staging:
needs: build
runs-on: ubuntu-latest
environment: staging
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: docker-image
- name: Deploy to staging
run: |
echo "Deploying ${{ needs.build.outputs.version }} to staging"
# scp, ssh 등을 통한 배포 로직
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: docker-image
- name: Deploy to production
run: |
echo "Deploying ${{ needs.build.outputs.version }} to production"
# 운영 배포 로직
시크릿 관리
데이터베이스 비밀번호, API 키 등 민감한 정보는 GitHub Secrets에 저장합니다.
# GitHub Secrets 사용 예시
env:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
주의사항으로, Secrets 값은 로그에 자동으로 마스킹되지만 의도치 않게 노출되지 않도록 주의해야 합니다. 특히 echo로 환경변수를 출력하는 디버깅 코드를 배포 전에 반드시 제거해야 합니다.
Slack 알림 연동
배포 성공이나 실패 시 Slack으로 알림을 보내면 팀 전체가 배포 상황을 즉시 인지할 수 있습니다.
- name: Notify Slack
if: always()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
fields: repo,message,commit,author,action,eventName,ref
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
실무 팁
워크플로우 실행 시간 최적화
- 병렬 실행: 독립적인 Job은 병렬로 실행하여 전체 시간을 단축합니다
- 조건부 실행:
paths필터를 사용하여 관련 파일이 변경된 경우에만 워크플로우를 실행합니다 - 캐싱: Gradle, npm 등의 의존성을 캐싱하여 반복 다운로드를 방지합니다
보안 점검 자동화
OWASP Dependency-Check를 CI에 포함하여 취약한 라이브러리를 자동으로 탐지합니다.
- name: OWASP Dependency Check
run: ./gradlew dependencyCheckAnalyze
- name: Upload OWASP report
uses: actions/upload-artifact@v4
with:
name: dependency-check-report
path: build/reports/dependency-check-report.html
CI/CD 구축 후 팀에 생긴 변화
GitHub Actions를 활용한 CI/CD 파이프라인은 코드 품질 관리부터 자동 배포까지 개발 프로세스 전반을 개선합니다. 처음에는 간단한 빌드-테스트 워크플로우부터 시작하여 점진적으로 기능을 추가하는 것을 추천합니다.
10년차 풀스택 개발자. Spring Boot, Flutter, AI 등 실무 경험을 기록합니다.
GitHub →
💬 댓글