tsconfig.json 완전 가이드 — strict, paths, target 옵션 정리
tsconfig.json은 TypeScript 프로젝트의 컴파일 옵션과 파일 범위 를 정의하는 설정 파일입니다.
기본 구조
{
"compilerOptions": {
// 컴파일 옵션
},
"include": ["src/**/*"], // 포함할 파일
"exclude": ["node_modules"], // 제외할 파일
"extends": "./tsconfig.base.json", // 다른 설정 파일 상속
"references": [] // 프로젝트 레퍼런스
}
타입 검사 옵션 (Type Checking)
strict 모드
{
"compilerOptions": {
"strict": true // 아래 모든 strict 옵션을 한 번에 켬
}
}
strict: true가 켜는 옵션들:
| 옵션 | 설명 |
|---|---|
strictNullChecks | null/undefined를 별도 타입으로 취급 |
strictFunctionTypes | 함수 매개변수를 반공변적으로 검사 |
strictBindCallApply | bind, call, apply의 타입을 엄격하게 검사 |
strictPropertyInitialization | 클래스 속성 초기화를 강제 |
noImplicitAny | 타입이 any로 추론되면 에러 |
noImplicitThis | this가 any로 추론되면 에러 |
alwaysStrict | 모든 파일에 "use strict" 추가 |
useUnknownInCatchVariables | catch의 error를 unknown으로 |
새 프로젝트에서는 반드시 strict: true 를 켜는 것을 권장합니다.
추가 검사 옵션
{
"compilerOptions": {
"noUnusedLocals": true, // 사용하지 않는 지역 변수 에러
"noUnusedParameters": true, // 사용하지 않는 매개변수 에러
"noFallthroughCasesInSwitch": true, // switch fallthrough 방지
"noUncheckedIndexedAccess": true, // 인덱스 접근 시 undefined 가능성 체크
"exactOptionalPropertyTypes": true // 선택적 속성에 undefined 직접 할당 금지
}
}
noUncheckedIndexedAccess는 특히 유용합니다:
// noUncheckedIndexedAccess: true
const arr = [1, 2, 3];
const value = arr[0]; // number | undefined (범위 밖 접근 가능성)
const obj: Record<string, number> = { a: 1 };
const val = obj['b']; // number | undefined
출력 옵션 (Emit)
{
"compilerOptions": {
"target": "ES2020", // 변환할 ECMAScript 버전
"module": "ESNext", // 모듈 시스템
"outDir": "./dist", // 출력 폴더
"rootDir": "./src", // 소스 루트 폴더
"declaration": true, // .d.ts 선언 파일 생성
"declarationMap": true, // .d.ts.map 소스맵 생성
"sourceMap": true, // .js.map 소스맵 생성
"noEmit": true, // JS 파일을 생성하지 않음 (번들러 사용 시)
"removeComments": true // 주석 제거
}
}
target 선택 기준
| target | 지원 환경 |
|---|---|
ES5 | IE11 등 레거시 |
ES2015/ES6 | 구형 브라우저 지원 필요 시 |
ES2020 | 대부분의 모던 브라우저/Node.js 14+ |
ES2022 | Node.js 16+, 모던 브라우저 |
ESNext | 항상 최신 버전 |
module 선택 기준
{
"compilerOptions": {
"module": "ESNext", // 번들러 사용 시
"moduleResolution": "bundler", // Webpack, Vite 등
// 또는 Node.js 프로젝트에서
"module": "NodeNext",
"moduleResolution": "NodeNext"
}
}
경로 옵션 (Paths)
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@utils/*": ["src/utils/*"],
"@types/*": ["src/types/*"]
}
}
}
면접 포인트:
paths는 TypeScript 컴파일러에만 적용됩니다. 번들러(Webpack, Vite)나 Jest에도 동일한 경로 매핑을 설정해야 합니다.
프로젝트별 권장 설정
Next.js 프로젝트
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"module": "esnext",
"moduleResolution": "bundler",
"strict": true,
"noEmit": true,
"jsx": "preserve",
"incremental": true,
"plugins": [{ "name": "next" }],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
Node.js 서버 프로젝트
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"sourceMap": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
라이브러리 프로젝트
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["src/**/*"]
}
include/exclude
{
"include": [
"src/**/*", // src 폴더 하위 모든 파일
"types/**/*.d.ts" // 커스텀 타입 선언
],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts", // 테스트 파일 제외
"**/*.spec.ts"
]
}
extends로 설정 상속
// tsconfig.base.json — 공통 설정
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}
// tsconfig.json — 프로젝트별 설정
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"target": "ES2020",
"outDir": "./dist"
}
}
모노레포에서는 루트의 tsconfig.base.json을 각 패키지에서 상속하는 패턴이 일반적입니다.
정리
strict: true는 새 프로젝트에서 반드시 켜야 한다noUncheckedIndexedAccess는 배열/객체 접근의 안전성을 높인다target은 실행 환경에 따라,module은 번들러 사용 여부에 따라 결정한다paths는 TypeScript 컴파일러 전용이므로 번들러에도 동일 설정 필요extends로 공통 설정을 상속하면 모노레포에서 관리가 편하다
댓글 로딩 중...