LabHub

블로그

현대 CI/CD 파이프라인 완전 분해 — GitHub Actions, GitOps, Argo CD, BuildKit, SLSA, Sigstore, SBOM (2025)

"Continuous delivery is the ability to get changes of all types into production — safely and quickly in a sustainable way." — Jez Humble (Continuous Delivery, 2010)

CI/CD는 지루해 보인다. "빌드 돌리고, 테스트 돌리고, 배포한다." 그러나 대형 팀과 소형 팀을 가르는 가장 큰 차이가 CI/CD 파이프라인의 질이라는 건 놀라운 사실이다. Google은 "커밋 → 배포"를 분 단위로, 대부분의 한국 기업은 일 단위로 한다. 이 격차는 단순한 도구 차이가 아니라, 철학과 축적된 자동화의 차이다.

2005년의 Jenkins부터 2025년의 GitHub Actions + Argo CD + Sigstore까지. 이 글은 현대 CI/CD의 지도를 그린다.


1. CI/CD의 간단한 역사

2001 — XP와 Continuous Integration

2005 — Hudson의 탄생

2011 — Hudson → Jenkins 분할

2014 — 클라우드 CI 1세대

2019 — GitHub Actions

2020s — GitOps와 공급망 보안


2. Pipeline as Code — 철학의 전환

GUI의 시대

Jenkinsfile (2016) — 첫 걸음

YAML의 승리

예시 — GitHub Actions

name: CI
on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'
      - run: pnpm install --frozen-lockfile
      - run: pnpm test

재사용성 — Composite Action, Reusable Workflow

Composite Action: 여러 step을 하나로 묶음. Reusable Workflow: 전체 워크플로우를 다른 워크플로우에서 호출.

# 호출
jobs:
  build:
    uses: myorg/shared/.github/workflows/node-build.yml@v1
    with:
      node-version: 20

조직 전체에 일관된 빌드 표준을 강제할 수 있음.

모범 사례


3. 빌드 캐시 — CI 속도의 핵심

왜 캐시인가

로컬 캐시

원격 빌드 캐시 — 모노레포의 구원

Bazel의 Remote Execution

예시 — Turborepo

{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "test": {
      "dependsOn": ["build"]
    }
  }
}

입력 해시 = 파일 내용 + dependsOn 결과의 해시. 변경 없으면 0초에 완료.


4. Container 기반 빌드 — BuildKit과 Nixpacks

Dockerfile의 진화

Multi-stage Build

FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-slim AS runtime
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]

최종 이미지에는 소스/빌드 도구 없음. 크기 10배 감소.

BuildKit Cache Mount

RUN --mount=type=cache,target=/root/.npm \
    npm ci

레이어 간에 캐시 유지 → 재빌드 속도 ↑

Nixpacks / Buildpacks

Distroless 이미지


5. Test 병렬화 — CI 시간 반으로

Sharding

strategy:
  matrix:
    shard: [1, 2, 3, 4]
steps:
  - run: npx jest --shard=${{ matrix.shard }}/4

지능적 할당

Flaky Test 대응

E2E 병렬화


6. Artifact Management

OCI Registry — 이미지 저장소

OCI는 이미지 이상을 저장한다

OCI = 콘텐츠 주소 가능한 저장소 프로토콜이 되고 있음.

Semantic Tagging

v1.2.3        — 고정 버전
v1.2          — minor 고정
v1            — major 고정
latest        — 최신 (prod에서 금지!)
sha-abc1234   — 커밋 기반 (추적 가능)

Pull-through Cache


7. Secrets Management — OIDC의 혁명

구시대 — 장기 자격증명

OIDC 기반 — Keyless

예시 — AWS

permissions:
  id-token: write
steps:
  - uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123:role/GitHubActions
      aws-region: us-east-1

Vault / External Secrets

SOPS — 암호화된 시크릿 git에 저장


8. GitOps — Pull 모델의 우아함

Push vs Pull 배포

Push (전통): CI가 kubectl apply로 직접 배포

Pull (GitOps): 클러스터가 git을 주기적으로 확인

4원칙 (OpenGitOps)

  1. Declarative — 원하는 상태를 선언
  2. Versioned & Immutable — git에 기록
  3. Pulled Automatically — 에이전트가 적용
  4. Continuously Reconciled — 항상 감시

Argo CD

Flux

예시 — Argo CD Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
spec:
  source:
    repoURL: https://github.com/org/infra
    path: apps/my-app
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: my-app
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Argo Rollouts — Progressive Delivery와 통합

앞선 글 "Feature Flag & Progressive Delivery"와 연결:


9. Supply Chain Security — 2020년 이후 대격변

SolarWinds 충격 (2020)

SLSA — Supply chain Levels for Software Artifacts

Google 주도, OpenSSF로 이관. 4단계 성숙도:

레벨요구사항
L0요구사항 없음
L1빌드가 자동화 + 기본 provenance
L2버전 관리 + provenance 생성 서명
L3Hardened build (isolated, hermetic)
L42-party review + hermetic, reproducible

