[TypeScript] tsc 명령어와 tsconfig.json 설정하기

들어가며
타입스크립트 교과서 4장을 공부하면서 정리한 내용입니다. 앞에서는 기본 타입과 유틸리티 타입을 다뤘는데, 이번에는 타입스크립트 코드를 실제로 검사하고 자바스크립트로 변환하는 tsc 명령어와, 그 동작을 정하는 tsconfig.json 을 정리해 보겠습니다.
브라우저나 Node.js 는 타입스크립트를 바로 실행하지 못합니다. 그래서 .ts 파일을 .js 로 바꿔주는 과정이 필요한데, 이걸 해주는 것이 타입스크립트 컴파일러 tsc 입니다.
1. 타입스크립트 설치하기
프로젝트 폴더에서 npm 으로 설치합니다.
npm i typescript
특정 버전을 쓰고 싶다면 @버전 을 붙입니다. 책과 같은 결과를 보려고 저는 책의 버전에 맞춰 설치했습니다.
npm i typescript@5.0.4
전역(-g)이 아니라 프로젝트에 설치하면, 프로젝트마다 다른 타입스크립트 버전을 쓸 수 있고 팀원들도 같은 버전을 쓰게 됩니다. 프로젝트에 설치한 tsc 는 npx 로 실행합니다.
2. tsc 명령어
자바스크립트로 변환하기
npx tsc
tsconfig.json 설정에 따라 타입 검사를 하고, .ts 파일을 .js 파일로 변환합니다.
타입 검사만 하기
npx tsc --noEmit
--noEmit 을 붙이면 .js 파일을 만들지 않고 타입 에러만 검사합니다. 실제 변환은 Vite 같은 번들러가 해주는 프로젝트에서는 tsc 를 타입 검사 용도로만 쓰는 경우가 많아서 자주 쓰는 옵션입니다.
에러가 없을 때만 변환하기
npx tsc --noEmitOnError
사실 tsc 는 타입 에러가 있어도 기본적으로 자바스크립트 파일을 만들어 버립니다. 타입은 실행에 영향을 주지 않기 때문입니다.
--noEmitOnError 를 붙이면 에러가 있을 때는 변환하지 않고 에러만 보여주고, 에러가 없을 때만 변환합니다. 에러가 있는 코드가 실수로 배포되는 것을 막을 수 있습니다.
정리
| 명령어 | 타입 검사 | JS 파일 생성 |
|---|---|---|
npx tsc |
O | 항상 |
npx tsc --noEmit |
O | X |
npx tsc --noEmitOnError |
O | 에러가 없을 때만 |
3. package.json 스크립트로 등록하기
명령어를 매번 치기 귀찮으니 package.json 의 scripts 에 등록해 두었습니다.
{
"scripts": {
"typecheck": "tsc --noEmit",
"typecheck:watch": "tsc --noEmit --watch",
"build": "tsc"
},
"devDependencies": {
"typescript": "5.0.4"
}
}
-
npm run typecheck: 타입 검사만 -
npm run typecheck:watch: 파일을 저장할 때마다 자동으로 다시 검사 (--watch) -
npm run build: 자바스크립트로 변환
scripts 안에서는 npx 를 붙이지 않아도 프로젝트에 설치된 tsc 가 실행됩니다.
4. tsconfig.json
tsc 를 어떻게 동작시킬지는 프로젝트 최상단의 tsconfig.json 에서 정합니다. 기본 파일은 다음 명령어로 만들 수 있습니다.
npx tsc --init
공부용 프로젝트에서 사용한 설정 중 주요 부분만 추리면 다음과 같습니다.
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"strict": true,
"noImplicitReturns": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"rootDir": ".",
"outDir": "./dist",
"noEmitOnError": true
},
"include": ["chapter*/**/*.ts", "chapter*/**/*.tsx"],
"exclude": ["node_modules", "dist"]
}
어떤 파일을 검사할지
-
include : 컴파일할 파일. 챕터 폴더(
chapter01,chapter02…) 안의.ts,.tsx파일만 대상으로 잡았습니다. -
exclude : 제외할 폴더.
node_modules와 결과물 폴더dist는 검사할 필요가 없습니다. -
rootDir / outDir : 원본 기준 폴더와 변환된
.js가 저장될 폴더입니다.outDir을 정하지 않으면.ts옆에.js가 생겨서 폴더가 지저분해집니다.
어떤 자바스크립트로 변환할지
-
target : 어떤 버전의 자바스크립트 문법으로 변환할지 정합니다.
ES2022면 최신 문법을 거의 그대로 유지하고,ES5처럼 낮추면 화살표 함수나 클래스 같은 문법을 옛날 문법으로 바꿔줍니다. -
module :
import/export를 어떤 모듈 방식으로 변환할지 정합니다.ESNext는import문을 그대로 둡니다. -
lib : 코드에서 사용할 수 있는 내장 타입 목록입니다.
DOM을 넣어야document,window같은 브라우저 API 의 타입을 쓸 수 있습니다.
얼마나 엄격하게 검사할지
-
strict : 엄격한 타입 검사 옵션들을 한 번에 켭니다. 2장에서 봤던 implicit any 에러(
noImplicitAny),null체크(strictNullChecks),catch의e를unknown으로 받는 것(useUnknownInCatchVariables) 등이 전부 여기에 포함됩니다. 처음부터 켜두는 것을 추천합니다. - noImplicitReturns : 함수의 일부 경로에서만 값을 반환하면 에러를 냅니다.
-
noEmitOnError : 위에서 본
--noEmitOnError를 설정 파일에 넣어둔 것입니다. 이제 그냥tsc만 실행해도 에러가 있으면 변환하지 않습니다.
그 외
-
esModuleInterop :
import React from "react"처럼 CommonJS 로 만든 라이브러리를 ES 모듈 방식으로import할 수 있게 해줍니다. -
forceConsistentCasingInFileNames :
import할 때 파일 이름의 대소문자가 실제와 다르면 에러를 냅니다. 윈도우에서는 대소문자를 구분하지 않아서 잘 되다가, 리눅스 서버에 배포하면 깨지는 문제를 막아줍니다.
마치며
tsc 는 결국 타입 검사기이자 변환기이고, 둘 중 무엇을 얼마나 엄격하게 할지는 tsconfig.json 이 정합니다. 처음에는 옵션이 너무 많아 보이지만, include / outDir / target / strict 정도만 이해해도 대부분의 프로젝트 설정은 읽을 수 있을 것 같습니다.