프로젝트 레퍼런스 — 모노레포에서 TS 빌드 최적화
프로젝트 레퍼런스(Project References)는 TypeScript 프로젝트를 여러 하위 프로젝트로 분리 해서 독립적으로 컴파일하고, 증분 빌드를 활용하는 기능입니다.
왜 프로젝트 레퍼런스가 필요한가
모노레포에서 모든 코드를 하나의 tsconfig.json으로 컴파일하면 문제가 생깁니다.
- 파일 하나를 바꿔도 전체를 다시 컴파일
- 프로젝트가 커지면 ** 타입 체크 시간이 급증**
- 패키지 간 ** 의존성이 불명확**
프로젝트 레퍼런스는 이 문제를 해결합니다.
기본 설정
my-monorepo/
├── packages/
│ ├── shared/ # 공용 유틸리티
│ │ ├── src/
│ │ └── tsconfig.json
│ ├── api/ # API 서버
│ │ ├── src/
│ │ └── tsconfig.json
│ └── web/ # 프론트엔드
│ ├── src/
│ └── tsconfig.json
└── tsconfig.json # 루트 설정
하위 프로젝트 설정
// packages/shared/tsconfig.json
{
"compilerOptions": {
"composite": true, // 필수: 프로젝트 레퍼런스에 참여
"declaration": true, // 필수: .d.ts 생성
"declarationMap": true, // 권장: Go to Definition 지원
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"]
}
// packages/api/tsconfig.json
{
"compilerOptions": {
"composite": true,
"declaration": true,
"outDir": "./dist",
"rootDir": "./src"
},
"references": [
{ "path": "../shared" } // shared 프로젝트를 참조
],
"include": ["src/**/*"]
}
루트 설정
// tsconfig.json (루트)
{
"files": [], // 루트는 직접 컴파일할 파일 없음
"references": [
{ "path": "packages/shared" },
{ "path": "packages/api" },
{ "path": "packages/web" }
]
}
tsc --build 모드
프로젝트 레퍼런스를 사용하면 --build 플래그로 빌드합니다.
# 전체 빌드 — 의존성 순서대로 컴파일
npx tsc --build
# 약자
npx tsc -b
# 변경된 것만 증분 빌드
npx tsc -b
# 깨끗하게 다시 빌드
npx tsc -b --clean
npx tsc -b --force
# 워치 모드
npx tsc -b --watch
증분 빌드의 효과
첫 빌드: shared → api → web (전체 컴파일)
shared 수정: shared → api → web (shared에 의존하는 것만 재컴파일)
api만 수정: api (api만 재컴파일)
composite: true로 설정하면 .tsbuildinfo 파일이 생성되어 이전 빌드 정보를 캐싱합니다.
prepend 옵션
// 참조 프로젝트의 출력을 현재 출력 앞에 붙이기
{
"references": [
{ "path": "../shared", "prepend": true }
]
}
prepend는 outFile을 사용할 때 참조 프로젝트의 출력을 합치는 옵션입니다. 번들러를 사용하는 경우에는 잘 쓰지 않습니다.
실전 패턴: 테스트 분리
// tsconfig.json — 소스 코드
{
"compilerOptions": {
"composite": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"]
}
// tsconfig.test.json — 테스트 코드
{
"extends": "./tsconfig.json",
"compilerOptions": {
"composite": true,
"rootDir": ".",
"outDir": "./dist-test",
"types": ["node", "jest"]
},
"references": [
{ "path": "./" } // 소스 프로젝트를 참조
],
"include": ["src/**/*", "tests/**/*"]
}
Solution Style tsconfig
IDE에서 모든 파일을 인식하도록 하는 패턴입니다.
// tsconfig.json (루트 — solution style)
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.test.json" }
]
}
주의점
composite: true는declaration: true를 필수로 요구한다- 참조 프로젝트에서 직접
.ts파일을 import하면 안 되고, 빌드된.d.ts를 통해 참조한다 .tsbuildinfo파일은.gitignore에 추가하는 것이 좋다
정리
- 프로젝트 레퍼런스는 큰 프로젝트를 하위 프로젝트로 분리해서 증분 빌드를 가능하게 한다
composite: true와declaration: true가 필수 옵션이다tsc --build로 의존성 순서대로 빌드하고, 변경된 프로젝트만 재컴파일한다- 모노레포에서 빌드 시간을 크게 줄일 수 있다
- 테스트 코드를 분리하는 패턴에도 활용할 수 있다
댓글 로딩 중...