LabHub

블로그

현대 CI/CD의 진화 심화 가이드 — GitHub Actions, Dagger, Turborepo, Nx, Bazel, Remote Cache, Hermetic Build, SLSA, sigstore까지 (2025)

TL;DR — CI/CD는 지난 10년간 조용한 혁명을 겪었다. Jenkins → CircleCI → GitHub Actions → Dagger의 계보, Bazel → Turborepo/Nx의 monorepo 빌드 혁명, Remote Cache 대중화(빌드 90% 단축), Hermetic Build(완벽한 재현성), SLSA + sigstore + cosign + SBOM supply chain 보안, Progressive Delivery(Flagger, Argo Rollouts)까지 — 2024-2025년 CI/CD는 "빌드 30분" 시대를 벗어나 "빌드 5분, 배포 5번/일"을 표준화했다. 이 글은 GitHub Actions 고급 패턴부터 Dagger의 "programmable pipeline", Monorepo Task Graph, SolarWinds 사건 이후 supply chain 보안의 흐름, Blue/Green · Canary · Shadow Deploy의 과학까지 — 현대 CI/CD의 전 지형도를 정리한다.

CI/CD 30년 간추리기

Phase 1: 1990s - 빌드 서버 (Hudson)

Phase 2: 2010s - CI as a Service

Phase 3: 2018-2021 - Workflow Files

Phase 4: 2022- Dagger + SDK 기반

Phase 5: 2024- AI 통합

GitHub Actions — 사실상 표준

2024년 기준 GitHub 호스팅 프로젝트의 80%+가 GitHub Actions 사용. 경쟁자 중 압도.

기본 구조

# .github/workflows/ci.yml
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

Matrix Strategy — 교차 테스트

jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        node: [18, 20, 22]
        include:
        - os: ubuntu-latest
          node: 22
          experimental: true
      fail-fast: false
    runs-on: $" + "{{" + " matrix.os " + "}}" + "
    steps:
    - run: node --version

(Note: 위 YAML의 변수 참조는 실제로는 ${{ matrix.os }} 같은 GitHub Actions 표현식이지만, MDX에서는 따로 표기.)

Reusable Workflows

# .github/workflows/reusable-test.yml
on:
  workflow_call:
    inputs:
      node-version:
        type: string
        required: true

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/setup-node@v4
      with:
        node-version: inputs.node-version

# caller workflow
jobs:
  call-test:
    uses: ./.github/workflows/reusable-test.yml
    with:
      node-version: "20"

Composite Actions

반복 스텝을 하나의 액션으로 패키징. action.ymlruns.using: 'composite'.

Secrets + OIDC

2021년 GitHub Actions OIDC 지원. 클라우드 자격증명을 장기 토큰 없이 사용.

permissions:
  id-token: write  # OIDC 토큰 발행

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: aws-actions/configure-aws-credentials@v4
      with:
        role-to-assume: arn:aws:iam::123:role/github-actions
        aws-region: us-east-1
    # 이제 AWS SDK 호출 가능, 키 없이

Self-hosted Runners

Self-hosted Runner 위협

2023년 복잡한 PwnRequest 공격 발견 — PR의 워크플로우가 self-hosted에서 실행되어 크레덴셜 유출 가능. pull_request_target 이벤트 주의.

GitLab CI, Buildkite, CircleCI — 경쟁 구도

GitLab CI

Buildkite

CircleCI

Jenkins

2025년 신흥

Dagger — "Pipeline as code"

Solomon Hykes(Docker 창시자)가 2022년 공개. CI 파이프라인을 TypeScript/Go/Python SDK로 작성.

전통적 CI YAML의 문제

Dagger 철학

// build.ts
import { dag, Container, Directory } from '@dagger.io/dagger'

export class MyModule {
  async build(source: Directory): Promise<Container> {
    return dag
      .container()
      .from("node:20")
      .withMountedDirectory("/app", source)
      .withWorkdir("/app")
      .withExec(["npm", "ci"])
      .withExec(["npm", "run", "build"])
  }
  
  async test(source: Directory): Promise<string> {
    const container = await this.build(source)
    return container.withExec(["npm", "test"]).stdout()
  }
}
# 로컬에서도 CI에서도 동일
dagger call test --source=.

이점

  1. 로컬-CI 동일성 — 같은 코드, 같은 결과
  2. 캐싱 — Dagger engine이 BuildKit 기반 자동 캐시
  3. 조합 가능 — 모듈 = 재사용 가능한 파이프라인 단위
  4. 벤더 중립 — GitHub/GitLab/Jenkins 어디서든 실행

