.ts 하나 돌려보려고 ts-node·nodemon·tsconfig 세팅부터 하는 게 번거로웠던 적 있을 겁니다. Node 24에선 그냥 node app.ts로 되는데, 모르면 안 써도 될 의존성을 계속 얹고, 무턱대고 걷어내면 enum에서 에러가 터집니다.
Node로 스크립트·백엔드를 다뤄온 관점에서 공식 문서를 직접 확인해 되는 것과 안 되는 것을 갈랐습니다. 이 순서대로 가면 ts-node를 걷어낼지, 어디까지 걷어낼지 판단이 섭니다.

빌드 없이 .ts가 실행되나 — 되는 것부터
됩니다. Node 24는 .ts 파일을 그대로 받습니다.
node app.ts
--experimental-strip-types 플래그는 필요 없습니다. 이 타입 스트리핑은 v23.6부터 기본으로 켜져 있고, v24에서 Stable로 승격됐습니다. 끄고 싶을 때만 --no-strip-types를 붙입니다.
원리는 단순합니다. Node는 타입스크립트를 컴파일하지 않고, 타입 부분만 같은 길이의 공백으로 치환해서 실행합니다. let x: number = 1이 실행 시점엔 let x = 1이 되는 식이죠. 삭제가 아니라 공백 치환이라 소스맵도 어긋나지 않습니다.
그래서 Node.js 24 TypeScript 실행은 "타입을 지우고 JS로 돌린다"에 가깝지, "TS를 빌드한다"가 아닙니다. 이 차이가 뒤에 나오는 "안 되는 것"의 원인 전부입니다.
되는 것 — 실행 세팅과 권장 tsconfig
Node.js 24 TypeScript 실행에 세팅이랄 게 거의 없습니다. Node 24만 있으면 됩니다.