대부분의 기업은 L2-L3이 현실적 목표.

Provenance — 무엇을, 어떻게 빌드했나

Sigstore — "무료 서명 인프라"

cosign sign --yes ghcr.io/org/image:v1.0.0
cosign verify --certificate-identity "..." ghcr.io/org/image:v1.0.0

키 관리 없이도 서명 가능 — Keyless 서명의 혁명.

SBOM — Software Bill of Materials

도구

Provenance 검증 in Kubernetes


10. 배포 전략 — 안전하게 푸는 기술

(상세는 앞선 "Feature Flag & Progressive Delivery" 글 참조, 여기서는 CI/CD 관점)

Rolling Update

Blue/Green

Canary

Feature Flag


11. Dev Loop Speed — "5분 철학"

구글 내부 원칙 중 하나: "커밋 → 배포 가능 상태까지 5분 이내."

기법

  1. Incremental build — 변경된 것만
  2. Test selection — 관련 테스트만 (Bazel, Nx)
  3. Distributed execution — Remote execution
  4. Parallel pipeline — 독립 job 동시 실행
  5. Warm runner — self-hosted + 캐시 볼륨
  6. Pre-commit hook — 로컬에서 lint/format

측정 — DORA Metrics

2014년 Google DORA 팀이 제시한 4대 지표:

  1. Deployment Frequency — 배포 빈도
  2. Lead Time for Changes — 커밋 → 프로덕션 시간
  3. Change Failure Rate — 배포 실패율
  4. Time to Restore Service — 장애 복구 시간

Elite 팀:


12. 실전 예시 — 현대적 풀스택 파이프라인

name: Full CI/CD

on:
  push:
    branches: [main]
  pull_request:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: read
  id-token: write
  packages: write
  attestations: write

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'
      - run: pnpm install --frozen-lockfile
      - run: pnpm lint
      - run: pnpm test --coverage
      - uses: codecov/codecov-action@v5

  build:
    needs: test
    runs-on: ubuntu-latest
    outputs:
      digest: ${{ steps.build.outputs.digest }}
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - id: build
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          provenance: true
          sbom: true

  sign:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: sigstore/cosign-installer@v3
      - run: |
          cosign sign --yes \
            ghcr.io/${{ github.repository }}@${{ needs.build.outputs.digest }}

  deploy:
    needs: sign
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          repository: ${{ github.repository_owner }}/infra-gitops
          token: ${{ secrets.GITOPS_TOKEN }}
      - name: Update image tag
        run: |
          yq -i '.image.tag = "${{ github.sha }}"' 
          apps/my-app/values.yaml
      - run: |
          git config user.name github-actions
          git config user.email github-actions@github.com
          git commit -am "deploy: ${{ github.sha }}"
          git push
      # Argo CD가 이후 자동 sync

이 한 파일에:


13. 안티패턴 TOP 10

  1. Latest 태그 배포 — 재현 불가, 디버그 지옥
  2. CI에 장기 자격 증명 저장 — OIDC 써라
  3. 메인 브랜치 직접 빌드/배포 — Branch protection 필수
  4. Flaky test 재시도로 가림 — 근본 원인 수정
  5. npm install (vs npm ci) — lockfile 존중 안 함
  6. CI에서 sudo apt install — 빌드 환경 오염, 느림
  7. Secret을 로그에 echo — GitHub이 일부 마스킹하지만 주의
  8. Pipeline 없이 개별 CI 스크립트 — 일관성 부재
  9. 서명 없는 이미지 배포 — SolarWinds 재현 가능
  10. 빌드 시간 30분 이상 방치 — 개발 속도 마비

14. 현대 CI/CD 체크리스트


마치며 — CI/CD는 문화다

CI/CD는 도구 선택이 아니라 문화다. GitHub Actions냐 Jenkins냐보다, "커밋하면 15분 안에 staging에 가는가?" "금요일 오후 6시에도 배포할 수 있는가?" "배포 실패 시 1시간 안에 복구되는가?"가 훨씬 중요하다.

공급망 보안의 시대에는 한 걸음 더 나아가야 한다. "내가 빌드한 이것이 정확히 어떤 소스에서, 어떤 경로로 나왔는가?"를 서명된 증거로 남기는 것. SolarWinds 이후, 이 질문에 답하지 못하는 조직은 규제/고객 감사에서 걸러진다.

"Slow is smooth, and smooth is fast. But in CI/CD, fast is safe — because you catch problems before they compound." — Charity Majors (Honeycomb)


다음 글 예고 — 프론트엔드 번들러의 내전 — Webpack, Vite, esbuild, Turbopack, Rspack, Rolldown (2026)

CI/CD가 배포의 혈관이라면, 번들러는 프론트엔드 빌드의 심장이다. 다음 글에서는:

"빌드 시간 3초" 시대를 가능케 한 Rust/Go 혁명을 해부하는 여정.


"The best CI/CD pipeline is the one you don't notice. It just works, every time, for everyone." — Kelsey Hightower

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다