tsconfig.json 설정
tsconfig의 compilerOptions와 include·exclude·extends를 구성해 출력 대상, 모듈 방식, 엄격한 타입 검사 범위를 정합니다.
타입스크립트 프로젝트의 핵심은 tsconfig.json입니다.
이 파일에는 컴파일러(tsc)의 컴파일 방식과 타입 검사 기준이 모두 담깁니다.
tsconfig.json이 없으면 기본 설정에 의존하거나,
명령줄 옵션을 매번 직접 입력해야 해 작업 효율이 크게 떨어집니다.
tsconfig.json 파일은 프로젝트의 규모, 목적, 사용 환경(Node.js, 브라우저, 특정 프레임워크 등)에 따라 매우 다양한 옵션을 가질 수 있습니다.
이 절에서는 가장 중요하고 자주 사용되는 tsconfig.json의 주요 설정들을 자세히 살펴보겠습니다.
tsconfig.json의 기본 구조
tsconfig.json 파일은 JSON 형식으로 작성되며, 최상위 속성으로 compilerOptions, files, include, exclude, extends 등을 가집니다.
{
"compilerOptions": {
// 컴파일러 옵션들을 여기에 정의
"target": "es2018",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": [
// 컴파일에 포함할 파일 또는 디렉토리 패턴
"src/**/*"
],
"exclude": [
// 컴파일에서 제외할 파일 또는 디렉토리 패턴
"node_modules",
"dist"
],
"files": [
// 특정 파일을 명시적으로 포함 (거의 사용되지 않음)
// "src/main.ts"
],
"extends": "./configs/base.json" // 다른 tsconfig 파일을 상속
}설정 모양과 실행 가능한 프로젝트를 구분합니다. 위 예시의 extends를 사용하려면 configs/base.json이 실제로 있어야 합니다. files: []는 명시적으로 추가한 시작 파일이 없다는 뜻이며, 함께 적힌 include까지 비우지는 않습니다. 다만 상속이나 참조가 없는 단일 설정에 빈 files: []를 두면 타입스크립트 6.0에서 TS18002 진단이 나올 수 있습니다. 일반 단일 프로젝트는 실제 파일명을 적거나 files 항목을 생략하고 include를 사용하세요. 설정 파일을 만들었다는 사실만으로 편집기·빌드 도구·런타임이 모두 같은 설정을 사용한다고 단정하지 말고, 다음 절의 tsc -p로 선택한 프로젝트를 확인합니다.
주요 compilerOptions
compilerOptions는 tsconfig.json에서 가장 중요한 부분으로, 타입스크립트 컴파일러의 동작 방식을 제어하는 수많은 옵션들을 포함합니다.
target (ECMAScript 대상 버전)- 생성될 JavaScript 코드의 ECMAScript 버전을 지정합니다. 구형 브라우저나 Node.js 버전을 지원해야 한다면 낮은 버전을, 최신 환경이라면 높은 버전을 설정합니다.
- 값:
"ES3","ES5","ES2015"(또는"ES6"),"ES2016","ES2017","ES2018","ES2019","ES2020","ES2021","ES2022","ESNext" - 예시:
"target": "es5"(구형 브라우저 지원),"target": "es2020"(최신 문법 사용),"target": "esnext"(사용 가능한 최신 문법)
module (모듈 시스템) (7.1, 7장 2절 참조)
- 생성될 JavaScript 코드의 모듈 형식을 지정합니다.
- 값:
"commonjs","amd","umd","system","es2015","es2020","esnext","node16","nodenext" - 예시:
"module": "commonjs"(Node.js 백엔드),"module": "esnext"(프론트엔드 + 번들러)
lib (라이브러리 선언 파일)- 컴파일 시 포함할 표준 내장 API 정의 파일(
.d.ts파일) 목록을 지정합니다. 특정 전역 API(DOM, ES2015 Collections 등)를 사용하려면 명시해야 합니다. - 값:
"dom","es2015","es2016.array.include","webworker","scripthost"등. - 예시:
"lib": ["es2020", "dom"](ES2020 문법과 브라우저 DOM API 사용) - 팁:
target에 따라 일부lib가 자동으로 포함됩니다 (예:target: "es2015"는lib: ["es2015", "dom"]을 암시).
outDir (출력 디렉터리)- 컴파일된 JavaScript 파일(
.js)과 타입 정의 파일(.d.ts)이 생성될 출력 디렉터리 경로를 지정합니다. - 예시:
"outDir": "./dist"
rootDir (루트 디렉터리)- 프로젝트의 소스 파일이 위치한 루트 디렉터리를 지정합니다. 이 경로를 기준으로
outDir로의 출력 경로가 결정됩니다. - 예시:
"rootDir": "./src"
strict (엄격 모드 활성화)- 타입스크립트의 엄격한 타입 검사 옵션 묶음(
noImplicitAny,strictNullChecks,strictFunctionTypes등)을 한 번에 활성화/비활성화합니다. 개별 옵션을 명시하면 그 값이 우선합니다.true로 설정하는 것이 강력히 권장됩니다. - 값:
true|false - 예시:
"strict": true
esModuleInterop (CommonJS-ESM 호환성) (7장 2절 참조)
- CommonJS 모듈의
export와 ES 모듈의import구문 간의 상호 운용성을 향상시킵니다. Node.js 환경에서 ES 모듈처럼import구문을 사용할 때 유용하며,true로 설정하는 것이 일반적입니다. - 값:
true|false - 예시:
"esModuleInterop": true
skipLibCheck (라이브러리 타입 검사 건너뛰기)- 선언 파일(
.d.ts파일, 특히node_modules내부의 파일)에 대한 타입 검사를 건너뛸지 여부를 지정합니다. 대규모 프로젝트의 컴파일 시간을 단축하거나, 간혹 잘못된@types정의로 인해 발생하는 오류를 무시할 때 사용될 수 있습니다. 검사 시간과 선언 오류를 숨기는 위험을 비교해 선택합니다. - 값:
true|false - 예시:
"skipLibCheck": true
forceConsistentCasingInFileNames (파일 이름 대소문자 일관성)- 파일 이름의 대소문자가 일관되지 않을 경우 오류를 발생시킬지 여부를 지정합니다. Windows와 macOS는 파일 시스템이 대소문자를 구분하지 않을 수 있지만, Linux는 구분하기 때문에 플랫폼 간의 문제를 방지하는 데 도움이 됩니다.
true로 설정하는 것이 권장됩니다. - 값:
true|false - 예시:
"forceConsistentCasingInFileNames": true
declaration (타입 정의 파일 생성) (8장 2절 참조)
- 타입스크립트 소스 파일과 함께 해당 타입 정의 파일(
.d.ts파일)을 생성할지 여부를 지정합니다. 라이브러리를 배포할 때 필수적입니다. - 값:
true|false - 예시:
"declaration": true
jsx (JSX 처리 방식)- JSX 구문을 어떻게 처리할지 지정합니다. React나 Preact와 같은 UI 프레임워크를 사용할 때 필수적입니다.
- 값:
"preserve","react","react-jsx","react-jsxdev","react-native" - 예시:
"jsx": "react-jsx"(React 17+ 권장)
moduleResolution (모듈 해석 전략) (7장 4절 참조)
import문에서 모듈을 찾아내는 전략을 지정합니다.- 값:
"node","bundler","classic" - 예시:
"moduleResolution": "node"(Node.js 환경),"moduleResolution": "bundler"(모던 번들러 사용 시)
baseUrl 및 paths (절대 경로 및 별칭) (7장 4절 참조)
baseUrl: 비-상대 모듈 임포트의 기준 디렉터리를 지정합니다.paths:baseUrl을 기준으로 모듈 가져오기 경로에 대한 별칭 매핑을 정의합니다.-
예시
"baseUrl": ".", "paths": { "@components/*": ["src/components/*"], "@utils/*": ["src/utils/*"] }
sourceMap (소스 맵 생성)- 컴파일된 JavaScript 파일과 원본 TypeScript 소스 파일 간의 매핑 정보를 담은 소스 맵 파일(
.map파일)을 생성할지 여부를 지정합니다. 디버깅에 필수적입니다. - 값:
true|false - 예시:
"sourceMap": true
파일 포함 및 제외 옵션
include: 컴파일러가 타입 검사를 수행하고 컴파일할 파일이나 디렉터리 패턴(glob 패턴)의 배열을 지정합니다.rootDir와 함께 사용될 때 효과적입니다.- 예시:
"include": ["src/**/*.ts", "tests/**/*.ts"]
- 예시:
exclude:include에 의해 포함될 수 있는 파일이라도 컴파일에서 제외할 파일이나 디렉터리 패턴의 배열을 지정합니다.node_modules와 컴파일 출력 디렉터리는 기본적으로 제외됩니다.- 예시:
"exclude": ["node_modules", "dist", "**/*.spec.ts"]
- 예시:
files: 컴파일할 특정 파일들의 목록을 배열로 직접 지정합니다. 소규모 프로젝트에서만 사용되며, 일반적으로include를 선호합니다.
exclude는 include의 검색 결과를 제한할 뿐 import된 파일이나 files에 명시된 파일까지 차단하지 않습니다. rootDir도 포함 파일을 고르는 옵션이 아니라 출력 경로와 emit 범위를 제약합니다.
extends (설정 상속)
extends 속성을 사용하면 다른 tsconfig.json 파일의 설정을 상속받을 수 있습니다.
이는 여러 프로젝트나 모듈 간에 공통된 설정을 공유하고, 특정 설정을 오버라이드할 때 유용합니다.
{
"compilerOptions": {
"target": "es2020",
"module": "esnext",
"strict": true,
"esModuleInterop": true
}
}{
"extends": "./configs/base.json", // base.json 설정을 상속
"compilerOptions": {
"outDir": "./dist",
"declaration": true // base.json에는 없는 추가 옵션
},
"include": [
"src/**/*.ts"
]
}extends는 기본 설정을 읽은 뒤 현재 옵션을 덮어씁니다. files·include·exclude는 자식에 있으면 기본 배열을 대체하며 references는 상속하지 않습니다. 상대 경로는 그 설정을 작성한 파일을 기준으로 해석합니다.
주석 사용
tsconfig.json은 주석과 후행 쉼표를 허용하는 JSONC 방식으로 작성할 수 있습니다. 모든 JSON5 문법을 지원한다는 뜻은 아닙니다.
이는 설정의 목적을 설명하고 다른 개발자들이 이해하기 쉽게 만드는 데 도움이 됩니다.
{
"compilerOptions": {
"target": "es2020", // 최신 ECMAScript 문법 지원
"module": "esnext", // ES 모듈 시스템 사용
"strict": true /* 모든 엄격한 타입 검사 활성화 */
}
}tsconfig.json 파일은 타입스크립트 프로젝트의 컴파일과 타입 검사 동작을 제어하는 중심점입니다.
프로젝트 요구사항과 개발 환경에 맞춰 이 파일의 옵션을 신중하게 설정하는 것이 매우 중요합니다.
설정을 바꿀 때는 문법 출력, 모듈 해석, 타입 엄격성, 산출물의 영향을 한 번에 점검해야 예상치 못한 빌드 변화를 줄일 수 있습니다.
특히 target, module, strict, esModuleInterop, jsx, moduleResolution, baseUrl, paths 옵션은 프로젝트 구조와 런타임 동작에 큰 영향을 미치므로 충분히 이해하고 사용해야 합니다.
다음 절에서는 타입스크립트 컴파일러 tsc를 직접 실행하고 사용하는 방법에 대해 알아보겠습니다.
target은 문법 출력과 기본 lib 선택에 영향을 주지만 polyfill을 설치하지 않습니다. lib와 paths도 런타임 API나 import 경로를 자동으로 구현·변환하지 않습니다. 위 ES3와 node/classic 표기는 과거 선택지를 포함하므로 설치한 TypeScript 버전에 맞춰야 하며, 현대 Node ESM은 node16/nodenext 계열의 module·resolution 조합을 확인합니다.
아래 다이어그램은 tsconfig.json의 기본 구조와 주요 compilerOptions가 타입 해석과 빌드 결과에 주는 영향을 정리합니다.
CONFIG → PROGRAM → CHECK / EMIT
설정과 입력을 합친 프로그램에서 검사와 출력을 나눈다
extends를 먼저 읽고 현재 설정을 덮어씁니다. 유효 옵션과 파일·import 집합을 함께 사용해 프로그램을 만들며, 타입 검사와 emit의 역할을 구별합니다.
01 · MERGE
설정이 작성된 위치가 기준
상대 경로는 각 설정 파일을 기준으로 읽습니다. 현재 files·include·exclude 배열은 상속한 배열을 대체하고 references는 상속하지 않습니다.
02 · INPUT
exclude는 import를 차단하지 않는다
exclude는 include 검색만 제한합니다. import되거나 files에 명시된 파일은 입력이 될 수 있습니다. rootDir는 입력 선택이 아니라 출력 경로를 제약합니다.
03 · OUTPUT
검사와 emit을 구별한다
noEmit은 JS·선언·source map 출력을 끕니다. 필요한 선언 출력은 declaration 같은 옵션으로 선택합니다.
04 · RUNTIME
실제 loader를 별도로 검증한다
paths가 import 문자열을 다시 쓰지는 않습니다. target·lib도 런타임 API나 polyfill을 설치하지 않습니다.
유효 설정과 실제 입력을 확인한 뒤 산출물과 실행 환경을 검증합니다.
버전이 바뀌면 선택지와 기본값도 달라집니다. 위 목록은 과거 TypeScript의 선택지도 함께 설명합니다. 예를 들어 TypeScript 6.0에서는 baseUrl과 moduleResolution: "node"가 폐기 예정 옵션이며, 프로젝트에 맞는 현대 설정을 선택하는 것이 우선입니다. paths에 baseUrl이 반드시 필요한 것은 아니며(TypeScript 4.1 이후), paths만 지정하면 해당 설정 파일 위치를 기준으로 상대 경로를 해석할 수 있습니다. 설치 버전과 런타임을 확인한 뒤 설정을 선택하고, 오래된 예시의 옵션을 그대로 복사해 모든 버전에서 동작한다고 기대하지 않습니다.
파일 선택을 작은 프로젝트로 추적해 봅니다. 다음 사례는 TypeScript 4.7 이상의 Node16 옵션 조합을 사용합니다. 프로젝트 안에 아래 세 파일과 tsconfig.json만 있으며, package.json은 없다고 가정합니다. types: []는 주변의 자동 포함 @types 패키지가 이 사례에 끼어들지 않게 하는 조건입니다.
{
"compilerOptions": {
"target": "ES2020",
"module": "Node16",
"moduleResolution": "Node16",
"strict": true,
"rootDir": "./src",
"outDir": "./dist",
"types": [],
"noEmitOnError": true
},
"include": ["src/**/*.ts"],
"exclude": ["src/secret.ts", "**/*.spec.ts"]
}import { amount } from "./secret";
export const total = amount + 1;export const amount: number = 2;const value: number = "bad";tsc -p .를 실행할 때, 표준 라이브러리 선언 파일을 제외한 프로젝트 파일만 세어 다음을 설명해 보세요.
include·exclude검색으로 고른 시작 파일과, import를 따라 완성한 프로그램의 파일은 각각 무엇인가요?unused.spec.ts의 타입 오류도 진단하나요?- 처음 상태에서 어떤 JavaScript 파일을 출력하며,
total을 계산한 값은 얼마인가요? 선언 파일도 자동으로 나오나요? secret.ts만export const amount: number = "two";로 바꾸고 기존 dist가 없는 새 작업 폴더에서 다시 컴파일하면, 이 파일은 exclude되어 있으므로 오류와 출력에 영향을 주지 않을까요?
해설
- 검색으로 고른 시작 파일은
src/main.ts하나입니다. 하지만 그 파일의 import를 해석하면서src/secret.ts도 프로그램에 들어옵니다.exclude는 import 차단 규칙이 아닙니다.unused.spec.ts는 검색에서 제외되고 어디서도 import하지 않으므로 이 프로그램의 검사 대상이 아니며, 그 파일 안의 타입 오류도 여기서는 진단하지 않습니다. - 오류가 없으므로
dist/main.js와dist/secret.js를 출력합니다.rootDir아래 상대 경로를outDir아래에 유지하기 때문에dist/src/main.js가 되지 않습니다. 코드를 실행했을 때total은 3입니다.declaration: true를 지정하지 않았으므로 이 사례에서는.d.ts를 출력하지 않습니다.unused.spec.js도 출력하지 않습니다. - import로 들어온
secret.ts의 문자열을number에 대입했으므로 타입 오류가 발생합니다.noEmitOnError: true가 있어 두 JavaScript 파일 모두 새로 출력하지 않습니다. 이 옵션은 이미 남아 있는 오래된 산출물을 지우는 기능이 아니므로, 새 폴더라는 조건을 빼면 예전 dist를 새 출력으로 오해할 수 있습니다.