---
id: devops-cicd-pipeline-patterns
title: CI/CD Pipeline 패턴
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [devops, cicd, github-actions, vibe-coding]
tech_stack: { language: "GitHub Actions / GitLab CI", applicable_to: ["Backend", "Web", "Mobile"] }
applied_in: []
aliases: [GitHub Actions, fan-out, matrix, artifacts, secrets]
---

# CI/CD Pipeline

> 빠르고 신뢰할 수 있는 파이프라인 = (1) 매 PR 5분 안 검증, (2) 캐시 적극 활용, (3) **fan-out/fan-in** 으로 병렬, (4) deploy 가 원자적 + 롤백 1분.

## 📖 핵심 개념
- Trigger: PR / push / cron / manual.
- Stages: lint → typecheck → test → build → deploy.
- Artifact: stage 사이 파일 전달.
- Secret: 환경별 token.
- Cache: deps / build output.

## 💻 코드 패턴 (GitHub Actions)

### 기본 PR 검증
```yaml
name: PR Check
on:
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20', cache: 'npm' }
      - run: npm ci
      - run: npm run lint
      - run: npm run typecheck
      - run: npm test -- --coverage
      - uses: codecov/codecov-action@v4
```

### Matrix — 병렬
```yaml
test:
  strategy:
    matrix:
      node: ['18', '20']
      os: [ubuntu-latest, macos-latest]
  runs-on: ${{ matrix.os }}
  steps:
    - uses: actions/setup-node@v4
      with: { node-version: ${{ matrix.node }} }
    - run: npm test
```

### Fan-out / fan-in — build 한 번 → 여러 곳 deploy
```yaml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with: { name: dist, path: dist/ }

  deploy-staging:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with: { name: dist }
      - run: ./scripts/deploy.sh staging

  deploy-prod:
    needs: build
    if: github.ref == 'refs/heads/main'
    environment: production  # 승인 필요
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with: { name: dist }
      - run: ./scripts/deploy.sh prod
```

### Cache 전략
```yaml
- uses: actions/cache@v4
  with:
    path: |
      node_modules
      .next/cache
    key: ${{ runner.os }}-deps-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-deps-
```

### Concurrency — 같은 PR 만 최신 한 개
```yaml
concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true
```

### Reusable workflow
```yaml
# .github/workflows/test.yml (reusable)
on: { workflow_call: { inputs: { node: { type: string } } } }
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: ${{ inputs.node }} }
      - run: npm ci && npm test

# 호출
- uses: ./.github/workflows/test.yml
  with: { node: '20' }
```

## 🤔 의사결정 기준
| 단계 | 빈도 | 시간 한도 |
|---|---|---|
| Lint / format | 매 commit | < 30s |
| Typecheck | 매 PR | < 1m |
| Unit test | 매 PR | < 3m |
| Integration | 매 PR | < 5m |
| E2E | 매 PR (smoke) + main (full) | < 10m |
| Build | 매 PR (artifact 보관) | < 5m |
| Deploy staging | 매 main merge | auto |
| Deploy prod | 승인 후 | manual gate |

## ❌ 안티패턴
- **모든 step 직렬**: 30분 PR 검증 → 사람 떠남. 병렬 + cache.
- **secret hardcode**: code 또는 log 노출. 항상 secrets context.
- **cache 키 stable 안 함**: 매번 cache miss. lock file hash.
- **artifact 무한 보관**: 비용. retention.
- **production deploy 승인 없음**: 사고 위험. environment + reviewer.
- **rollback 절차 없음**: 사고 시 panic. 1-click rollback.
- **deploy 가 비원자적**: 일부 인스턴스만 새 버전 → 사고. blue-green / canary.
- **dependent test 가 한 job 안에서 실행**: 한 fail 시 모두 stop. matrix 분리.

## 🤖 LLM 활용 힌트
- "PR 검증 5분 이내 목표. cache + concurrency cancel + fan-out" 강조.
- production gate = environment + 승인.

## 🔗 관련 문서
- [[DevOps_Docker_Layer_Cache]]
- [[DevOps_Deployment_Strategies]]