Dagger Cloud (SaaS)

Monorepo Build 혁명

Monorepo가 다시 뜬 이유

Bazel — Google 방식

2015년 Google이 오픈소스화. 내부 Blaze의 공개 버전.

# BUILD.bazel
load("@rules_go//go:def.bzl", "go_library")

go_library(
    name = "auth",
    srcs = ["auth.go"],
    deps = ["//utils:utils"],
)

go_test(
    name = "auth_test",
    srcs = ["auth_test.go"],
    embed = [":auth"],
)

특징:

단점: 학습 곡선 가파름, 기존 npm/go build/make 대체해야.

Turborepo — JS/TS 중심

Vercel이 2021년 인수. JavaScript/TypeScript 모노레포에 집중.

// turbo.json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "dist/**"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": []
    },
    "lint": {}
  }
}

Nx — Angular → 범용

Nrwl이 만든 빌드 도구. Angular에서 시작, 지금은 범용.

nx run-many -t build test --parallel=4
nx affected -t build   # 변경된 프로젝트만

pnpm workspace + Changesets

Rush (Microsoft)

Lerna

Bazel vs Nx vs Turborepo 선택

기준BazelNxTurborepo
언어다중JS 중심, 확장 가능JS/TS
러닝 커브가파름중간완만
Remote Cache가장 강력Nx CloudTurbo Remote
Hermetic Build완벽부분부분
규모Google급수백 패키지수십-수백
설정 복잡도매우 높음중간단순

Remote Cache — 빌드 90% 단축

Remote Cache: 동료가 이미 빌드한 결과를 네트워크에서 가져옴. 한 번 빌드 = 모두 재사용.

원리

빌드 입력(소스, 의존성, 환경)의 해시 → 결과 캐시 키.

Input hash: sha256(source + deps + env)
Cache lookup: S3/GCS/CDN
  ↓ hit?
Skip execution, download result
  ↓ miss?
Execute, upload result

요구사항

  1. Hermetic — 같은 입력 = 같은 출력 (시간, 랜덤, 시스템 상태 배제)
  2. Deterministic — 병렬 실행 순서 무관
  3. Cache invalidation — 입력 변경 시 정확히 miss

도구

효과

CI 시간 단축 사례:

Hermetic Build — 완벽한 재현성

"언제 어디서 빌드해도 같은 결과".

왜 어려운가

해결책

Nix 예시

# default.nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.stdenv.mkDerivation {
  name = "my-app";
  src = ./.;
  buildInputs = [ pkgs.nodejs_20 pkgs.pnpm ];
  buildPhase = "pnpm install && pnpm build";
  installPhase = "cp -r dist $out";
}

nix-build → 2024년 Macbook과 2026년 Linux 서버에서 바이트 동일 결과.

Supply Chain Security — SolarWinds 이후

2020년 SolarWinds 공격: 해커가 빌드 프로세스에 침투, 악성 코드를 정상 업데이트로 배포. 18,000+ 고객 감염. 이후 supply chain 보안 표준화 가속.

SLSA (Supply Chain Levels for Software Artifacts)

Google 주도, 2021년 발표. 4단계 보안 레벨.

sigstore + cosign

OpenSSF 프로젝트. "아티팩트를 서명, 공개 투명성 로그에 기록".

# Cosign으로 컨테이너 이미지 서명
cosign sign --yes myregistry/myapp:v1.0.0

# 검증
cosign verify --certificate-identity "github@example.com" \
              --certificate-oidc-issuer "https://github.com/login/oauth" \
              myregistry/myapp:v1.0.0

Fulcio (CA) + Rekor (투명성 로그) + Cosign (서명 도구).

SBOM (Software Bill of Materials)

"이 소프트웨어에 들어간 모든 의존성 명세".

생성 도구:

2023년 US Executive Order 14028 → 연방 정부 구매 SW에 SBOM 요구. 업계 표준화 가속.

Dependency Review

Test 전략 — Parallelization과 Flakiness

Test Parallelization

# GitHub Actions matrix + sharding
jobs:
  test:
    strategy:
      matrix:
        shard: [1, 2, 3, 4]
    steps:
    - run: pnpm test --shard=$" + "{{" + " matrix.shard " + "}}" + "/4

Flaky Test 관리

"가끔 실패하는 테스트"는 CI 신뢰 파괴. 해결:

Test Impact Analysis

"변경 영향 받는 테스트만 실행".

