GitHub Actions CI/CD 파이프라인 구축 — 빌드부터 배포까지
GitHub Actions로 테스트 → 빌드 → Docker 이미지 → Kubernetes 배포까지 완전한 CI/CD 파이프라인 구축 방법. 실전 워크플로우 예시 포함.
TestForge Team ·
CI/CD 파이프라인 전체 흐름
PR Open → 테스트 → 빌드
main merge → Docker Build → ECR Push → K8s Deploy
1. 기본 CI 워크플로우 (테스트)
# .github/workflows/ci.yml
name: CI
on:
pull_request:
branches: [main, develop]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_DB: testdb
POSTGRES_USER: test
POSTGRES_PASSWORD: test
ports: ["5432:5432"]
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7-alpine
ports: ["6379:6379"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: gradle
- name: Test
run: ./gradlew test
env:
SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/testdb
SPRING_DATASOURCE_USERNAME: test
SPRING_DATASOURCE_PASSWORD: test
SPRING_REDIS_HOST: localhost
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: build/reports/tests/
2. Docker 빌드 + Registry Push
# .github/workflows/build.yml
name: Build & Push
on:
push:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=sha-
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
3. Kubernetes 배포
deploy:
needs: build
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Configure kubectl (EKS)
run: |
aws eks update-kubeconfig \
--region ap-northeast-2 \
--name my-cluster
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Deploy
run: |
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}"
kubectl set image deployment/my-app \
my-app=$IMAGE \
--namespace=production
kubectl rollout status deployment/my-app \
--namespace=production \
--timeout=5m
4. 환경별 배포 분기
on:
push:
branches:
- main → production 배포
- develop → staging 배포
- 'release/**' → pre-production 배포
jobs:
deploy:
environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
5. 보안 강화: OIDC로 AWS 인증 (Access Key 불필요)
permissions:
id-token: write
contents: read
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/github-actions-role
aws-region: ap-northeast-2
AWS IAM에서 GitHub OIDC Provider 신뢰 관계 설정 필요.
6. 슬랙 알림
- name: Notify Slack
if: always()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "${{ job.status == 'success' && '✅' || '❌' }} Deploy ${{ job.status }}: ${{ github.repository }}@${{ github.sha }}",
"blocks": [{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*${{ github.workflow }}* — <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>"
}
}]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
비용 최적화 팁
# 캐시로 빌드 시간 단축
- uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
# 변경된 파일만 실행
on:
push:
paths:
- 'src/**'
- 'Dockerfile'
- '.github/workflows/**'
# 동시 실행 제한 (같은 브랜치)
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: true
전체 파이프라인 소요 시간 목표
| 단계 | 목표 |
|---|---|
| 단위 테스트 | 2분 이내 |
| Docker 빌드 (캐시) | 1분 이내 |
| 배포 + 롤아웃 | 3분 이내 |
| 전체 | 5분 이내 |