Menu

TypeScript 파일 실행 방법: tsc, Node.js, tsx, ts-node

.ts 파일을 실행하는 다섯 가지 방법: tsc로 컴파일해서 JavaScript를 실행하기, node file.ts로 바로 실행하기(타입 제거), tsx나 ts-node 쓰기, Deno와 Bun 쓰기. 어느 것이 타입을 검사하는지, 각각 어떤 문법을 지원하는지, 무엇을 고를지 알아봅니다.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

TypeScript 파일은 그대로는 실행할 수 없습니다. 브라우저와 JavaScript 엔진이 타입 표기를 이해하지 못하기 때문입니다. 먼저 무언가가 타입을 제거해야 합니다. 그 무언가는 타입 검사도 함께 하는 TypeScript 컴파일러(tsc)이거나, 타입을 지우기만 하는 더 빠른 도구입니다. 이 페이지의 코드를 가장 빨리 실행하는 방법은 Run 버튼입니다.

출력:

[x] Install TypeScript
[ ] Run a .ts file

이 문서의 실행 가능한 블록은 모두 같은 방식으로 동작합니다. 코드는 strict가 켜진 TypeScript 7로 타입 검사를 받고, 타입 오류가 없을 때만 실행됩니다. 더 긴 실험에는 같은 에디터를 독립된 페이지로 제공하는 TypeScript 플레이그라운드를 쓰세요. 이 페이지의 나머지는 내 컴퓨터에서 .ts 파일을 실행하는 방법을 다룹니다.

방법 한눈에 보기

명령타입 검사빌드 단계 필요enum, namespace, 매개변수 속성 지원
npx tsc 후 node dist/index.js예예예
node index.ts (Node.js 22.18+, 23.6+)아니요아니요아니요
npx tsx index.ts아니요아니요예
npx ts-node index.ts예아니요예, 단 TypeScript 7에서는 안 됨
deno run index.ts아니요(deno check가 검사)아니요예
bun index.ts아니요아니요예

사람들이 놀라는 것은 첫 번째 열입니다. 빠른 방법 대부분은 타입 오류가 있는 코드도 실행합니다. 일반적인 프로젝트는 이 중 하나로 코드를 실행하고, 오류를 잡기 위해 에디터와 CI에서 따로 tsc --noEmit을 실행합니다.

tsc로 컴파일한 뒤 Node로 실행하기

어디서든 동작하고 모든 것을 검사하는 방법입니다. 프로젝트에 TypeScript가 설치되어 있고 tsconfig.json에 "rootDir": "./src"와 "outDir": "./dist"가 설정되어 있다면:

npx tsc
node dist/index.js

tsc는 모든 파일을 타입 검사한 다음 dist에 .js 파일을 씁니다. 프로젝트 없이 파일 하나만 컴파일하려면 파일 이름을 넘기세요. 그러면 기본 옵션을 쓰고 index.ts 옆에 index.js를 씁니다.

npx tsc index.ts
node index.js

(폴더에 tsconfig.json이 있으면 tsc는 error TS5112를 내며 파일 이름을 거부합니다. 그냥 npx tsc를 실행하거나 --ignoreConfig를 더하세요.)

기본적으로 tsc는 타입 오류가 있어도 JavaScript를 쓰므로, 검사에 실패한 프로그램을 node가 실행할 수 있습니다. 이를 막으려면 설정에 "noEmitOnError": true를 더하거나, 첫 단계가 성공했을 때만 두 번째 단계가 실행되도록 스크립트에서 명령을 이어 붙이세요.

{
    "scripts": {
        "build": "tsc",
        "start": "tsc && node dist/index.js"
    }
}

개발 중에는 npx tsc --watch가 저장할 때마다 다시 컴파일합니다.

Node.js로 TypeScript 바로 실행하기

최신 Node.js는 .ts 파일을 직접 실행합니다.

node index.ts

Node는 타입 표기를 공백으로 바꿔서 제거하고(그래서 스택 트레이스의 줄 번호가 그대로 맞습니다) 남은 코드를 실행합니다. Node.js 23.6.0과 22.18.0부터 기본으로 켜져 있고, 24.3.0과 22.18.0부터는 경고를 출력하지 않으며, Node.js 24.12.0과 25.2.0에서 안정 기능이 되었습니다. 이 기능이 있는 이전 릴리스(22.6부터 22.17, 23.0부터 23.5)에서는 플래그가 필요합니다: node --experimental-strip-types index.ts.

