Quick Reference
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}paths는 TypeScript와 editor가 import를 찾는 방법일 뿐, emit된 JavaScript의 alias를 바꾸지 않습니다. alias를 쓰면 bundler·test runner·Node runtime에도 같은 해석 규칙을 설정하고, package exports나 relative import로 해결되는 단순한 경계에는 alias를 늘리지 않습니다.
해석 경로
module resolution을 읽을 때 먼저 눈에 들어오면 좋은 해석 방식은 아래입니다.
- 상대 경로 import:
./utils/math - 패키지 import:
react,zod - alias import:
@/components/Button tsconfigalias 선언: 주로paths
1) module resolution은 import 문자열을 파일로 연결하는 규칙이다
import { sum } from "./math" 같은 한 줄 뒤에는, 이 경로를 어떤 파일로 해석할지 결정하는 규칙이 있습니다.
즉 import 오류는 코드 한 줄보다 해석 규칙 문제일 때가 많습니다.
import { sum } from "./math";
import { Button } from "@/components/Button";2) path alias는 긴 상대 경로를 줄이는 도구다
디렉터리가 깊어져 ../../../components/... 같은 경로가 반복되면 alias가 가독성을 크게 높일 수 있습니다.
import { Button } from "@/components/Button";대규모 프론트엔드나 모노레포에서 특히 이점이 큽니다.
3) alias는 TypeScript만 맞춘다고 끝나지 않는다
tsconfig에서 alias를 선언했다고 실제 실행 환경이 자동으로 이해하는 것은 아닙니다.
번들러, 테스트 러너, 런타임도 같은 규칙을 알아야 합니다.
{
"compilerOptions": {
"paths": {
"@/*": ["src/*"]
}
}
}최근 TypeScript에서는 paths를 baseUrl 없이 둘 수도 있으므로, baseUrl + paths를 고정 공식처럼 읽기보다 현재 도구 체인에서 정말 필요한지 같이 보는 편이 정확합니다. 핵심은 TypeScript 해석과 번들러/테스트/런타임 해석이 같은 별칭 규칙을 공유하는가입니다.
4) 가까운 참조엔 상대 경로가 오히려 더 단순할 수 있다
모든 import를 alias로 통일한다고 항상 좋아지는 것은 아닙니다. 같은 폴더나 바로 인접한 파일 정도는 상대 경로가 더 읽기 쉬운 경우도 많습니다.
5) import 문제가 나면 코드보다 설정 일치를 먼저 본다
에디터 자동완성은 되는데 테스트/빌드가 깨진다면, 대체로 code issue보다 alias 설정 불일치일 가능성이 큽니다. 핵심은 바로 그 지점을 빠르게 의심하는 것입니다.
- 에디터만 된다: TypeScript 설정만 맞았을 가능성
- 테스트만 깨진다: 테스트 러너 alias 누락 가능성
- 빌드만 깨진다: 번들러 해석 규칙 불일치 가능성
어디서 꼬이나
- 가까운 파일 한두 개 참조다: 상대 경로
- 깊은 구조에서 공통 루트를 많이 참조한다: path alias
- 해석 규칙을 조정한다:
paths, 필요 시baseUrl - editor는 되는데 실행이 안 된다: 번들러/런타임 설정도 확인
- alias가 너무 많다: 오히려 구조를 흐리는지 점검
주의할 점
tsconfig에 alias만 추가하고 런타임 도구 설정을 맞추지 않으면, 에디터에서는 되는데 실제 실행은 깨질 수 있습니다.
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}참고 링크
2 sources