Ch4. Turborepo 파이프라인과 캐싱
Task pipeline 설계, dependsOn, remote caching, 빌드 최적화
turbo.json 파이프라인 설계
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"globalEnv": ["NODE_ENV", "VERCEL_URL"],
"tasks": {
"build": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": [".next/**", "!.next/cache/**", "dist/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"dependsOn": ["^build"]
},
"test": {
"dependsOn": ["^build"],
"inputs": ["src/**", "tests/**", "vitest.config.*"]
},
"typecheck": {
"dependsOn": ["^build"]
}
}
}dependsOn과 실행 순서
| 접두사 | 의미 | 예시 |
|---|---|---|
^ | 의존 패키지의 태스크 먼저 실행 | "dependsOn": ["^build"] |
| 없음 | 같은 패키지 내 태스크 먼저 실행 | "dependsOn": ["lint"] |
$ | 특정 패키지의 태스크 지정 | "dependsOn": ["@org/types#build"] |
^build는 "내가 의존하는 모든 패키지의 build가 끝난 뒤 내 build를 시작하라"는 의미입니다. Turborepo가 의존성 그래프를 분석해 최대 병렬성으로 실행합니다.
Content-aware hashing
Turborepo는 파일 내용을 해싱하여 캐시 히트를 판단합니다.
해시 입력:
├── 소스 파일 내용 (inputs에 매칭되는 파일)
├── 의존 패키지의 해시
├── turbo.json의 태스크 설정
├── env에 선언된 환경 변수 값
└── globalDependencies 파일 내용타임스탬프가 아닌 내용 기반이므로, 파일을 되돌려도 이전 캐시를 그대로 사용합니다.
Remote caching
| 방식 | 설정 | 장점 | 단점 |
|---|---|---|---|
| Vercel | npx turbo login + npx turbo link | 제로 설정, 팀 자동 공유 | Vercel 계정 필요 |
| 자체 S3 | turbo.json에 endpoint 설정 | 완전 통제, 비용 최적화 | 서버 운영 필요 |
| GitHub Actions Cache | actions/cache + .turbo | CI 한정, 추가 인프라 없음 | 팀원 로컬에선 불가 |
# Vercel Remote Cache 연결
npx turbo login
npx turbo link
# CI 환경 변수 (GitHub Actions)
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}환경 변수와 캐시 무효화
{
"globalEnv": ["NODE_ENV"], // 모든 태스크의 캐시 키에 포함
"globalPassThroughEnv": ["CI"], // 캐시 키에서 제외 (런타임에만 사용)
"tasks": {
"build": {
"env": ["DATABASE_URL"], // 이 태스크 캐시 키에만 포함
"passThroughEnv": ["DEBUG"] // 이 태스크에서 캐시 키 제외
}
}
}캐시 포이즌 방지
NEXT_PUBLIC_* 환경 변수를 env에 선언하지 않으면, 환경 변수가 바뀌어도 이전 캐시가 사용됩니다.
빌드 결과에 영향을 주는 환경 변수는 반드시 env에 명시하세요.
캐시 디버깅
# 캐시 히트/미스 상세 확인
turbo run build --summarize
# 특정 패키지만 빌드 (필터)
turbo run build --filter=apps/web
# 변경된 패키지만 빌드 (since)
turbo run build --filter=...[HEAD~1]
# 캐시 무시하고 전체 빌드
turbo run build --force--summarize 플래그는 .turbo/runs/ 디렉토리에 JSON 리포트를 생성합니다. 캐시 미스가 발생한 이유를 추적할 때 유용합니다.
2025~2026 Turborepo 신기능
Composable Configuration (2026.1)
turbo.jsonc 지원과 함께 설정을 앱/패키지별로 분리 합성할 수 있게 됐습니다:
// apps/web/turbo.json — 앱별 태스크 오버라이드
{
"extends": ["//"],
"tasks": {
"build": {
"env": ["NEXT_PUBLIC_API_URL"]
}
}
}Sidecar Tasks (2025.10)
메인 태스크와 함께 실행되는 보조 프로세스를 선언할 수 있습니다. 개발 서버와 함께 타입 체크 워처를 자동 실행하는 등의 패턴에 유용합니다.
Boundaries (실험적)
패키지 간 의존성 규칙을 선언적으로 정의하고 위반을 감지합니다. 캐싱 안전성을 높이고 모노레포 아키텍처 규칙을 자동 검증합니다.
// turbo.json
{
"boundaries": {
"tags": {
"packages/ui": ["ui"],
"packages/db": ["data"]
},
"deny": [
{ "from": "ui", "to": "data" }
]
}
}기타 변경
| 항목 | 버전 | 설명 |
|---|---|---|
| turbo.jsonc | 2.3 | JSONC(주석 허용) 설정 파일 지원 |
$TURBO_ROOT$ | 2.3 | 루트 디렉토리 참조 변수 |
| Devtools | 2.4 | 태스크 그래프 시각화 도구 |
| Microfrontends | 2.4 | 마이크로프론트엔드 빌드 지원 |
| Bun 패키지 매니저 | 2.4 | Bun 안정화 지원 |