여기에는 네 가지 규칙이 따릅니다.

  • 타입 검사가 없습니다. const age: number = "forty"가 있는 파일도 실행되어 forty를 출력합니다.
  • 지울 수 있는 문법만 됩니다. 사라지는 대신 JavaScript 코드가 되어야 하는 것은 모두 거부됩니다. enum, 런타임 코드가 있는 namespace 블록, constructor(private name: string) 같은 생성자 매개변수 속성, import x = require() 별칭이 그렇습니다. Node는 SyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript enum is not supported in strip-only mode를 내며 멈춥니다.
  • tsconfig.json은 무시됩니다. paths나 target 같은 옵션은 효과가 없습니다.
  • import에는 실제 파일 이름이 필요합니다. 확장자까지 붙여 import { add } from "./math.ts"라고 쓰고, 타입 전용 import에는 type을 표시하세요: import { add, type Pair } from "./math.ts". type이 없으면 Node는 Pair라는 런타임 export를 찾다가 SyntaxError: The requested module './math.ts' does not provide an export named 'Pair'로 실패합니다.

두 가지 컴파일러 옵션을 쓰면 tsc가 같은 규칙을 강제하므로, Node보다 먼저 에디터가 경고해 줍니다. "erasableSyntaxOnly": true는 enum에 error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.를 보고하고, "verbatimModuleSyntax": true는 타입 전용 import에 type 키워드를 요구합니다. import에 .ts 확장자를 계속 쓰면서 tsc로도 컴파일하려면 "rewriteRelativeImportExtensions": true를 더하세요. 출력에서 ./math.ts를 ./math.js로 바꿔 줍니다.

Node.js 24에는 enum과 매개변수 속성을 거부하는 대신 코드를 생성하는 --experimental-transform-types도 있습니다. 하지만 ExperimentalWarning을 출력하고 Node.js 26에서 이 플래그가 제거되었으므로 이것에 기대지 마세요.

이 블록은 node index.ts가 거부하는 기능 두 가지를 씁니다. 여기서 실행되는 것은 에디터가 TypeScript 컴파일러로 컴파일하고, 컴파일러가 둘 다 JavaScript로 생성하기 때문입니다.

같은 코드를 지울 수 있는 문법으로 쓰면 const 객체와 일반 필드를 쓰게 되고, Node가 그대로 실행할 수 있습니다.

tsx

tsx는 설정 없이, 문법 제약 없이 TypeScript 파일을 한 단계로 실행합니다.

npm install --save-dev tsx
npx tsx index.ts
npx tsx watch index.ts   # rerun on every change

esbuild로 코드를 변환하므로 enum, namespace, 매개변수 속성이 동작하고, 확장자 없는 import도 번들러에서처럼 해석됩니다. Node의 타입 제거처럼 타입 검사는 하지 않습니다. 타입 제거 기능이 없는 이전 Node.js 버전이나 Node가 거부하는 문법을 쓰는 코드에서 스크립트, 개발 서버, 테스트를 돌릴 때 흔히 선택합니다.

ts-node

ts-node는 수년간 Node.js에서 TypeScript를 실행하는 표준 방법이었고, 많은 튜토리얼과 오래된 프로젝트가 여전히 씁니다(npx ts-node index.ts, node -r ts-node/register). 기본적으로 TypeScript 컴파일러의 JavaScript API로 타입을 검사합니다.

바로 그 API가 TypeScript 7에는 없습니다. 컴파일러가 네이티브 프로그램이 되었고, typescript 7 패키지는 JavaScript에 컴파일러 API를 제공하지 않습니다. TypeScript 7이 설치되어 있으면 ts-node는 아무것도 실행하기 전에 멈춥니다.

TypeError: Cannot read properties of undefined (reading 'fileExists')
    at readConfig (/project/node_modules/ts-node/dist/configuration.js:91:33)

ts-node의 최신 릴리스 10.9.2는 2023년 12월에 나왔습니다. 새 코드에는 tsx나 node index.ts를 쓰세요. ts-node에 의존하는 기존 구성은 프로젝트가 TypeScript 6에 머물고(npm install --save-dev typescript@6) tsconfig.json이 있다면(빈 {}라도) 계속 동작합니다. 설정 파일이 없으면 ts-node는 TypeScript 6이 폐기한 node10 모듈 해석이 포함된 내장 기본값을 쓰고, npx ts-node index.ts는 파일을 실행하지도 오류를 출력하지도 않고 종료합니다.

Deno와 Bun

두 런타임 모두 TypeScript를 정식 파일 형식으로 다룹니다.

