필사 모드: 프런트엔드 CI/CD·배포 전략 2025 — GitHub Actions·Turborepo·Vercel·Cloudflare·Preview·Canary·Feature Flag·SLSA·SBOM 완전 가이드
한국어프롤로그 — "프라이데이 배포하지 마세요"
10년 전 엔지니어링 문화에서 **금요일 배포는 금기**였다. 뭔가 터지면 주말 없이 밤샘해야 했기 때문이다. 2025년에는 이 격언이 많이 낡았다. **세상의 많은 팀은 금요일에도 하루 수십 번 배포한다.** 무엇이 바뀌었는가?
**바뀐 건 세 가지다**:
1. **배포 파이프라인이 자동화됐다** — 사람의 실수 개입 여지가 줄었다
2. **Preview Deployment가 기본이 됐다** — 프로덕션 전에 실제 환경과 동일한 URL로 검증
3. **Progressive Delivery** — Canary, Feature Flag로 "일부 사용자에게만" 먼저 배포
2025년의 주요 전환점:
1. **Monorepo Build Cache의 대중화** — Turborepo·Nx·Bazel의 Remote Cache가 무료/저렴하게 제공. 첫 빌드 10분이 두 번째 빌드 10초로
2. **Edge-first 배포** — Vercel·Cloudflare·Netlify의 Edge Function + Static 하이브리드
3. **AI 에이전트의 PR 배포** — Copilot·Cursor·Claude Code가 브랜치 생성→PR→배포까지
4. **공급망 보안 의무화** — EU CRA, 미국 EO 14028, SLSA Level 3, SBOM 제출 요구 확산
이번 글에서는 13개 챕터로 CI/CD·배포 전략을 정리한다.
1장 · CI/CD 기본 용어 재정리
네 가지 개념
- **CI (Continuous Integration)** — 코드 변경을 자주 merge + 자동 빌드·테스트
- **CD (Continuous Delivery)** — merge 후 언제든 배포 가능한 상태 유지
- **CD (Continuous Deployment)** — merge → 자동 프로덕션 배포
- **Progressive Delivery** — Canary·Feature Flag로 점진적 전달
배포 지표 — DORA 4가지
Google의 DevOps Research and Assessment가 만든 표준:
| 지표 | Elite | High | Medium | Low |
| --- | --- | --- | --- | --- |
| Deployment Frequency | 하루 여러 번 | 주 1회+ | 월 1회 | 6개월 |
| Lead Time for Changes | 1시간 미만 | 1일 미만 | 1주~1개월 | 1~6개월 |
| Change Failure Rate | 0~15% | 16~30% | 16~30% | 46~60% |
| Mean Time to Restore | 1시간 미만 | 1일 미만 | 1일~1주 | 1주~1개월 |
2023년 DORA 보고서는 **Stability(MTTR·Change Failure Rate) + Throughput(Frequency·Lead Time) 균형**이 핵심이라고 정리. "빠른 배포"만이 아니라 "안전한 빠른 배포"가 엘리트.
2장 · GitHub Actions — 2025 de facto 표준
왜 Actions가 이겼나
1. **GitHub 내장** — 별도 계정·설정 없음
2. **Marketplace** — 20,000+ 공개 Action
3. **매트릭스 빌드** — Node 18·20·22 × OS 3종 병렬
4. **Reusable Workflow** — DRY
5. **Artifact·Cache** 내장
기본 CI 워크플로우
.github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm test
- run: pnpm build
Concurrency — 동일 브랜치 이전 실행 취소
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
PR에 push를 여러 번 할 때 이전 실행을 자동 취소 → 비용 절감.
OIDC로 클라우드 자격 증명 관리
긴 수명의 `AWS_ACCESS_KEY_ID`를 GitHub Secrets에 저장하는 시대는 끝났다. OIDC Federation으로 **토큰이 매번 새로 발급**되고, GitHub Actions → AWS·GCP·Azure로 안전하게 인증.
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/github-actions-role
aws-region: ap-northeast-2
대안들
- **CircleCI** — Parallelism 세밀, Docker Executor
- **Buildkite** — Self-hosted agent, 엔터프라이즈
- **GitLab CI** — GitLab 쓰면 자연스럽다
- **Jenkins** — 여전히 레거시 엔터프라이즈 표준
**2025 스타트업·중소규모**: GitHub Actions가 기본. 빌드 시간이 수십 분이거나 비용이 문제되면 self-hosted runner 병행.
3장 · Monorepo — Turborepo·Nx·Bazel
왜 모노레포인가
- 프런트엔드(web·mobile·admin) + 디자인 시스템 + 공용 라이브러리를 **한 저장소**에
- Lockstep 버전 관리, 원자적 PR
- 공통 ESLint·TS·Test 설정 공유
Turborepo — Vercel 인수, Rust로 재작성 중
npx create-turbo@latest my-monorepo
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "dist/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": []
},
"dev": { "cache": false, "persistent": true }
}
}
Remote Cache — 협업 캐시
npx turbo login
npx turbo link
내 PC에서 빌드한 결과를 팀원과 CI가 공유. "이미 빌드한 거 또 안 함" → CI 시간 80% 감소 사례 다수.
Nx — 엔터프라이즈 모노레포
npx create-nx-workspace@latest
Turborepo 대비:
- **Nx Graph** — 의존 관계 시각화
- **Generators** — 새 앱·라이브러리 템플릿
- **Affected** — 변경된 프로젝트만 빌드 (`nx affected -t test`)
- Nx Cloud Remote Cache
Angular 생태계에서 출발했지만 React·Vue·Svelte·Node 지원.
Bazel — Google 스케일
수천 개 패키지·다언어(C++·Go·Java·TS) 섞인 초대형 모노레포에서만 의미. 셋업 비용이 크다. Uber·Airbnb·Spotify 사례.
2025 선택
- **단순·빠른**: Turborepo
- **다양한 기능·시각화**: Nx
- **초대형·다언어**: Bazel
- **아주 단순**: npm workspaces + 그냥 스크립트
4장 · 배포 플랫폼 — Vercel·Netlify·Cloudflare Pages·AWS Amplify
Vercel
- **Next.js 친화** (Vercel이 Next 개발사)
- **Preview Deployment 원조** — 모든 PR·브랜치에 고유 URL
- **Edge Function + Serverless Function** 하이브리드
- **Speed Insights·Analytics** 통합
- 비용: 호비 무료, 상용은 높은 편
Netlify
- Jamstack 원조
- Build Plugin 생태계
- Edge Function (Deno 런타임)
- Forms·Identity 기본 제공
- Vercel과 유사한 UX, 가격 약간 저렴
Cloudflare Pages + Workers
- **CDN 자체가 강점** — 330+ 도시 Edge
- **Workers** — V8 isolate 기반 경량 Edge
- **KV·D1·R2·Durable Objects** — Full stack 백엔드
- **비용이 매우 저렴** — Free tier 관대
- Next.js SSR 완벽 지원은 여전히 발전 중(OpenNext)
AWS Amplify
- AWS 리소스(Lambda·Cognito·AppSync) 통합
- 대기업·이미 AWS 사용 조직에 자연스러움
- UX는 Vercel/Netlify보다 투박
선택 기준
- **Next.js·React 중심 + Simplicity**: Vercel
- **다양한 프레임워크·Build Plugin**: Netlify
- **비용·Edge 성능·Full stack 서버리스**: Cloudflare
- **이미 AWS 기반**: Amplify
5장 · Preview Deployment — 리뷰 문화의 혁명
왜 혁명적인가
- 코드 리뷰 + **실제 동작하는 URL 리뷰**가 결합
- 디자이너·PM·QA가 PR 단계에서 직접 검증
- "머지하고 보자"가 아니라 "머지 전에 보고 결정"
동작 방식
1. PR 생성 또는 push
2. CI가 빌드 → 고유 URL(`branch-name--project.vercel.app`)에 배포
3. PR에 자동 코멘트로 URL 게시
4. 코멘트·툴바로 피드백
Vercel 기본 동작
별 설정 없이 GitHub 연결 → 모든 PR Preview 자동.
Self-host 구현
- AWS S3 + CloudFront + Route53 서브도메인
- Cloudflare Pages + Wrangler
- Kubernetes + Argo Rollouts + Namespace
Preview URL과 환경변수
- Preview에도 DB 접근이 필요 → Preview DB(Neon·PlanetScale branch)
- 실 서비스 DB 접근 금지 (데이터 오염 방지)
- 피처 플래그는 보통 **Preview는 모든 플래그 On**
2024~2025 확장 — Stagewise·Toolbar
- 페이지 위에 띄우는 "리뷰 오버레이" 툴
- 디자이너가 요소 클릭 → 코멘트 남기기
- Vercel Toolbar, v0, Stagewise가 대표 사례
6장 · Progressive Delivery — Canary·Blue-Green·Feature Flag
Blue-Green Deployment
- 현재 프로덕션(Blue)과 별도로 새 버전(Green)을 완전히 배포
- LB 스위치 한 번으로 전환
- 문제 시 즉시 롤백 가능
Canary Deployment
- 새 버전을 일부 트래픽(1%·5%·25%)에만 점진 공개
- 에러율·지연·전환율을 모니터링하며 단계적 확대
- 실패 시 해당 단계에서 롤백
Feature Flag
- **배포와 기능 공개를 분리**한다
- 코드는 배포되었지만, 플래그로 on/off 제어
- 세그먼트별 공개 가능 (특정 회사·국가·플랜)
- A/B Test·Experiment도 동일 인프라
Feature Flag 서비스 2025
- **LaunchDarkly** — 엔터프라이즈 표준
- **Flagsmith** — 오픈소스 가능
- **Unleash** — 오픈소스 + SaaS
- **PostHog Feature Flags** — Analytics·Replay와 통합
- **Vercel Edge Config + Feature Flags** — 2024년 출시, 초저지연
구현 예
const flags = await getAllFlags();
if (flags["checkout-v2"]) {
return <CheckoutV2 />;
}
Canary + Feature Flag 조합
- 코드 100% 배포 (Canary 100%)
- 기능은 Flag로 1% → 10% → 50% → 100% 점진 공개
- 문제 시 **재배포 없이 플래그만 off**
2025년의 권장 패턴: **"Deploy ≠ Release"**. 배포는 상시, 릴리스는 제품 의사결정.
7장 · Rollback 전략 — "언제든 되돌릴 수 있는가?"
자동 Rollback 조건
- **Canary 단계에서 에러율 > P50 * 2**
- **Core Web Vitals 회귀** (LCP p75 > 2.5s)
- **Synthetic Test 실패**
수동 Rollback
- Vercel: PR Revert + Redeploy (또는 이전 배포 Promote)
- Netlify·Cloudflare도 동일
- 쿠버네티스: `kubectl rollout undo`
Database Migration의 함정
코드는 쉽게 롤백돼도 **DB 스키마 변경은 비가역**. 2025 권장 패턴:
1. **Expand** — 새 컬럼·테이블 추가 (기존 코드와 호환)
2. **Migrate** — 새 코드 배포, 점진적 이동
3. **Contract** — 구 컬럼·테이블 제거 (새 코드가 안정화된 후)
이 **Expand-Contract 패턴** 덕분에 언제든 직전 배포로 안전 롤백.
Feature Flag의 Rollback 역할
- 배포 롤백보다 **Flag off**가 훨씬 빠름 (초 단위)
- 하지만 Flag에만 의존하지 말고 **실제 Revert**도 옵션으로 유지
8장 · CDN·ISR·Cache Invalidation
Frontend 배포의 Cache 3계층
1. **Browser Cache** — 브라우저 내 (`Cache-Control`)
2. **CDN Cache** — Edge 노드 (Vercel·Cloudflare·CloudFront)
3. **Origin Cache** — 서버 레벨 (Redis·Memcached)
Next.js ISR (Incremental Static Regeneration)
- 빌드 시 정적 생성
- 요청 시 "오래됨" 체크 → `revalidate` 주기 지나면 재생성
- 재생성 중에도 기존 페이지 서빙 (Stale-While-Revalidate)
// App Router
export const revalidate = 3600; // 1시간마다 재생성
// Page Router
export async function getStaticProps() {
return { props, revalidate: 3600 };
}
On-demand Revalidation
// 관리자가 상품 수정 시
revalidateTag("products");
revalidatePath("/products/[id]", "page");
Cache Invalidation의 어려움
> "There are only two hard things in Computer Science: cache invalidation and naming things." — Phil Karlton
실전:
- **Hash 기반 파일명** (Next·Vite·Turbopack) → 신버전은 새 URL
- **Tag 기반 무효화** (Next.js 14+) → 연관 데이터 그룹 단위
- **Purge API** (Cloudflare·Fastly) → 특정 URL 즉시 삭제
- **Stale-While-Revalidate 기본값** → 사용자 경험 우선
9장 · Edge·Regional·Serverless 배포
Edge — 전 세계 CDN 노드 실행
- **V8 Isolate** 기반 (Vercel Edge, Cloudflare Workers)
- Cold Start 거의 없음 (ms 단위)
- 제약: Node.js API 일부 제한, 번들 크기 제한
- 적합: 인증·지역 라우팅·A/B·개인화 경량 로직
Regional Function — 특정 Region 서버리스
- **AWS Lambda, Vercel Serverless Functions**
- Node.js 완전 호환
- Cold Start 100ms~수 초
- 적합: DB 의존 복잡 로직, 파일·이미지 처리
Static + Edge Revalidation
- 빌드 시 정적 HTML 생성 → CDN 배포
- 동적 부분만 Edge Function 또는 RSC streaming
- 2025 Next.js **PPR (Partial Prerendering)**이 이 모델
"Runtime 선언"
export const runtime = "edge"; // 또는 "nodejs"
페이지·API마다 실행 환경 선택. Edge가 빠르지만 npm 라이브러리 호환성 낮음.
10장 · Artifact·Build Cache·Remote Cache
빌드 결과물을 공유한다는 것
CI가 매번 `npm install`·`tsc`·`webpack`을 돌리면 시간·비용 폭발. **이미 같은 input으로 빌드된 결과는 재사용**.
GitHub Actions Cache
- uses: actions/cache@v4
with:
path: |
~/.pnpm-store
.next/cache
key: ${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
Turborepo Remote Cache
- 로컬·CI·팀원 간 공유
- Vercel 기본 제공 또는 자체 호스팅(S3·R2)
TURBO_TOKEN=... TURBO_TEAM=... turbo run build
Nx Cloud
- 유사 개념
- Distributed Task Execution(DTE)으로 병렬 실행 자동 분산
Docker Layer Cache
- Dockerfile 명령어별 레이어 캐시
- `FROM node:22-alpine` → `COPY package.json` → `RUN install` 순서가 중요
- 자주 바뀌는 파일을 뒤에 둬서 캐시 히트 최대화
11장 · Supply Chain 보안 — SLSA·SBOM·Sigstore
왜 의무화됐나
- 2020 SolarWinds 사건 (국가급 공급망 공격)
- 2021 US Executive Order 14028 — 정부 납품 SW는 SBOM 제출
- 2024 EU Cyber Resilience Act — 2027년 완전 적용
SBOM (Software Bill of Materials)
내가 사용하는 모든 직접·transitive 의존성 목록. **제품의 성분표**.
포맷:
- **SPDX** (Linux Foundation)
- **CycloneDX** (OWASP)
생성:
npx @cyclonedx/cyclonedx-npm --output-file sbom.json
또는
syft packages npm:. -o spdx-json
SLSA (Supply chain Levels for Software Artifacts)
Google 주도. Level 1~4로 공급망 보안 수준 표준화.
- **Level 1**: 빌드 기록 존재
- **Level 2**: 서명된 provenance
- **Level 3**: 격리된 빌드 환경, 변조 방지
- **Level 4**: 재현 가능한 빌드, 두 사람 리뷰
Sigstore·cosign
- 소프트웨어 아티팩트(컨테이너 이미지·npm 패키지·바이너리)에 **서명**
- 공개키 인프라(PKI)가 아닌 **키 없는 서명** (Keyless, OIDC 기반)
cosign sign --keyless ghcr.io/me/app:1.0
cosign verify --certificate-identity-regexp ...
npm Provenance
- 2023년 출시
- npm publish 시 GitHub Actions OIDC로 서명
- `npm install` 시 검증 가능
npm publish --provenance
한국 맥락
- ISMS-P 인증 범위에 공급망 보안 추가 논의
- 정부·금융·공공 조달에서 SBOM 요구 확산
12장 · AI 에이전트가 릴리스 PR을 만드는 2025
2024년 말~2025년의 변화
- **Dependabot**이 매일 수천 개 PR 생성·자동 머지
- **Renovate Bot**이 설정된 규칙대로 의존성 업그레이드 + 테스트 + 머지
- **Claude Code·Cursor·Devin**이 이슈 → 브랜치 → PR → Review → Merge 전체 자동화
자동 릴리스 PR 패턴
1. 이슈 라벨링 (`type:feature`, `impact:low`)
2. AI가 이슈를 읽고 변경 계획 제안
3. 사람 승인 → 에이전트가 브랜치·PR 생성
4. CI 통과 + 사람 리뷰 (Code·Preview URL)
5. 머지 → 자동 배포 → Canary 단계별 모니터링
리스크
- **자동 머지의 범위**: 의존성 patch는 OK, 프로덕션 로직은 사람이
- **롤백 권한**: AI가 만든 배포라도 롤백은 사람이
- **감사 로그**: "이 배포 누가 만들었나" 추적 가능해야
2025의 권장
- **Dependabot·Renovate**은 이미 안전. 즉시 도입.
- **에이전트 기반 기능 구현**은 점진 도입, 위험도 낮은 곳부터.
- **문서·테스트·번역**이 AI 에이전트에 가장 적합.
13장 · 체크리스트·안티패턴·다음 글 예고
CI/CD 체크리스트 (15개)
1. **GitHub Actions**(또는 CircleCI) 기본 CI: lint·test·build
2. **Concurrency cancel-in-progress**로 중복 실행 취소
3. **OIDC 인증**으로 클라우드 자격 증명 관리
4. **Turborepo/Nx Remote Cache**로 빌드 시간 단축
5. **Preview Deployment** 모든 PR에 자동
6. **Preview DB** 분리 (Neon·PlanetScale branch)
7. **Feature Flag** 기본 탑재 (LaunchDarkly·PostHog·Vercel)
8. **Canary/Blue-Green**로 Progressive Delivery
9. **자동 Rollback** 조건 정의 (에러율·Vitals 회귀)
10. **Expand-Contract** DB 마이그레이션 패턴
11. **ISR + 태그 기반 Revalidation**
12. **Edge vs Regional** 적재 적소 선택
13. **SBOM 생성** CI에 통합
14. **npm/docker provenance** 서명
15. **DORA 4 지표** 팀 대시보드
CI/CD 안티패턴 TOP 10
1. **모든 환경 변수를 GitHub Secrets에 평문 저장**
2. **Secrets를 PR 로그에 출력** (`echo ${{ secrets.X }}`)
3. **Canary 없이 Big-Bang 배포**
4. **Feature Flag를 영구적으로 유지** → dead code 폭발
5. **Preview에서 프로덕션 DB 접근**
6. **빌드 시간 30분+ 방치**
7. **DB 마이그레이션과 코드 배포 동시** (롤백 불가)
8. **CI 실패를 "그냥 재실행"** (Flaky 방치)
9. **배포 후 모니터링 미확인**
10. **의존성 업데이트를 분기별로 수동 일괄** (위험 누적)
다음 글 예고 — Season 6 Ep 13 FINALE: "2025년 프런트엔드 엔지니어로 살아가기"
Season 6의 마지막 글. 기술을 넘어 **프런트엔드 엔지니어로서의 일하기·성장하기·커뮤니티**.
- 2025년 프런트엔드의 지도 (RSC·Signals·AI·Edge)
- 풀스택 vs 스페셜리스트 vs 디자인 엔지니어
- 커뮤니티와 오픈소스 참여
- 컨퍼런스·블로그·트위터(X)의 힘
- AI와 공존하며 성장하기
- 번아웃과 지속 가능한 학습
- 한국 프런트엔드 생태계의 과제와 기회
- 다음 10년을 어떻게 준비할까
**"기술은 도구다. 도구는 사람을 위한 것이다. 프런트엔드는 결국 '사람이 쓸 것'을 만드는 일이다."**
다음 글에서 만나자.
> "CI/CD는 코드와 사용자 사이의 다리다. 다리가 튼튼하고 자동으로 점검되고 무너져도 수 분 내 수리되는 상태가 되면, 엔지니어는 **'배포가 아니라 제품'**에 집중할 수 있다. 이게 2025년의 성숙한 팀이다."
현재 단락 (1/295)
10년 전 엔지니어링 문화에서 **금요일 배포는 금기**였다. 뭔가 터지면 주말 없이 밤샘해야 했기 때문이다. 2025년에는 이 격언이 많이 낡았다. **세상의 많은 팀은 금요일에...