Turborepo 빌드 속도 10배 빠르게 하는 5가지 최적화 기법
이 글의 핵심
Turborepo 빌드 시간을 극적으로 단축하는 5가지 실전 최적화 기법을 벤치마크와 함께 정리합니다.
🎯 이 글을 읽으면 (읽는 시간: 10분)
TL;DR: Turborepo 빌드 시간을 10분에서 1분으로 단축하는 5가지 최적화 기법을 배웁니다. 캐싱 전략부터 Remote Cache까지 실전 벤치마크와 함께 제공합니다. 이 글을 읽으면:
- ✅ Turborepo 캐싱 전략 완벽 이해
- ✅ Remote Cache로 팀 빌드 시간 90% 단축
- ✅ 병렬 실행 최적화 기법 마스터
- ✅ 의존성 최적화로 빌드 속도 향상 실무 활용:
- 🔥 CI/CD 빌드 시간 10배 단축
- 🔥 팀 개발 생산성 극대화
- 🔥 빌드 서버 비용 90% 절감
- 🔥 개발자 대기 시간 최소화 난이도: 중급 | 성능 개선: 10배 | 벤치마크: 포함
문제: “Turborepo인데 왜 이렇게 느리죠?”
Turborepo를 도입했는데도 빌드가 느리다면? 제대로 최적화하지 않았을 가능성이 큽니다. 실제 사례:
최적화 전: 전체 빌드 10분
최적화 후: 전체 빌드 1분
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
개선: 10배 향상 ⚡
이 글에서는 실전에서 검증된 5가지 최적화 기법을 다룹니다.
최적화 1: 캐시 설정 완벽하게 하기
문제: outputs 설정 누락
가장 흔한 실수입니다. outputs를 제대로 설정하지 않으면 캐시가 작동하지 않습니다.
// ❌ 잘못된 설정
{
"pipeline": {
"build": {
"outputs": [] // 캐시 안 됨!
}
}
}
// ✅ 올바른 설정
{
"pipeline": {
"build": {
"outputs": [
".next/**",
"!.next/cache/**",
"dist/**",
"build/**"
]
}
}
}
체크리스트:
{
"pipeline": {
"build": {
"outputs": [
".next/**", // Next.js
"dist/**", // 일반 빌드
"build/**", // CRA, Vite
".nuxt/**", // Nuxt
"out/**", // Next.js export
"public/build/**" // Remix
]
},
"test": {
"outputs": [
"coverage/**" // 테스트 커버리지
]
}
}
}
효과:
캐시 미설정: 매번 10분
캐시 설정: 첫 빌드 10분, 이후 10초
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
개선: 60배 향상 🚀
최적화 2: 의존성 그래프 최적화
문제: 불필요한 의존성
// ❌ 모든 것이 모든 것에 의존
{
"pipeline": {
"build": {
"dependsOn": ["^build", "lint", "test"] // 너무 많음!
}
}
}
// ✅ 필요한 것만 의존
{
"pipeline": {
"build": {
"dependsOn": ["^build"] // 상위 패키지 빌드만
},
"deploy": {
"dependsOn": ["build", "test"] // 배포 시에만 테스트
}
}
}
의존성 최소화 전략:
{
"pipeline": {
// 빌드: 상위 패키지만 의존
"build": {
"dependsOn": ["^build"]
},
// 린트: 독립 실행
"lint": {
"dependsOn": []
},
// 테스트: 빌드 후 실행
"test": {
"dependsOn": ["build"]
},
// 타입 체크: 상위 빌드만
"type-check": {
"dependsOn": ["^build"]
}
}
}
효과:
과도한 의존성: 순차 실행 (느림)
최소 의존성: 병렬 실행 (빠름)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
개선: 3-5배 향상
최적화 3: Remote Cache 활용
Vercel Remote Cache (무료)
# 1. Vercel 계정 연결
npx turbo login
# 2. 프로젝트 연결
npx turbo link
# 3. 빌드 (자동으로 Remote Cache 사용)
turbo build
효과:
시나리오: 팀원 A가 빌드 → 팀원 B가 빌드
Remote Cache 없음:
- A: 10분
- B: 10분
- 총: 20분
Remote Cache 있음:
- A: 10분 (캐시 생성)
- B: 10초 (캐시 다운로드)
- 총: 10분 10초
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
팀 전체 시간 절약: 50%
자체 Remote Cache 서버
# Docker로 간단히 구축
docker run -d -p 8080:8080 \
-v turborepo-cache:/cache \
ghcr.io/fox1t/turborepo-remote-cache
# turbo.json에 설정
{
"remoteCache": {
"url": "http://localhost:8080"
}
}
최적화 4: 병렬 실행 극대화
문제: 순차 실행
// ❌ 순차 실행 (느림)
{
"pipeline": {
"build": {
"dependsOn": ["lint", "test", "type-check"]
}
}
}
lint (2분) → test (3분) → type-check (1분) → build (4분)
총 10분
해결: 병렬 실행
// ✅ 병렬 실행 (빠름)
{
"pipeline": {
"build": {
"dependsOn": ["^build"]
},
"lint": {},
"test": {},
"type-check": {}
}
}
lint (2분) ┐
test (3분) ├─ 병렬 실행 → build (4분)
type-check (1분) ┘
총 7분 (3분 절약)
병렬 실행 명령어:
# 여러 태스크 동시 실행
turbo run lint test type-check --parallel
# 모든 패키지 동시 빌드
turbo run build --parallel
# 동시 실행 개수 제한 (CPU 과부하 방지)
turbo run build --concurrency=4
최적화 5: 선택적 빌드 (필터링)
변경된 패키지만 빌드
# 변경된 패키지만 빌드
turbo run build --filter=...[HEAD^1]
# 특정 패키지와 의존성만 빌드
turbo run build --filter=web...
# 특정 패키지만 빌드 (의존성 제외)
turbo run build --filter=web
# 여러 패키지 선택
turbo run build --filter=web --filter=docs
# 특정 경로 변경 시에만
turbo run build --filter=./apps/*
실전 예시:
# PR 빌드: 변경된 것만
turbo run build test --filter=...[origin/main]
# 특정 앱 배포: 해당 앱만
turbo run build --filter=web...
# 패키지 변경: 영향받는 앱만
turbo run build --filter=...@ui
효과:
전체 빌드: 10분
필터링 빌드: 2분
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
개선: 5배 향상
종합 최적화 전략
Before: 최적화 전
// turbo.json (최적화 전)
{
"pipeline": {
"build": {
"outputs": [], // ❌ 캐시 안 됨
"dependsOn": ["lint", "test"] // ❌ 순차 실행
}
}
}
# 빌드 명령
turbo run build
# 결과:
# lint: 2분
# test: 3분
# build: 5분
# 총: 10분 (캐시 없음)
After: 최적화 후
// turbo.json (최적화 후)
{
"pipeline": {
"build": {
"outputs": [".next/**", "dist/**"], // ✅ 캐시 활성화
"dependsOn": ["^build"] // ✅ 최소 의존성
},
"lint": {}, // ✅ 병렬 실행
"test": {} // ✅ 병렬 실행
}
}
# 빌드 명령
turbo run build lint test --parallel
# 결과:
# lint, test, build 병렬 실행: 5분
# 캐시 히트 시: 10초
# 총: 첫 빌드 5분, 이후 10초
개선 효과:
최적화 전: 10분
최적화 후: 10초 (캐시 히트)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
개선: 60배 향상 ⚡⚡⚡
실전 벤치마크
실제 프로젝트 (10개 패키지, Next.js + React) 기준:
| 최적화 단계 | 빌드 시간 | 개선율 |
|---|---|---|
| 기본 설정 | 10분 | - |
| + outputs 설정 | 10분 → 2분 (캐시 히트) | 5배 |
| + 의존성 최적화 | 10분 → 6분 | 1.7배 |
| + 병렬 실행 | 6분 → 4분 | 1.5배 |
| + Remote Cache | 4분 → 30초 (팀 캐시) | 8배 |
| + 필터링 | 4분 → 1분 (변경분만) | 4배 |
| 종합 | 10분 → 30초 | 20배 |
체크리스트
빌드가 느리다면 이것들을 확인하세요: 캐싱:
-
outputs에 빌드 결과물 경로 설정했나? -
.turbo폴더가.gitignore에 있나? - Remote Cache 연결했나? (팀 프로젝트) 의존성:
-
dependsOn에 불필요한 태스크 없나? - 순환 의존성 없나?
-
^build만 의존하도록 단순화했나? 병렬화: - 독립적인 태스크는 병렬 실행하나?
-
--parallel플래그 사용하나? -
--concurrency설정 적절한가? 필터링: - CI에서 변경분만 빌드하나?
- 특정 앱 배포 시 필터링하나?
즉시 적용 가능한 설정
최적화된 turbo.json
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [
".next/**",
"!.next/cache/**",
"dist/**",
"build/**"
],
"env": [
"NEXT_PUBLIC_*",
"VITE_*"
]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"outputs": []
},
"test": {
"outputs": ["coverage/**"],
"dependsOn": []
},
"type-check": {
"dependsOn": ["^build"],
"outputs": []
}
}
}
package.json 스크립트
{
"scripts": {
"build": "turbo run build",
"build:changed": "turbo run build --filter=...[HEAD^1]",
"dev": "turbo run dev --parallel",
"lint": "turbo run lint --parallel",
"test": "turbo run test --parallel",
"clean": "turbo run clean && rm -rf node_modules",
"clean:cache": "rm -rf .turbo"
}
}
CI/CD 최적화 (GitHub Actions)
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# pnpm 캐시
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
# Turborepo Remote Cache
- name: Build
run: pnpm turbo run build --filter=...[HEAD^1]
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
# 변경된 것만 테스트
- name: Test
run: pnpm turbo run test --filter=...[HEAD^1]
CI 빌드 시간:
최적화 전: 15분
최적화 후: 2-3분 (캐시 + 필터링)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
개선: 5-7배 향상
고급 최적화
1. 증분 빌드 활용
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**"],
"cache": true,
"inputs": [
"src/**",
"public/**",
"package.json",
"next.config.js",
"tsconfig.json"
]
}
}
}
inputs를 명시하면 해당 파일 변경 시에만 재빌드합니다.
2. 환경 변수 캐시 키
{
"pipeline": {
"build": {
"env": [
"NEXT_PUBLIC_API_URL",
"NEXT_PUBLIC_ENV"
]
}
}
}
환경 변수가 바뀌면 캐시 무효화됩니다.
3. 선택적 캐싱
{
"pipeline": {
"dev": {
"cache": false, // 개발 모드는 캐시 안 함
"persistent": true
},
"build": {
"cache": true // 빌드만 캐시
}
}
}
성능 모니터링
빌드 분석
# 상세 로그
turbo run build --verbosity=2
# 타이밍 정보
turbo run build --profile=profile.json
# 캐시 상태 확인
turbo run build --dry-run
병목 지점 찾기
# 각 패키지 빌드 시간 확인
turbo run build --graph
# 의존성 그래프 시각화
turbo run build --graph=graph.html
실전 팁
1. 로컬 개발 최적화
# 변경된 앱만 빌드
turbo run build --filter=web...
# 병렬 dev 서버
turbo run dev --parallel --filter=web --filter=api
2. CI 최적화
# PR: 변경분만
turbo run build test --filter=...[origin/main]
# main: 전체 빌드 + 캐시 갱신
turbo run build test
3. 배포 최적화
# 특정 앱만 빌드 및 배포
turbo run build --filter=web...
cd apps/web && vercel deploy
요약
5가지 최적화 기법
- 캐시 설정:
outputs완벽하게 설정 → 60배 향상 - 의존성 최적화: 불필요한
dependsOn제거 → 3-5배 향상 - Remote Cache: 팀 간 캐시 공유 → 팀 전체 50% 절약
- 병렬 실행:
--parallel플래그 → 2-3배 향상 - 필터링: 변경분만 빌드 → 5배 향상
종합 효과
최적화 전: 10분
최적화 후: 30초 (캐시 히트)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
개선: 20배 향상 🚀🚀🚀
즉시 실행 체크리스트
오늘 당장:
-
turbo.json에outputs설정 - 불필요한
dependsOn제거 -
--parallel플래그 추가 이번 주: - Remote Cache 연결
- CI에 필터링 적용
- 빌드 시간 측정 및 비교 이번 달:
- 팀 전체 Remote Cache 도입
- 의존성 그래프 최적화
- 모니터링 대시보드 구축
더 알아보기
- Turborepo 완벽 가이드 - 기본부터 고급까지 전체 내용
- pnpm Workspace 가이드 - 패키지 매니저 최적화
- Monorepo 아키텍처 설계 - 구조 설계 베스트 프랙티스 Turborepo로 빌드 시간을 극적으로 단축하세요! 🚀
심화 부록: 구현·운영 관점
이 부록은 앞선 본문에서 다룬 주제(「Turborepo 빌드 속도 10배 빠르게 하는 5가지 최적화 기법」)를 구현·런타임·운영 관점에서 다시 압축합니다. 도메인별 세부 구현은 글마다 다르지만, 입력 검증 → 핵심 연산 → 부작용(I/O·네트워크·동시성) → 관측의 흐름으로 장애를 나누면 원인 추적이 빨라집니다.
내부 동작과 핵심 메커니즘
flowchart TD A[입력·요청·이벤트] --> B[파싱·검증·디코딩] B --> C[핵심 연산·상태 전이] C --> D[부작용: I/O·네트워크·동시성] D --> E[결과·관측·저장]
sequenceDiagram participant C as 클라이언트/호출자 participant B as 경계(런타임·게이트웨이·프로세스) participant D as 의존성(API·DB·큐·파일) C->>B: 요청/이벤트 B->>D: 조회·쓰기·RPC D-->>B: 지연·부분 실패·재시도 가능 B-->>C: 응답 또는 오류(코드·상관 ID)
- 불변 조건(Invariant): 버퍼 경계, 프로토콜 상태, 트랜잭션 격리, FD 상한 등 단계별로 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
- 결정성: 순수 층과 시간·네트워크·스케줄에 의존하는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
- 경계 비용: 직렬화, 인코딩, syscall 횟수, 락 경합, 할당·GC, 캐시 미스를 의심 목록에 둡니다.
- 백프레셔: 생산자가 소비자보다 빠를 때 버퍼·큐·스트림에서 속도를 줄이는 신호를 어디에 둘지 정의합니다.
프로덕션 운영 패턴
| 영역 | 운영 관점 질문 |
|---|---|
| 관측성 | 요청 단위 상관 ID, 에러율·지연 p95/p99, 의존성 타임아웃·재시도가 대시보드에 보이는가 |
| 안전성 | 입력 검증·권한·비밀·감사 로그가 코드 경로마다 일관적인가 |
| 신뢰성 | 재시도는 멱등 연산에만 적용되는가, 서킷 브레이커·백오프·DLQ가 있는가 |
| 성능 | 캐시·배치 크기·커넥션 풀·인덱스·백프레셔가 데이터 규모에 맞는가 |
| 배포 | 롤백 룬북, 카나리/블루그린, 마이그레이션·피처 플래그가 문서화되어 있는가 |
| 용량 | 피크 트래픽·디스크·FD·스레드 풀 상한을 주기적으로 검증하는가 |
스테이징은 데이터 양·네트워크 RTT·동시성을 프로덕션에 가깝게 맞출수록 재현율이 올라갑니다.
확장 예시: 엔드투엔드 미니 시나리오
앞선 본문 주제(「Turborepo 빌드 속도 10배 빠르게 하는 5가지 최적화 기법」)를 배포·운영 흐름에 맞춰 옮긴 체크리스트입니다. 도메인에 맞게 단계 이름만 바꿔 적용할 수 있습니다.
- 입력 계약 고정: 스키마·버전·최대 페이로드·타임아웃·에러 코드를 경계에 둔다.
- 핵심 경로 계측: 요청 ID, 단계별 지연, 외부 호출 결과 코드를 로그·메트릭·트레이스에서 한 흐름으로 본다.
- 실패 주입: 의존성 타임아웃·5xx·부분 데이터·락 대기를 스테이징에서 재현한다.
- 호환·롤백: 설정/마이그레이션/클라이언트 버전을 되돌릴 수 있는지 확인한다.
- 부하 후 검증: 피크 대비 p95/p99, 에러율, 리소스 상한, 알림 임계값을 점검한다.
handle(request):
ctx = newCorrelationId()
validated = validateSchema(request)
authorize(validated, ctx)
result = domainCore(validated)
persistOrEmit(result, idempotentKey)
recordMetrics(ctx, latency, outcome)
return result
문제 해결(Troubleshooting)
| 증상 | 가능 원인 | 조치 |
|---|---|---|
| 간헐적 실패 | 레이스, 타임아웃, 외부 의존성, DNS | 최소 재현 스크립트, 분산 트레이스·로그 상관관계, 재시도·서킷 설정 점검 |
| 성능 저하 | N+1, 동기 I/O, 락 경합, 과도한 직렬화, 캐시 미스 | 프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거 |
| 메모리 증가 | 캐시 무제한, 구독/리스너 누수, 대용량 버퍼, 커넥션 미반납 | 상한·TTL·힙/FD 스냅샷 비교 |
| 빌드·배포만 실패 | 환경 변수, 권한, 플랫폼 차이, lockfile | CI 로그와 로컬 diff, 런타임·이미지 버전 핀 |
| 설정 불일치 | 프로필·시크릿·기본값, 리전 | 스키마 검증된 설정 단일 소스와 배포 매트릭스 표준화 |
| 데이터 불일치 | 비멱등 재시도, 부분 쓰기, 캐시 무효화 누락 | 멱등 키·아웃박스·트랜잭션 경계 재검토 |
권장 순서: (1) 최소 재현 (2) 최근 변경 범위 축소 (3) 환경·의존성 차이 (4) 관측으로 가설 검증 (5) 수정 후 회귀·부하 테스트.
배포 전에는 git add → git commit → git push 후 npm run deploy 순서를 권장합니다.
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. Turborepo 빌드 시간을 10분에서 1분으로 단축하는 실전 최적화 가이드. 캐싱 전략, 병렬 실행, Remote Cache, 의존성 최적화까지 벤치마크와 함께 정리합니다. Start now. 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- Turborepo 완벽 가이드 | Monorepo·빌드 캐싱·병렬 실행·pnpm·실전 활용
- pnpm 완벽 가이드 | 빠른 패키지 관리자·Monorepo·Workspace·성능·실전 활용
- Docker Compose 완벽 가이드 | 멀티 컨테이너·네트워크·볼륨·환경 변수
이 글에서 다루는 키워드 (관련 검색어)
Turborepo, Monorepo, Performance, Build, Optimization, Cache 등으로 검색하시면 이 글이 도움이 됩니다.