deno run index.ts    # runs without checking
deno check index.ts  # type-checks, reports errors, runs nothing

bun index.ts         # runs without checking

둘 다 typescript 설치나 tsconfig.json이 필요 없고, enum 같은 지울 수 없는 기능도 지원합니다. Deno는 deno check를 위해 TypeScript 컴파일러의 복사본을 내장합니다. Bun은 타입만 제거하므로, Bun 프로젝트에서도 타입 오류를 찾으려면 typescript를 설치하고 tsc --noEmit을 실행합니다.

타입 오류로 프로그램이 멈추는 것은 tsc뿐

타입 오류가 있는 프로그램의 실행을 거부하는 것은 먼저 tsc를 실행하는 경로뿐입니다. 이 페이지의 에디터가 그중 하나이므로, 이 블록은 컴파일러에서 멈춥니다.

index.ts(6,21): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

같은 코드를 파일로 저장해 node index.ts, npx tsx index.ts, bun index.ts로 실행하면 3 * "4"가 문자열을 변환하므로 코드가 실행되어 12를 출력합니다. 더 빠른 도구로 코드를 실행하더라도 tsc --noEmit을 작업 흐름에 두어야 하는 이유입니다.

{
    "scripts": {
        "dev": "tsx watch src/index.ts",
        "typecheck": "tsc --noEmit"
    }
}

무엇을 써야 할까?

  • 학습이나 빠른 테스트: 이 페이지의 Run 버튼이나 플레이그라운드.
  • 최신 Node.js에서 도는 스크립트나 작은 도구: node index.ts. 설정에 erasableSyntaxOnly를 넣어 Node가 거부할 코드를 에디터가 표시하게 하세요.
  • 어떤 Node.js 프로젝트든, 어떤 문법이든: 실행은 tsx, 검사는 tsc --noEmit.
  • 라이브러리나 배포하는 모든 것: tsc. 사용자에게 필요한 .d.ts 파일도 써 주기 때문입니다.
  • 프론트엔드 코드: 번들러나 프레임워크(Vite, Next.js, Angular CLI)가 TypeScript를 대신 실행해 줍니다. 검사를 위해 tsc --noEmit을 더하세요.

자주 묻는 질문

TypeScript 파일은 어떻게 실행하나요?

전통적인 방법은 두 단계입니다. npx tsc로 .ts를 .js로 컴파일한 다음 node dist/index.js로 출력을 실행합니다. Node.js 22.18 또는 23.6 이상에서는 파일이 지울 수 있는 타입 문법만 쓴다면 node index.ts로 바로 실행할 수도 있습니다. npx tsx index.ts는 어떤 TypeScript 파일이든 한 단계로 실행합니다.

Node.js에서 TypeScript를 바로 실행할 수 있나요?

네. Node.js 23.6과 22.18부터 플래그 없이 node file.ts가 동작합니다. Node가 타입 표기를 제거하고 나머지를 실행합니다. 타입 검사는 하지 않고, tsconfig.json을 무시하며, enum, 런타임 코드가 있는 namespace, 생성자 매개변수 속성처럼 코드 생성이 필요한 문법은 거부합니다.

ts-node는 TypeScript 7에서 동작하나요?

아니요. ts-node는 컴파일러의 JavaScript API를 호출하는데, typescript 7 패키지는 그 API를 제공하지 않으므로 시작하자마자 멈춥니다(Cannot read properties of undefined (reading 'fileExists')). 마지막 릴리스는 2023년 12월의 10.9.2입니다. tsx나 Node 자체의 타입 제거를 쓰거나, ts-node를 TypeScript 6과 함께 계속 쓰세요.

tsx와 ts-node의 차이는 무엇인가요?

tsx는 (esbuild로) 타입만 제거하고 결과를 실행하므로 빠르게 시작하지만 타입 오류를 절대 보고하지 않습니다. ts-node는 기본적으로 TypeScript 컴파일러로 타입을 검사하므로 더 느리고 컴파일러의 JavaScript API에 묶여 있습니다. 요즘 대부분의 프로젝트는 실행에는 tsx나 node file.ts를, 검사에는 tsc --noEmit을 함께 씁니다.

온라인 TypeScript 샌드박스가 있나요?

네. 이 문서 페이지의 코드 블록과 Coddy의 TypeScript 플레이그라운드는 코드를 TypeScript 7로 컴파일해서 실행하고, 컴파일러 오류나 프로그램 출력을 보여 줍니다. typescriptlang.org의 공식 TypeScript Playground는 생성된 JavaScript와 오류를 보여 줍니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기