GitHub Actions

GitHub 저장소에서 직접 CI/CD 워크플로우를 자동화


GitHub 저장소에서 직접 CI/CD 워크플로우를 자동화

목표: GitHub Actions를 사용하여 완전한 CI/CD 파이프라인을 구축할 수 있는 수준


🎯 GitHub Actions 개요

아키텍처

graph TB
    subgraph "GitHub Actions"
        EVENT["🎉 Event"] -->|"트리거"| WORKFLOW["📋 Workflow"]
        WORKFLOW -->|"실행"| JOB1["🔨 Job 1"]
        WORKFLOW -->|"실행"| JOB2["🔨 Job 2"]
        
        JOB1 -->|"순차/병렬"| STEP1["1. Checkout"]
        STEP1 --> STEP2["2. Build"]
        STEP2 --> STEP3["3. Test"]
        
        subgraph "Runner"
            RUNNER["💻 GitHub Runner"]
        end
    end

핵심 개념:

  • Workflow: 자동화된 프로세스
  • Event: 트리거 (push, PR, schedule)
  • Job: 실행 단위
  • Step: Job 낭의 작업
  • Action: 재사용 가능한 단위
  • Runner: 실행 환경

📝 Workflow 작성

기본 구조

# .github/workflows/ci.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 0 * * 0'  # 매주 일요일

env:
  NODE_VERSION: '18'
  REGISTRY: ghcr.io

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run linter
        run: npm run lint
      
      - name: Build application
        run: npm run build
      
      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: build-files
          path: dist/

  test:
    needs: build
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [16, 18, 20]
        os: [ubuntu-latest, windows-latest]
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run tests
        run: npm test
      
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info

  deploy:
    needs: [build, test]
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    environment:
      name: production
      url: https://myapp.example.com
    
    steps:
      - name: Download build artifacts
        uses: actions/download-artifact@v4
        with:
          name: build-files
          path: dist/
      
      - name: Deploy to production
        run: |
          echo "Deploying to production..."
          # 배포 스크립트

🔄 이벤트 트리거

Push/PR

on:
  push:
    branches:
      - main
      - 'release/**'
    tags:
      - 'v*'
    paths:
      - 'src/**'
      - '!src/**/*.test.js'
  
  pull_request:
    branches:
      - main
    types: [opened, synchronize, reopened]

수동 실행

on:
  workflow_dispatch:
    inputs:
      environment:
        description: '배포 환경'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production
      version:
        description: '배포 버전'
        required: true
        type: string

🐳 Docker 빌드/푸시

name: Build and Push Docker Image

on:
  push:
    tags:
      - 'v*'

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Setup Docker Buildx
        uses: docker/setup-buildx-action@v3
      
      - name: Login to Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
      
      - name: Build and push
        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

☸️ Kubernetes 배포

name: Deploy to Kubernetes

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Setup kubectl
        uses: azure/setup-kubectl@v3
      
      - name: Setup Helm
        uses: azure/setup-helm@v3
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2
      
      - name: Update kubeconfig
        run: aws eks update-kubeconfig --name my-cluster
      
      - name: Deploy with Helm
        run: |
          helm upgrade --install my-app ./helm \
            --namespace production \
            --set image.tag=${{ github.sha }} \
            --wait
      
      - name: Verify deployment
        run: |
          kubectl rollout status deployment/my-app -n production

📋 체크리스트

  • Workflow 작성
  • 이벤트 트리거 설정
  • Job 정의
  • Step 구성
  • Action 사용
  • 매트릭스 빌드
  • Docker 빌드/푸시
  • Kubernetes 배포
  • Secrets 관리
  • 환경 보호
  • 알림 설정

🔗 관련 노트

  • 01-01-CI-CD-개념 — CI/CD 개념
  • 02-01-Jenkins-파이프라인 — Jenkins
  • 01-03-도커-기본 — Docker

마지막 업데이트: 2026-06-01