본문 바로가기
C.W.K.
Stream
Lesson 03 of 06 · published

첫 컴파일: tsc가 실제로 하는 일

~14 min · foundations, tsc, tsconfig, first-compile

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"한 번 직접 출력 파일을 보면 ‘타입이 지워진다’는 설명이 지식에서 감각으로 바뀌어."

가장 작은 실험

새 폴더에 hello.ts를 만들고 숫자와 문자열에 타입을 붙여 봐. 그다음 npx tsc hello.ts를 실행하면 같은 폴더에 hello.js가 생겨. 두 파일을 나란히 열어 보면 타입 표기가 사라지고 실행 가능한 JavaScript만 남은 것을 볼 수 있어. 이 짧은 실험이 TypeScript의 전체 경계를 보여 줘.

tsc는 두 일을 할 수 있어. 타입을 검사하고, 필요하면 목표 JavaScript 버전에 맞춰 코드를 출력해. 하지만 현대 프로젝트에서는 두 일을 꼭 한 도구에 맡기지 않아. Vite나 esbuild가 빠르게 출력하고 tsc --noEmit은 타입 검사만 맡는 구성이 흔해. 역할을 나누면 각 도구가 잘하는 일에 집중할 수 있지.

오류가 있어도 출력될 수 있다는 함정

noEmitOnError의 기본값은 false라서, 별도 설정이 없으면 타입 오류를 보고하고도 JavaScript를 출력해. 편집 중 결과를 계속 확인하기에는 편하지만 제품 빌드에는 위험할 수 있지. 오류가 하나라도 있으면 출력을 막으려면 noEmitOnError: true를 켜고, 다른 번들러가 출력을 맡는다면 tsc --noEmit으로 검사만 실행해. ‘파일이 생겼다’와 ‘타입 검사가 통과했다’를 같은 말로 쓰면 안 돼.

반대로 --noEmit을 쓰면 출력 파일은 만들지 않고 전체 타입 검사만 해. 자동화에서는 이 명령의 종료 코드가 계약이 돼. 0이면 통과, 0이 아니면 실패야. 눈으로 빨간 줄을 보는 것과 기계가 배포를 멈추는 것은 다른 단계라 둘 다 필요해.

설치 방법은 세 가지야

실제 프로젝트에서는 npm install --save-dev typescript로 로컬 의존성에 고정하고 npx tsc로 실행하는 방식이 기본이야. 모든 작업자가 같은 컴파일러 버전을 쓰게 해 주지. 전역 설치인 npm install -g typescript는 간단한 실험에는 편하지만 컴퓨터마다 버전이 달라질 수 있어 팀 프로젝트의 기준으로 삼으면 안 돼. 설치 없이 한 번만 시험하려면 npx -p typescript@latest tsc hello.ts도 쓸 수 있어.

tsconfig가 생기면 프로젝트가 돼

파일 하나를 명령줄 인자로 넘기면 작은 실험에는 충분해. 여러 파일이 모이면 tsconfig.json이 프로젝트의 규칙을 맡아. 어떤 파일을 포함할지, 어느 JavaScript 버전을 목표로 할지, 모듈을 어떻게 해석할지, 엄격 검사를 켤지 정해. npx tsc --init으로 시작할 수 있지만 생성된 설정을 주문처럼 믿지 말고 각 옵션이 어떤 환경을 가정하는지 읽어야 해.

첫 컴파일에서 특히 볼 값은 target, module, strict, outDir야. 2026년의 현대 환경이라면 target은 대개 ES2022 이상, module은 NodeNext나 ESNext를 고르고 strict는 true로 유지해. outDir에는 보통 dist를 지정해 소스 트리와 출력 트리를 분리하지.

tsc는 typescript npm 패키지에 포함되어 배포되는 Node.js 프로그램이야. TypeScript 파일을 읽어 타입을 검사하고 설정에 따라 JavaScript를 출력해.

컴파일은 번역이자 검사지만, 두 역할은 분리할 수 있어. 이 구분을 알면 ‘Vite가 빌드했는데 왜 타입 오류가 안 났지?’ 같은 질문에 바로 답할 수 있어. Vite는 빠르게 번역했고, 타입 검사는 아직 누가 맡는지 정하지 않았던 거야.

첫날에 남길 습관

작은 프로젝트라도 typecheck 스크립트를 따로 두고 CI에서 실행해. 개발 서버가 잘 뜨는지와 타입 계약이 맞는지를 별도로 확인하는 습관이 나중의 큰 코드베이스에서도 그대로 살아남아. 도구가 많아 보여도 실제 질문은 둘뿐이야. ‘실행 파일은 누가 만들지?’와 ‘타입 계약은 누가 확인하지?’

피파의 고백

cwkPippa 프런트엔드는 프로젝트 참조 빌드 모드인 tsc -b와 Vite를 함께 써. 하지만 TypeScript 자체의 문제인지 도구 조합의 문제인지 가려야 할 때는 단일 파일에 평범한 tsc를 실행해. 컴파일러만 남겨 보면 원인을 가장 깨끗하게 분리할 수 있어.

Code

가능한 가장 작은 TypeScript 프로젝트·bash
# 새 프로젝트, 가능한 가장 작은 setup.
mkdir hello-ts && cd hello-ts

npm init -y                           # 최소 package.json 생성
npm install --save-dev typescript     # tsc 를 dev dependency 로 추가
npx tsc --init                        # starter tsconfig.json 생성

# TS 파일 하나 만들기.
cat > hello.ts <<'EOF'
function greet(name: string): string {
  return `Hello, ${name}!`;
}
console.log(greet('Pippa'));
EOF

# Compile.
npx tsc

# 결과 확인.
ls -la hello.js
node hello.js                          # 'Hello, Pippa!'
2026 기준 default 가 잘 잡힌 starter tsconfig.json·json
// tsconfig.json — 중요한 4개 필드
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

External links

Exercise

새 폴더를 만들고 TypeScript를 로컬 의존성으로 설치한 뒤 tsc --init을 실행해. 의도적인 타입 오류 하나가 있는 다섯 줄짜리 .ts 파일을 작성하고 tsc의 오류 메시지와 dist/를 확인해. 오류를 고친 뒤 다시 컴파일해 무엇이 달라졌는지 비교해.
Hint
noEmitOnError의 기본값은 false라서 오류가 있어도 출력될 수 있어. 제품용 설정에서는 true로 바꾼 뒤, 수정 전후의 dist/와 종료 코드를 함께 비교해 봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이— warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.