GitHub Actions는 GitHub에서 제공하는 CI/CD(Continuous Integration/Continuous Deployment) 플랫폼입니다.
코드 저장소에서 직접 소프트웨어 개발 워크플로우를 자동화할 수 있게 해주는 서비스로, 2019년 출시 이후 현재 세계에서 가장 인기있는 CI/CD 도구 중 하나가 되었습니다.
1위: GitHub Actions (45%)
2위: GitLab CI/CD (22%)
3위: Jenkins (18%)
4위: Azure DevOps (8%)
5위: 기타 (7%)
출처: Stack Overflow Developer Survey 2024
# .github/workflows/ci.yml
name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
단 8줄로 CI 완성! 🎉
"스타트업부터 대기업까지, 신규 프로젝트의 80%가 GitHub Actions를 채택" - GitHub 2024 Report
.github/workflows/
디렉토리에 위치on:
push: # 코드 푸시 시
pull_request: # PR 생성/수정 시
schedule: # 주기적 실행
workflow_dispatch: # 수동 실행
# 프로젝트 루트에서
mkdir -p .github/workflows
touch .github/workflows/hello-world.yml
# .github/workflows/hello-world.yml
name: Hello World
# 언제 실행할지 정의
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# 실행할 작업들 정의
jobs:
hello:
runs-on: ubuntu-latest # 실행 환경
steps:
- name: 인사하기
run: echo "안녕하세요, GitHub Actions!"
- name: 현재 시간 출력
run: date
- name: 시스템 정보
run: |
echo "운영체제: $(uname -s)"
echo "프로세서: $(uname -m)"
echo "사용자: $(whoami)"
git add .github/
git commit -m "feat: GitHub Actions Hello World 추가"
git push origin main
my-spring-app/
├── .github/
│ └── workflows/
│ └── ci-cd.yml
├── src/
├── build.gradle
└── Dockerfile
# .github/workflows/ci-cd.yml
name: 🚀 Spring Boot CI/CD
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# 테스트 단계
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: testpassword
MYSQL_DATABASE: testdb
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- name: 코드 체크아웃
uses: actions/checkout@v4
- name: Java 17 설정
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Gradle 캐시 설정
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Gradle 실행 권한 부여
run: chmod +x gradlew
- name: 정적 분석 (Checkstyle)
run: ./gradlew checkstyleMain checkstyleTest
- name: 단위 테스트 실행
run: ./gradlew test
env:
SPRING_DATASOURCE_URL: jdbc:mysql://localhost:3306/testdb
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: testpassword
- name: 테스트 결과 발행
uses: dorny/test-reporter@v1
if: success() || failure()
with:
name: 테스트 결과
path: build/test-results/test/*.xml
reporter: java-junit
- name: 코드 커버리지
run: ./gradlew jacocoTestReport
- name: 커버리지 업로드 (Codecov)
uses: codecov/codecov-action@v3
with:
file: build/reports/jacoco/test/jacocoTestReport.xml
# 빌드 단계
build:
needs: test
runs-on: ubuntu-latest
steps:
- name: 코드 체크아웃
uses: actions/checkout@v4
- name: Java 17 설정
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Gradle 캐시 설정
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- name: JAR 빌드
run: ./gradlew bootJar
- name: 빌드 결과물 저장
uses: actions/upload-artifact@v3
with:
name: spring-boot-jar
path: build/libs/*.jar
retention-days: 30
# Docker 빌드
docker-build:
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: 코드 체크아웃
uses: actions/checkout@v4
- name: 빌드 결과물 다운로드
uses: actions/download-artifact@v3
with:
name: spring-boot-jar
path: build/libs/
- name: Docker Buildx 설정
uses: docker/setup-buildx-action@v3
- name: Container Registry 로그인
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 메타데이터 추출
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=sha,prefix={{branch}}-
- name: Docker 이미지 빌드 & 푸시
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# 배포 단계 (개발 환경)
deploy-dev:
if: github.ref == 'refs/heads/develop'
needs: [test, build, docker-build]
runs-on: ubuntu-latest
environment: development
steps:
- name: 개발 서버 배포
run: |
echo "개발 환경에 배포 중..."
echo "배포 완료: https://dev.myapp.com"
- name: 🔍 헬스체크
run: |
sleep 30
curl -f https://dev.myapp.com/actuator/health
- name: 💬 슬랙 알림 (성공)
if: success()
uses: 8398a7/action-slack@v3
with:
status: success
channel: '#dev-alerts'
text: |
개발 환경 배포 성공!
커밋: ${{ github.event.head_commit.message }}
작성자: ${{ github.actor }}
서비스: https://dev.myapp.com
테스트: 모든 테스트 통과
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
# 배포 단계 (운영 환경)
deploy-prod:
if: github.ref == 'refs/heads/main'
needs: [test, build, docker-build]
runs-on: ubuntu-latest
environment: production # GitHub Environment 보호 규칙 적용
steps:
- name: 보안 스캔
run: |
echo "보안 취약점 검사 중..."
echo "보안 검사 완료 - 문제 없음"
- name: 성능 테스트
run: |
echo "성능 테스트 실행 중..."
echo "응답시간: 평균 120ms (기준: 200ms)"
echo "처리량: 1,200 TPS (기준: 1,000 TPS)"
- name: Blue-Green 배포
run: |
echo "Blue-Green 배포 시작..."
echo "Blue 환경에 새 버전 배포"
echo "Blue 환경 헬스체크 완료"
echo "트래픽을 Blue로 전환"
echo "Green 환경 정리"
echo "배포 완료: https://myapp.com"
- name: 모니터링 설정
run: |
echo "Grafana 대시보드 업데이트"
echo "알람 규칙 적용"
echo "로그 수집 시작"
- name: 배포 성공 알림
uses: 8398a7/action-slack@v3
with:
status: success
channel: '#prod-alerts'
text: |
운영 환경 배포 성공!
버전: ${{ github.sha }}
배포자: ${{ github.actor }}
서비스: https://myapp.com
모니터링: https://grafana.myapp.com
주요 변경사항:
${{ github.event.head_commit.message }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Repository Settings → Secrets and variables → Actions
필수 Secrets:
- SLACK_WEBHOOK_URL: 슬랙 웹훅 URL
- DB_PASSWORD: 데이터베이스 비밀번호
- JWT_SECRET_KEY: JWT 시크릿 키
- AWS_ACCESS_KEY_ID: AWS 액세스 키 (AWS 배포 시)
- AWS_SECRET_ACCESS_KEY: AWS 시크릿 키
jobs:
deploy:
if: github.ref == 'refs/heads/main' # main 브랜치만
steps:
- name: 조건부 단계
if: contains(github.event.head_commit.message, '[deploy]')
run: echo "배포 키워드 감지됨!"
jobs:
test:
strategy:
matrix:
java-version: [11, 17, 21]
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java-version }}
jobs:
deploy:
environment:
name: ${{ github.ref == 'refs/heads/main' && 'production' || 'development' }}
url: ${{ github.ref == 'refs/heads/main' && 'https://prod.myapp.com' || 'https://dev.myapp.com' }}
# .github/workflows/reusable-test.yml
name: 재사용 가능한 테스트
on:
workflow_call:
inputs:
java-version:
required: true
type: string
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-java@v4
with:
java-version: ${{ inputs.java-version }}
# 다른 워크플로우에서 사용
jobs:
call-reusable:
uses: ./.github/workflows/reusable-test.yml
with:
java-version: '17'
항목 | Jenkins | GitHub Actions |
---|---|---|
설정 복잡도 | 🔴 복잡 (Groovy, 플러그인) | 🟢 간단 (YAML) |
서버 관리 | 🔴 직접 관리 필요 | 🟢 GitHub에서 관리 |
비용 | 🟡 서버 비용 발생 | 🟢 Public 무료, Private 제한적 무료 |
학습 곡선 | 🔴 가파름 | 🟢 완만함 |
커뮤니티 | 🟡 오래된 커뮤니티 | 🟢 급성장하는 커뮤니티 |
확장성 | 🟢 매우 높음 | 🟡 제한적 |
기업 지원 | 🟢 강력함 | 🟡 발전 중 |
GitHub 통합 | 🟡 플러그인 필요 | 🟢 네이티브 지원 |
- name: 🐘 Gradle 캐시
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
jobs:
test:
strategy:
matrix:
test-group: [unit, integration, e2e]
lint:
runs-on: ubuntu-latest
# test와 병렬 실행됨
on:
push:
paths-ignore:
- '**.md'
- 'docs/**'
pull_request:
paths:
- 'src/**'
- 'build.gradle'
env:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }} # ✅ 올바름
API_KEY: "my-secret-key" # ❌ 위험함
jobs:
deploy:
permissions:
contents: read # 최소한의 권한만
packages: write # 필요한 권한만
- uses: actions/checkout@v4 # ✅ 공식 액션
- uses: docker/build-push-action@v5 # ✅ 검증된 액션
- uses: random-user/unsafe-action # ❌ 위험할 수 있음
- name: 💬 실패 알림
if: failure()
uses: 8398a7/action-slack@v3
with:
status: failure
text: |
🚨 빌드 실패!
📋 브랜치: ${{ github.ref }}
👤 커밋: ${{ github.actor }}
🔗 로그: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
- name: 📊 배포 상태 업데이트
uses: chrnorm/deployment-action@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
environment: production
state: success
name: 🚀 Production Deploy # ✅ 명확함
name: CI # ❌ 모호함
- name<: 📥 코드 체크아웃
- name: ☕ Java 설정
- name: 🧪 테스트 실행
- name: 📦 빌드
- name: 🚀 배포
- name: 🧪 테스트 실행
run: |
echo "::group::Unit Tests"
./gradlew test
echo "::endgroup::"
echo "::group::Integration Tests"
./gradlew integrationTest
echo "::endgroup::"
GitHub Actions는 현재 가장 접근하기 쉽고 강력한 CI/CD 플랫폼입니다.
GitHub Actions로 현대적인 DevOps 문화를 경험해보세요! 🎉