
Node.js, 이제 TypeScript를 기본 지원한다!
Node.js가 v23.6.0부터 TypeScript를 별도의 플래그 없이 실행할 수 있도록 지원하는데요.
이 글에서는 새로운 기능이 어떻게 동작하는지, 그리고 주의해야 할 점들을 살펴보겠습니다.
새로운 기능, 직접 확인해볼까요?
다음과 같은 TypeScript 파일이 있다고 가정해봅시다.
// demo.mts
function main(message: string): void {
console.log('Message: ' + message);
}
main('Hello!');
이제 이 파일을 바로 실행할 수 있습니다.
node demo.mts
하지만 현재는 다음과 같은 경고가 표시되는데요.
ExperimentalWarning: Type Stripping is an experimental feature and might change at any time
이 경고를 비활성화하려면 다음과 같이 실행하면 됩니다.
node --disable-warning=ExperimentalWarning demo.mts
--disable-warning 사용 팁
- 환경 변수
NODE_OPTIONS를 설정하면 매번 입력하지 않아도 됩니다. .env파일을 활용하면 환경 변수를 영구적으로 설정할 수도 있습니다.
파일 확장자는 어떻게 사용해야 할까요?
TypeScript 파일 확장자는 Node.js에서 다음과 같이 동작합니다.
| 확장자 | 설명 |
|---|---|
| .ts | .js 파일과 동일하게, ESM 또는 CommonJS 가능 |
| .mts | 항상 ESM으로 동작 (독립 실행 파일에 적합) |
| .cts | 항상 CommonJS로 동작 |
| .tsx | 지원되지 않음 (JSX 불가) |
Node.js TypeScript vs 일반 TypeScript
JavaScript가 아닌 기능은 지원되지 않습니다
enumnamespace- 클래스 생성자의 매개변수 속성(parameter properties)
JSX는 지원되지 않습니다
.tsx파일과 JSX 문법은 사용할 수 없습니다.
최신 JavaScript 기능을 변환하지 않습니다
TypeScript는 최신 JavaScript 기능을 변환(transpile)해주는 역할도 하는데요.
예를 들어, 데코레이터(Decorators) 같은 기능은 TypeScript에서는 지원하지만,
Node.js 자체에서 JavaScript로 변환하지 않기 때문에 사용할 수 없습니다.
(단, JavaScript에서 공식 지원되면 Node.js에서도 지원될 예정입니다.)
로컬 모듈을 불러올 때 주의할 점
기존 TypeScript에서는 transpile된 .js 파일을 import하는 것이 일반적이었습니다.
import { myFunction } from './my-module.js';
하지만 Node.js는 파일 확장자를 기준으로 모듈 타입을 결정하기 때문에,
이제는 .ts 확장자를 직접 명시해야 합니다.
import { myFunction } from './my-module.ts';
개인적으로도 이 방식이 더 직관적이라고 생각하는데요.
tsconfig.json 설정을 통해 프로젝트 전체적으로 적용할 수도 있습니다.
타입을 import할 때는 type을 사용해야 합니다
Node.js는 TypeScript 코드를 변환할 때 타입 관련 문법만 제거하는데요.
이 과정에서 타입을 일반 import로 가져오면 제거되지 않을 수 있습니다.
// 올바른 타입 import
import type { Cat, Dog } from './animal.ts';
// 인라인 타입 import
import { createCatName, type Cat, type Dog } from './animal.ts';
tsconfig.json 설정
Node.js의 타입 제거(type stripping)는 tsconfig.json을 무시하지만,
개발 중에 타입 검사를 수행하려면 tsconfig.json이 필요합니다.
Node.js 공식 문서에서 추천하는 최소 설정은 다음과 같습니다.
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"allowImportingTsExtensions": true,
"rewriteRelativeImportExtensions": true,
"verbatimModuleSyntax": true
}
}
주요 설정 살펴보기
1️⃣ allowImportingTsExtensions (TypeScript 5.0 이상)
→ .ts 파일을 직접 import할 수 있도록 허용합니다.
2️⃣ rewriteRelativeImportExtensions (TypeScript 5.7 이상)
→ .ts 파일을 .js로 변환(transpile)할 때, import 문도 .js로 변경합니다.
3️⃣ verbatimModuleSyntax (TypeScript 5.0 이상)
→ 타입을 import할 때 type 키워드를 사용하지 않으면 경고를 표시합니다.
--input-type 옵션
파일이 아닌 입력(예: stdin 또는 --eval)을 처리할 때,
Node.js가 코드를 해석하는 방식을 지정할 수 있습니다.
node --input-type=module-typescript
지원되는 옵션은 다음과 같습니다.
| 옵션 | 설명 |
|---|---|
module |
ESM(JavaScript) |
commonjs |
CommonJS(JavaScript) |
module-typescript |
ESM(TypeScript) |
commonjs-typescript |
CommonJS(TypeScript) |
타입 제거(Type Stripping)와 Source Map
Node.js의 타입 제거 기능은 "타입 부분을 공백으로 덮어씌우는 방식"을 사용합니다.
이 방식 덕분에 소스 코드의 줄 번호가 그대로 유지되므로,
디버깅할 때 stack trace가 깨지지 않습니다.
예제: TypeScript → JavaScript 변환
입력 (TypeScript)
function describeColor(color: Color): string {
return `Color named “${color.colorName}”`;
}
type Color = { colorName: string };
describeColor({ colorName: 'green' });
출력 (JavaScript)
function describeColor(color ) {
return `Color named “${color.colorName}”`;
}
describeColor({ colorName: 'green' });
보시다시피 타입 부분이 공백으로 유지되면서 코드 위치가 그대로 보존됩니다.
앞으로의 변화는?
TypeScript 5.8에서는 미지원 기능을 감지할 수 있음
Jake Bailey (Microsoft TypeScript 팀 개발자)의 말:
"Node.js에서 실행할 TypeScript 코드에서
enum,namespace,decorators같은
런타임 변환이 필요한 기능을 감지하고 경고하는 플래그가 추가될 예정입니다."
--experimental-transform-types
Node.js에서 TypeScript를 실제로 변환(transpile)하도록 만드는 실험적인 기능입니다.
이 기능이 활성화되면 기존보다 더 많은 TypeScript 기능을 지원하고,
source map도 자동으로 생성됩니다.
몇 가지 개인적인 생각
.ts,.tsx,.mts,.cts같은 다양한 확장자가 너무 많다는 느낌이 있는데요.
하지만 Node.js와 TypeScript를 함께 쓰려면 필요한 구분이긴 합니다.- 타입 제거(Type Stripping) 방식이 향후 브라우저에서도 적용될 가능성이 있을까요?
즉, JavaScript의 문법 확장은 지원하지 않고, 타입 제거만 지원하는 방향으로요.
마무리하며
이제 Node.js에서 TypeScript를 별다른 설정 없이 바로 실행할 수 있게 되었는데요.
아직 실험적인 기능이긴 하지만, 앞으로의 발전이 기대됩니다.
개발 환경에 맞춰 적절히 활용해보는 것도 좋을 것 같습니다.
'Javascript' 카테고리의 다른 글
| pnpm 10 주요 변경 사항 정리 (0) | 2025.01.13 |
|---|---|
| ECMAScript 2025에 포함될 Import Attributes, 무엇이 달라질까? (0) | 2025.01.13 |
| Node.js에서 AsyncLocalStorage로 비동기 컨텍스트 관리 간소화하기 (0) | 2025.01.08 |
| 자바스크립트 WeakRef 완벽 가이드: 메모리 관리를 쉽게 이해해볼까요? (0) | 2025.01.08 |
| JavaScript Truthy와 Falsy 완벽 정리: 헷갈리는 타입 변환, 이제 끝내자! (0) | 2025.01.08 |