Skip to content

✍️ 필사 모드: 현대 CI/CD 파이프라인 완전 분해 — GitHub Actions, GitOps, Argo CD, BuildKit, SLSA, Sigstore, SBOM (2025)

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

"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

  • Kent Beck의 Extreme Programming이 CI를 처음 제창
  • "하루 여러 번 통합"
  • CruiseControl (2001) — 최초의 오픈소스 CI 서버

2005 — Hudson의 탄생

  • Sun 마이크로시스템즈의 Kohsuke Kawaguchi가 개발
  • Java 기반, 플러그인 천국
  • 쉽고 빠르게 전 세계로 확산

2011 — Hudson → Jenkins 분할

  • Oracle의 Sun 인수 후 상표권 분쟁
  • 커뮤니티 대다수가 Jenkins로 이동
  • 10년 이상 CI의 사실상 표준

2014 — 클라우드 CI 1세대

  • Travis CI — GitHub 네이티브, YAML 설정
  • CircleCI — 병렬화, Docker 기반 혁신
  • "Jenkins 안 깔아도 된다"는 각성

2019 — GitHub Actions

  • GitHub이 직접 CI를 제공
  • Marketplace 액션으로 재사용 가능
  • 2025년 현재 사실상 시장 1위

2020s — GitOps와 공급망 보안

  • Argo CD (2018), Flux (2019) — Pull 기반 배포
  • Sigstore (2021), SLSA (2021)
  • SBOM 의무화 (미국 행정명령 14028, 2021)
  • AI 기반 자동 수정 (Dependabot, Renovate, Copilot)

2. Pipeline as Code — 철학의 전환

GUI의 시대

  • Jenkins Freestyle 프로젝트는 UI 클릭으로 설정
  • 재현 불가, 버전 관리 불가, 리뷰 불가

Jenkinsfile (2016) — 첫 걸음

  • Groovy DSL로 파이프라인 정의
  • 리포지토리에 Jenkinsfile 커밋
  • 여전히 복잡하고 Groovy 문법

