핵심 요약
50명 규모 TS 모노레포에서 pre-commit hook과 Git LFS 두 가지를 손봤더니 CI 빌드가 30초 단축. 사소해 보이는 변경의 누적 효과를 정리.
1. 진단 — 어디서 시간이 새는가
# GitHub Actions 빌드 트레이스
1. checkout 8s
2. install deps 45s
3. lint 18s
4. typecheck 22s
5. unit tests 34s
6. build 28s
7. e2e 72s
total 227s
린트·타입체크가 전체 작업의 18%. 그런데 이 둘은 대부분 변경되지 않은 파일까지 검사 중이었다.
2. pre-commit hook을 빠르게 — lint-staged + husky
// package.json
{
"scripts": {
"prepare": "husky"
},
"lint-staged": {
"*.{ts,tsx}": [
"biome check --apply",
"tsc --noEmit --incremental"
],
"*.md": ["prettier --write"]
}
}
# .husky/pre-commit
bunx lint-staged
핵심: 변경 파일에만 적용. CI에서도 같은 도구를 쓰면 같은 결과 보장.
3. CI 측 변경 — 변경 영향 범위만 빌드
# .github/workflows/ci.yml
- name: Detect changed files
id: changes
uses: tj-actions/changed-files@v45
- name: Run only affected tests
if: steps.changes.outputs.any_changed == 'true'
run: |
bunx affected:test --base=origin/main
Nx·Turborepo·moon 같은 모노레포 도구가 의존 그래프 기반 영향 분석을 자동화. Turborepo 사용 시:
turbo run test --filter=...[origin/main]
turbo run build --filter=...[origin/main]
4. Git LFS — 어떤 파일에 적용
| 파일 유형 | LFS 도입 |
|---|---|
| 스크린샷·디자인 PNG | O (모노레포에서 가장 큼) |
| video·gif (READMEs) | O |
| 모델 파일 (.onnx, .gguf) | O |
| 아이콘 SVG | X (텍스트, 작음) |
| 소스 코드 | X |
git lfs install
git lfs track "*.png" "*.jpg" "*.webm" "*.gguf"
# .gitattributes 자동 생성
git add .gitattributes
5. 실측 — 변경 전후
| 구간 | 변경 전 | 변경 후 |
|---|---|---|
| git clone (CI) | 14s | 8s |
| install deps | 45s | 45s |
| lint (변경 파일만) | 18s | 3s |
| typecheck (영향 범위) | 22s | 9s |
| tests (영향 범위) | 34s | 11s |
| build (영향 범위) | 28s | 14s |
| 총합 | 227s | 197s |
6. 더 큰 효과 — Turborepo 캐시
리모트 캐시 활성화 시 같은 입력에 대해 빌드 결과를 다른 PR이 재사용한다.
# turbo.json
{
"remoteCache": { "signature": true },
"tasks": {
"build": {
"outputs": [".next/**", "dist/**"],
"cache": true
},
"test": {
"dependsOn": ["^build"],
"cache": true
}
}
}
# CI에서 토큰 주입
TURBO_TOKEN=... TURBO_TEAM=... turbo build
같은 코드를 여러 PR에서 빌드 안 함 → 추가 30~50% 단축.
7. 함정
- incremental tsc 캐시 위치:
.tsbuildinfo가.gitignore에 없어 커밋되면 효과 사라짐.--incremental출력 경로를 워크스페이스 외부로 - LFS 후 재푸시: 기존 큰 파일을 LFS로 옮기려면
git lfs migrate import+ force push 필요. 팀 합의 후 진행 - 변경 감지 잘못:
changed-files가mainbase를 잘못 잡으면 모두 변경됨으로 판정 → 빌드 시간 회귀 - pre-commit hook 너무 느림: 5초 넘으면 개발자가
--no-verify로 우회. 빠른 검사만
8. 추가 권장
- concurrency 제한:
concurrency: { group: ${{ github.ref }}, cancel-in-progress: true } - self-hosted runner: 큰 모노레포는 GitHub-hosted runner CPU 부족
- 의존 그래프 캐시:
actions/setup-node의cache: 'pnpm'사용 - 매트릭스 분할: 테스트가 4분 이상이면 매트릭스로 4개 병렬
9. 측정 도구
- GitHub Actions Insights — 워크플로별 시간 분석
- Buildkite·CircleCI — 단계별 트레이스 시각화
- Turbo Run Summary — 캐시 적중률 리포트
10. 결론
"3초 단축" 작은 개선이 모이면 PR 1개당 30초, 50개 PR이면 25분, 1년이면 200시간. 인프라보다 자주 효과가 큰 영역.
참고
- turbo.build/repo/docs/core-concepts/remote-caching
- git-lfs.com

댓글 0