Deployment Strategies

Rolling Update

Blue/Green

Canary

Shadow/Mirror

Feature Flag Deploy

Progressive Delivery (2022-)

자동화된 canary + feature flag + SLO 기반 롤백의 통합 개념.

# Flagger Canary (Istio + Prometheus)
apiVersion: flagger.app/v1beta1
kind: Canary
metadata: { name: web }
spec:
  targetRef: { apiVersion: apps/v1, kind: Deployment, name: web }
  service:
    port: 80
  analysis:
    interval: 1m
    threshold: 5
    maxWeight: 50
    stepWeight: 10
    metrics:
    - name: request-success-rate
      thresholdRange: { min: 99 }
      interval: 1m
    - name: request-duration
      thresholdRange: { max: 500 }
      interval: 30s

Prometheus 메트릭이 기준 이하이면 자동 rollback.

Container Registry와 이미지 전략

레지스트리

이미지 최적화

# Multi-stage 예시
FROM node:20 AS builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build

FROM gcr.io/distroless/nodejs20
COPY --from=builder /app/dist /app
COPY --from=builder /app/node_modules /app/node_modules
CMD ["/app/index.js"]

결과: 1GB → 150MB.

GitOps + CI/CD 통합

앞선 Kubernetes 글에서 다룬 GitOps. CI는 이미지 빌드 + manifest 업데이트 담당, CD는 ArgoCD/Flux가 수행.

[CI: GitHub Actions]
1. 코드 테스트
2. 이미지 빌드 + sigstore 서명
3. SBOM 생성
4. ghcr.io 푸시
5. manifests repo의 image tag 업데이트 (PR)
      ↓ merge
[CD: ArgoCD]
6. manifests repo 감지
7. K8s apply
8. Canary 분석 (Flagger)
9. 통과 시 전체 롤아웃

2025년 CI/CD 트렌드

1. AI 통합

2. Build Acceleration

3. Hermetic 기본화

4. Supply Chain 의무화

5. Monorepo 주류화

6. Self-Service Platforms

7. Preview Environment

실전 CI/CD 체크리스트 (2025)

  1. GitHub Actions OIDC — 클라우드 자격증명 장기 토큰 제거
  2. Matrix + Sharding — 테스트 병렬화
  3. Cache strategy — node_modules, build outputs
  4. Remote Cache — Turborepo/Nx Cloud/Bazel RBE
  5. Concurrency control — 같은 branch 중복 실행 방지
  6. Fail fast — 린트/타입체크 먼저
  7. Container build with BuildKit cache
  8. Sigstore 서명 — 이미지와 SBOM
  9. Dependabot/Renovate — 의존성 자동 업데이트
  10. Preview environments — PR별
  11. Progressive Delivery — Flagger/Argo Rollouts
  12. CI 시간 모니터링 — p95 목표 10분 이하

10가지 흔한 안티패턴

  1. pull_request_target + self-hosted — credential 유출 취약
  2. Secrets를 로그에 출력 — echo 금지
  3. No concurrency control — 중복 배포 혼란
  4. 모든 커밋 전 체크를 직렬 실행 — 느림
  5. Docker 이미지 latest 배포 — 롤백 불가
  6. 테스트 없이 main 직접 push — 프로토콜 부재
  7. Remote Cache 도입 안 하고 30분 대기 — 생산성 파괴
  8. YAML에 복잡 로직 직접 작성 — Dagger 등 SDK로
  9. SBOM 없는 프로덕션 이미지 — 감사 불가
  10. 배포 후 모니터링만, canary 없음 — 장애 전파

다음 글 예고 — "보안 기초에서 모던 Zero Trust까지" — OWASP Top 10, OAuth/OIDC, JWT, Passkeys, mTLS, SPIFFE/SPIRE, Zero Trust Architecture

CI/CD가 안전해져도 런타임 보안이 약하면 의미 없다. 2024-2025년 웹 보안은 Passkeys 주류화, Zero Trust 아키텍처 확산, JWT 피로와 대안, SPIFFE/SPIRE 워크로드 ID 표준화 등 다층 변혁이 일어났다. SolarWinds, Log4Shell, MOVEit, XZ Utils backdoor 사건이 모두의 감을 바꿨다.

다음 글에서는:

을 다룬다. '안전한 소프트웨어'가 단순히 '취약점 패치'가 아니라 아키텍처 설계의 기본 원칙이 된 시대를 추적한다.

댓글

아직 댓글이 없습니다.

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