YAML의 승리

  • Travis → CircleCI → GitHub Actions 모두 YAML
  • 선언적, 간결, 익숙함
  • .github/workflows/*.yml 파일이 표준

예시 — 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

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

모범 사례

  • pin to SHAactions/checkout@8e5e7e5 (버전보다 안전, Dependabot 관리)
  • Matrix build — 여러 Node/Python 버전 동시 테스트
  • if conditions — skip 로직
  • concurrency group — 같은 PR에 여러 커밋 오면 이전 취소

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

왜 캐시인가

  • 빌드는 결정론적 — 같은 입력 → 같은 출력
  • 입력 해시로 출력을 조회하면 재빌드 불필요

로컬 캐시

  • npm/pnpm의 node_modules 캐시
  • Maven ~/.m2, Gradle build cache
  • actions/cache@v4로 CI 간에 공유

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

  • Turborepo (Vercel) — 원격 캐시로 "다른 개발자가 이미 빌드한 것"을 재사용
  • Nx (Nrwl) — 유사한 원격 캐시 + 분산 실행
  • Bazel — Google 내부에서 시작, 가장 강력한 Hermetic build

Bazel의 Remote Execution

  • 빌드 자체를 원격 클러스터에서
  • 수천 코어 병렬
  • Google이 모노레포에서 하루 20억 빌드하는 비결

예시 — Turborepo

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

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


4. Container 기반 빌드 — BuildKit과 Nixpacks

Dockerfile의 진화

  • 초기: 각 RUN이 레이어, 순서가 중요
  • 현재: BuildKit (2018+)이 기본
    • 병렬 빌드
    • 캐시 마운트 (--mount=type=cache)
    • 시크릿 마운트
    • 멀티 아키텍처

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

  • Cloud Native Buildpacks — Dockerfile 없이 언어 감지 → 빌드
  • Nixpacks (Railway) — Rust로 쓴 빠른 빌더
  • 단순 앱에는 훌륭, 복잡하면 Dockerfile로

Distroless 이미지

  • gcr.io/distroless/nodejs20-debian12
  • Shell 없음, 공격면 최소
  • 구글 표준, 보안 감사에 유리

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

Sharding

  • 테스트를 N개 조각으로 분할
  • 각 조각을 독립 runner에서 실행
strategy:
  matrix:
    shard: [1, 2, 3, 4]
steps:
  - run: npx jest --shard=${{ matrix.shard }}/4

지능적 할당

  • 이전 실행 시간 기반으로 균등 분배 (Jest --shard, Nx 분산 실행)
  • hot shard 문제 방지

Flaky Test 대응

  • Flaky = 같은 코드인데 때때로 실패
  • 원인: 타이밍, 공유 상태, 네트워크
  • 전략:
    • 재시도 (선택적, 남용 금지)
    • 격리 (Flaky 목록 분리 실행)
    • 뿌리 수정 — 가장 중요

E2E 병렬화

  • Playwright workers 옵션
  • 독립 DB 스키마, 독립 포트
  • 상태 격리가 핵심

6. Artifact Management

OCI Registry — 이미지 저장소

  • GitHub Container Registry (GHCR) — 무료, GitHub 연동
  • Docker Hub — 역사적, 레이트 리밋
  • AWS ECR, Google Artifact Registry, Azure ACR — 클라우드 네이티브
  • Harbor, Artifactory — 엔터프라이즈

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

  • Helm chart
  • Python wheel (oci-python)
  • Terraform module
  • SBOM, provenance

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

Semantic Tagging

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

Pull-through Cache

  • 사내 registry가 외부 registry를 캐시
  • Docker Hub 레이트 리밋 회피
  • 네트워크 지연 감소

7. Secrets Management — OIDC의 혁명

구시대 — 장기 자격증명

  • AWS_ACCESS_KEY_ID를 CI secrets에 저장
  • 유출되면 재앙
  • 갱신 부담

OIDC 기반 — Keyless

  • GitHub Actions가 자신을 증명하는 OIDC 토큰 발급
  • AWS/GCP/Azure가 그 토큰을 신뢰 → 임시 자격증명 발급
  • 장기 비밀이 아예 존재하지 않음

예시 — 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

  • HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager
  • External Secrets Operator — K8s에서 자동 주입
  • Secret rotation이 실제로 작동

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

  • Mozilla SOPS (Secrets Operations)
  • KMS/PGP로 암호화된 YAML/JSON
  • GitOps 친화적

8. GitOps — Pull 모델의 우아함

Push vs Pull 배포

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

  • CI가 클러스터 자격 증명을 가져야 함 (보안 위험)
  • 상태 drift 탐지 어려움

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

  • 자격 증명 CI에 노출 안됨
  • Git = 단일 진실 소스
  • drift 탐지/자동 복구

4원칙 (OpenGitOps)

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

Argo CD

  • CNCF Graduated
  • 웹 UI가 강력 — 앱별 상태, diff, sync
  • Application CRD로 선언
  • Kustomize/Helm 네이티브 지원
  • Multi-cluster 지원

Flux

  • CNCF Graduated
  • CLI 중심, Argo보다 가벼움
  • GitOps Toolkit로 모듈화

예시 — 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"와 연결:

  • Canary/Blue-Green을 Kubernetes 네이티브로
  • Analysis Template로 자동 rollback

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

SolarWinds 충격 (2020)

  • 해커가 빌드 시스템에 침투
  • 악성 코드를 정상 소프트웨어에 주입
  • 18,000+ 고객에 배포
  • CI/CD 자체가 공격 대상임을 드러냄

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 — 무엇을, 어떻게 빌드했나

  • 어떤 소스(git SHA)
  • 어떤 빌더(GitHub Actions runner)
  • 어떤 의존성
  • 어떤 파라미터
  • in-toto attestation 형식

Sigstore — "무료 서명 인프라"

  • Linux Foundation 프로젝트
  • Cosign — 이미지/아티팩트 서명
  • Fulcio — keyless 인증서 발급 (OIDC 기반)
  • Rekor — 투명성 로그
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

  • 빌드 결과물에 포함된 모든 의존성 목록
  • 포맷: SPDX, CycloneDX
  • 미국 행정명령 14028 — 연방 정부 납품 필수
  • EU CRA (Cyber Resilience Act) — 2025-2027 시행

도구

  • Syft — SBOM 생성 (Anchore)
  • Grype — CVE 스캔 (SBOM 기반)
  • Trivy — 통합 스캐너 (Aqua)
  • Dependency-Track — SBOM 집중 관리

Provenance 검증 in Kubernetes

  • Kyverno / OPA Gatekeeper 정책으로 "서명되지 않은 이미지 거부"
  • 클러스터 수준에서 enforce

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

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

Rolling Update

  • K8s 기본값, 점진적 pod 교체
  • maxSurge/maxUnavailable 튜닝
  • 간단하지만 rollback이 단순 이미지 교체

Blue/Green

  • 두 환경 병행, LB 스위칭
  • 빠른 rollback (LB만 전환)
  • 비용 2배

Canary

  • 1%, 5%, 25%, 100% 단계적 노출
  • 지표 확인 + 자동 진행/회귀
  • Argo Rollouts, Flagger 활용

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 팀:

  • 배포: 하루 여러 번
  • Lead Time: 1시간 미만
  • 실패율: 15% 미만
  • 복구: 1시간 미만

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

이 한 파일에:

  • 테스트 + 커버리지
  • 멀티 스테이지 빌드 + GHA 캐시
  • Provenance + SBOM 자동 생성
  • Keyless 서명 (Cosign + Fulcio)
  • GitOps 푸시 → Argo CD가 배포

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 체크리스트

  • Pipeline as Code — YAML이 리포지토리에
  • Branch protection + required status checks
  • Concurrency control — PR 중복 실행 취소
  • Build cache — actions/cache 또는 Turborepo/Nx
  • Multi-stage Docker build — 작은 이미지
  • OIDC 인증 — 장기 key 제거
  • 테스트 병렬화 — shard + 재시도 전략
  • SBOM + Provenance 자동 생성
  • Cosign keyless signing
  • Argo CD/Flux — pull 기반 배포
  • DORA 메트릭 대시보드
  • 배포 rollback 15분 이내 가능 훈련

마치며 — 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가 배포의 혈관이라면, 번들러는 프론트엔드 빌드의 심장이다. 다음 글에서는:

  • 번들링의 역사 — Browserify → Webpack의 독점 → JS 런타임 전쟁
  • Webpack — 왜 승자였고, 왜 내려가는가
  • esbuild — Go의 위력, 100배 빠른 빌드
  • Vite — Evan You의 "개발은 ESM, 빌드는 Rollup"
  • Turbopack — Vercel의 Rust 베팅
  • Rspack — 바이트댄스의 Rust Webpack
  • Rolldown — Vite의 다음 진화 (2025)
  • Bun bundler — 번들 + 런타임 + 패키지 매니저 통합
  • Tree-shaking, Code splitting, HMR — 기저 기술
  • Module Federation — 마이크로 프론트엔드
  • ESM in production — import maps의 부상

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


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

현재 단락 (1/381)

CI/CD는 지루해 보인다. "빌드 돌리고, 테스트 돌리고, 배포한다." 그러나 대형 팀과 소형 팀을 가르는 가장 큰 차이가 **CI/CD 파이프라인의 질**이라는 건 놀라운 사실...

작성 글자: 0원문 글자: 10,553작성 단락: 0/381