TurboRepo로 Monorepo를 구성하면서 pre-commit 단계에서 타입 체크를 위해 husky와 lint-staged를 사용했습니다.
프로젝트마다 독립적인 tsconfig.json 설정을 유지하려다 보니, lint-staged에서 루트에 없는 tsconfig를 참조하지 못해 에러가 발생했습니다. 이에 대한 문제 해결 과정과 추가로 겪은 문제 상황을 공유하고자 합니다.
초기 설정
프로젝트 구성은 다음과 같습니다.
├── apps
│ └── client
├── packages
│ └── ui
├── package.json
기존 package.json 설정은 다음과 같았습니다.
// ./package.json
{
"lint-staged": {
"*.{ts,tsx}": [
"eslint --cache --max-warnings=0",
"tsc --noEmit"
],
"*.{ts,tsx,css,md}": "prettier --write"
}
}
위와 같이 설정했을 때 tsc가 루트의 tsconfig.json을 참조하여 타입 검사를 시도했습니다. 그러나 루트에 tsconfig.json이 없었기 때문에, 각 패키지에 개별적으로 존재하는 tsconfig 설정을 참조하지 못하고 다음과 같은 에러가 발생했습니다.
error TS2307: Cannot find module '@repo/ui' or its corresponding type declarations.
error TS17004: Cannot use JSX unless the '--jsx' flag is provided.
따라서 각 패키지 내에서 따로 타입 검사를 수행해야 했습니다.
패키지별 타입 체크 설정
먼저, apps 또는 packages 내 패키지/앱들의 하위 package.json에 아래 스크립트를 추가했습니다.
{
"scripts": {
"type-check": "tsc --noEmit"
}
}
그리고 루트 package.json의 lint-staged 설정을 아래와 같이 수정했습니다. pnpm 패키지 매니저의 filter 옵션을 이용해, 특정 패키지/앱의 파일이면 해당 앱/패키지에서 type-check 스크립트를 실행하도록 설정했습니다.
// ./package.json
{
"lint-staged": {
"*.{ts,tsx}": "eslint --cache --max-warnings=0",
"*.{ts,tsx,css,md}": "prettier --write",
"./apps/client/**/*.{ts,tsx}": "pnpm run --filter client type-check",
"./packages/ui/**/*.{ts,tsx}": "pnpm run --filter ui type-check"
}
}
에러가 해결되지 않은 경우
이렇게 설정했음에도 여전히 에러가 발생했습니다. lint-staged가 명령어 뒤에 변경된 파일 경로를 자동으로 추가하는 동작 방식 때문이었습니다. 예를 들어, 다음과 같은 형태로 명령어가 실행됩니다.
`pnpm run --filter client type-check file1.ts file2.ts`
이 경우 tsc는 파일 경로가 직접 지정되면 tsconfig.json을 무시하고 기본 설정으로만 동작하게 되며, 그 결과로 module resolution, path alias 등의 설정이 적용되지 않는 문제가 발생했습니다.
lint-staged의 변경된 파일 무시하기
이 문제를 해결하기 위해 `bash -c` 명령어를 사용했습니다. 이를 통해 lint-staged가 추가하는 파일 목록을 무시하고, 각 패키지의 tsconfig.json 설정이 정상적으로 적용되도록 했습니다. 최종 설정은 다음과 같습니다.
// ./package.json
{
"lint-staged": {
"*.{ts,tsx}": ["prettier --write", "eslint --fix"],
"./apps/client/**/*.{ts,tsx}": "bash -c 'pnpm run --filter client type-check'",
"./packages/ui/**/*.{ts,tsx}": "bash -c 'pnpm run --filter ui type-check'"
}
`bash -c`를 사용하면 lint-staged가 추가하는 파일 목록이 무시되기 때문에, 각 패키지의 tsconfig.json 설정이 정상적으로 적용되었습니다.
Reference
TurboRepo로 Monorepo를 구성하면서 pre-commit 단계에서 타입 체크를 위해 husky와 lint-staged를 사용했습니다.
프로젝트마다 독립적인 tsconfig.json 설정을 유지하려다 보니, lint-staged에서 루트에 없는 tsconfig를 참조하지 못해 에러가 발생했습니다. 이에 대한 문제 해결 과정과 추가로 겪은 문제 상황을 공유하고자 합니다.
초기 설정
프로젝트 구성은 다음과 같습니다.
├── apps
│ └── client
├── packages
│ └── ui
├── package.json
기존 package.json 설정은 다음과 같았습니다.
// ./package.json
{
"lint-staged": {
"*.{ts,tsx}": [
"eslint --cache --max-warnings=0",
"tsc --noEmit"
],
"*.{ts,tsx,css,md}": "prettier --write"
}
}
위와 같이 설정했을 때 tsc가 루트의 tsconfig.json을 참조하여 타입 검사를 시도했습니다. 그러나 루트에 tsconfig.json이 없었기 때문에, 각 패키지에 개별적으로 존재하는 tsconfig 설정을 참조하지 못하고 다음과 같은 에러가 발생했습니다.
error TS2307: Cannot find module '@repo/ui' or its corresponding type declarations.
error TS17004: Cannot use JSX unless the '--jsx' flag is provided.
따라서 각 패키지 내에서 따로 타입 검사를 수행해야 했습니다.
패키지별 타입 체크 설정
먼저, apps 또는 packages 내 패키지/앱들의 하위 package.json에 아래 스크립트를 추가했습니다.
{
"scripts": {
"type-check": "tsc --noEmit"
}
}
그리고 루트 package.json의 lint-staged 설정을 아래와 같이 수정했습니다. pnpm 패키지 매니저의 filter 옵션을 이용해, 특정 패키지/앱의 파일이면 해당 앱/패키지에서 type-check 스크립트를 실행하도록 설정했습니다.
// ./package.json
{
"lint-staged": {
"*.{ts,tsx}": "eslint --cache --max-warnings=0",
"*.{ts,tsx,css,md}": "prettier --write",
"./apps/client/**/*.{ts,tsx}": "pnpm run --filter client type-check",
"./packages/ui/**/*.{ts,tsx}": "pnpm run --filter ui type-check"
}
}
에러가 해결되지 않은 경우
이렇게 설정했음에도 여전히 에러가 발생했습니다. lint-staged가 명령어 뒤에 변경된 파일 경로를 자동으로 추가하는 동작 방식 때문이었습니다. 예를 들어, 다음과 같은 형태로 명령어가 실행됩니다.
pnpm run --filter client type-check file1.ts file2.ts
이 경우 tsc는 파일 경로가 직접 지정되면 tsconfig.json을 무시하고 기본 설정으로만 동작하게 되며, 그 결과로 module resolution, path alias 등의 설정이 적용되지 않는 문제가 발생했습니다.
lint-staged의 변경된 파일 무시하기
이 문제를 해결하기 위해 bash -c
명령어를 사용했습니다. 이를 통해 lint-staged가 추가하는 파일 목록을 무시하고, 각 패키지의 tsconfig.json 설정이 정상적으로 적용되도록 했습니다. 최종 설정은 다음과 같습니다.
// ./package.json
{
"lint-staged": {
"*.{ts,tsx}": ["prettier --write", "eslint --fix"],
"./apps/client/**/*.{ts,tsx}": "bash -c 'pnpm run --filter client type-check'",
"./packages/ui/**/*.{ts,tsx}": "bash -c 'pnpm run --filter ui type-check'"
}
bash -c
를 사용하면 lint-staged가 추가하는 파일 목록이 무시되기 때문에, 각 패키지의 tsconfig.json 설정이 정상적으로 적용되었습니다.