한 가지 규칙은 있습니다. 상대 경로 import에 확장자를 반드시 붙여야 합니다.
// app.ts
import { sum } from './math.ts'; // ✅ .ts 확장자 필수
// import { sum } from './math'; // ❌ ERR_MODULE_NOT_FOUND
에디터 쪽 타입 정합을 위해 tsconfig는 아래 정도만 잡아두면 됩니다. TS 5.8+ 기준입니다.
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"rewriteRelativeImportExtensions": true,
"erasableSyntaxOnly": true,
"verbatimModuleSyntax": true,
"noEmit": true
}
}
erasableSyntaxOnly가 특히 유용합니다. enum처럼 스트리핑으로 지울 수 없는 문법을 tsc가 미리 에러로 잡아줘서, 실행 단계에서 터지기 전에 IDE에서 걸립니다. rewriteRelativeImportExtensions는 .ts로 쓴 import를 빌드 시 .js로 바꿔줘서, 나중에 tsc로 빌드하는 경로와 충돌하지 않게 합니다.
안 되는 것 — enum·데코레이터·타입 체크
핵심은 이 표 하나입니다. "런타임 코드를 만들어야 하는 문법"은 공백 치환으로 못 지우니 기본값에서 막힙니다.
| 문법/기능 | 스트리핑만(기본) | transform-types(Node 24) | 비고 |
|---|---|---|---|
| 타입 애노테이션·interface·type | ✅ | ✅ | 공백 치환 |
| import type / type-only namespace | ✅ | ✅ | type 키워드 필수 |
| enum | ❌ | ✅ | 런타임 객체 생성 |
| 런타임 namespace | ❌ | ✅ | 값 export |
| parameter properties(생성자) | ❌ | ✅ | 코드 생성 |
| 데코레이터 | ❌ | ❌ | 플래그로도 안 됨 |
| tsconfig paths | ❌ | ❌ | subpath(#) 우회 |
| 타입 검사 | ❌ | ❌ | tsc --noEmit 별도 |
| .tsx | ❌ | ❌ | 미지원 |
증상: enum Color { Red }를 쓴 파일에서 ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX
원인: enum은 실행 시 실제 객체를 만들어야 하는데, 스트리핑은 코드를 생성하지 않고 지우기만 합니다.
해결: enum을 as const 객체나 유니온 타입으로 바꾸거나, Node 24 한정으로 --experimental-transform-types를 붙입니다.
enum·런타임 namespace·parameter properties는 --experimental-transform-types를 붙이면 Node 24에선 실제로 동작합니다. 다만 이 플래그는 v26에서 제거 예정이라, 걸어두고 잊으면 나중에 그대로 깨집니다. 실측으로도 한 번 데였습니다. ts-node를 걷어낸 뒤 enum이 남은 스크립트에서 ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX를 만나, 급한 건 transform-types로 막고 나머지는 enum을 걷어내는 쪽으로 정리했습니다. 오래 갈 코드라면 enum 자체를 지양하는 게 정석입니다.
데코레이터는 결이 다릅니다. transform-types를 붙여도 안 됩니다. 스트리핑 대상이 아니라 파서 단계에서 걸리는 문제라, 데코레이터를 쓰는 NestJS류 코드는 지금도 빌드가 필요합니다.
타입 검사는 아예 안 합니다. node app.ts는 타입이 틀려도 그냥 돌립니다. 그래서 검사는 분리합니다. 상세는 yarn vs npm vs pnpm 비교에서 다룬 도구 선택과 같은 맥락으로, 실행과 검증을 각자 잘하는 도구에 맡기는 편이 낫습니다.
tsc --noEmit
tsconfig paths(@/utils 같은 별칭)도 무시됩니다. Node는 tsconfig를 안 읽기 때문입니다. 별칭이 필요하면 package.json의 subpath imports(# 프리픽스)로 대체합니다.
실전 — 개발 vs 프로덕션, ts-node 걷어낼까
Node.js 24 TypeScript로 개발 스크립트, 마이그레이션, 일회성 작업은 node app.ts로 거의 다 대체됩니다. ts-node·nodemon을 깔던 자리를 이걸로 비웁니다. 파일 변경 감지도 node --watch app.ts로 됩니다.
실행은 node로, 타입 안전은 tsc로 분리하는 게 낫습니다. node는 빠르게 돌리고, tsc --noEmit는 커밋 훅이나 CI에서 한 번 돌려 타입을 막습니다. 한 도구가 둘 다 하려다 느려지는 것보다 이 조합이 깔끔합니다.
프로덕션은 조건부입니다. 배포 산출물이 필요하거나, 구형 런타임으로 다운레벨해야 하거나, 데코레이터·타입 안전이 필수면 여전히 tsc나 tsup으로 빌드하는 게 맞습니다. transform-types는 v26에서 사라질 실험 기능이라 프로덕션에 걸어두기엔 부담이 있습니다. 반대로 서버에서 그냥 실행 스크립트 하나 돌리는 정도면 node app.ts로 충분합니다.
정리하면 이렇게 갈립니다. 실행만 하면 node, 산출물·타입 안전이 필요하면 빌드. 프론트엔드 번들이 함께 있으면 어차피 번들러가 TS를 처리하니 이 논의 바깥입니다.
Q&A — 자주 보는 질문 5개
Q. .ts 실행에 플래그가 필요한가요?
A. 아니요. Node 24는 타입 스트리핑이 기본으로 켜져 있어 node app.ts만으로 됩니다. 끄고 싶을 때만 --no-strip-types를 붙입니다.
Q. 이제 ts-node·tsx는 필요 없나요?
A. 대부분의 실행 시나리오는 대체됩니다. 단 tsconfig paths, 데코레이터, 완전한 타입 검사가 필요하면 여전히 이 도구들이나 빌드가 필요합니다.
Q. enum에서 에러가 나는데 어떻게 살리나요?
A. enum은 런타임 객체를 만들어야 해서 스트리핑으로 못 지웁니다. Node 24 한정으로 --experimental-transform-types를 붙이면 동작하지만, 이 플래그는 v26에서 제거 예정이라 as const 객체나 유니온 타입으로 바꾸는 편이 안전합니다.
Q. node app.ts가 타입 오류도 잡아주나요?
A. 아니요. 타입을 지우고 실행할 뿐 검사는 하지 않습니다. 타입 검사는 tsc --noEmit을 커밋 훅이나 CI에서 따로 돌려야 합니다.
Q. 프로덕션도 node app.ts로 배포해도 되나요?
A. 실행 스크립트 정도면 괜찮습니다. 다만 배포 산출물이 필요하거나 구형 런타임 다운레벨·데코레이터·타입 안전이 필요하면 tsc나 tsup으로 빌드하는 게 낫습니다.
같은 환경이면 위 순서대로 따라가도 무리 없습니다.
설치 환경: Node.js 24 LTS, TypeScript 5.8
'Backend > NodeJS' 카테고리의 다른 글
| [Node.js] Winston 사용하여 로깅하기 (1) | 2024.09.27 |
|---|---|
| Node.js, Express를 사용하여 간단한 웹 크롤러 만들기 (0) | 2023.11.30 |
| NVM 설치 및 사용 방법 (0) | 2022.11.13 |
| node-gyp 설치 오류 해결 방법 (0) | 2022.10.22 |
| npm install 시 gyp ERR! 해결 방법 (1) | 2022.10.18 |
IT 기술과 개발 내용을 포스팅하는 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!