코딩 에러 모음

TypeError: Unknown file extension ".ts" for ~(feat. commonJS, ESM)

문앵 2025. 3. 10. 18:26

ts 파일을 간단하게 실행 시킬 수 있는 인터프리터 환경인 ts-node를 사용하는 과정에서 겪은 에러다.

 

원래 ts는 js 로 컴파일 과정을 거치고 실행을 해야되는데

 

ts-node 를 쓰면 노드 환경에서 그냥 바로 ts 를 실행시킬 수 있다.

 

npx ts-node example.ts

 

난 그대로 따라했는데 에러가 났다.

TypeError: Unknown file extension ".ts" for 어쩌구

 

신기하게도 동일한 에러가 난 사람이 디코방에 질문을 올린게 있었다.

이 답변에 달린내용을 제대로 이해해보고자 기록을 남겨두려한다.

 

 

 


 

 

1. commonJS / ESM

js는 원래 브라우저 내에서 사용하던 언어인데, 그걸 브라우저가 아닌 다른 공간에서도 사용하고자 생긴 모듈 시스템 중 하나가 commonJS 이다. 초기 node.js에서는 commonJS 모듈을 채택했다.

 

ESM은 ES(ECMAScript, javascript 표준 사양) Module 이다.

두개의 가장 큰 차이점은 비동기 유무인데, ESM이 비동기 방식이다. 

그래서 브라우저에서 직접 ESM 을 지원한다. 네트워크 요청을 할때 빠르게 모듈만 비동기로 사용할 수 있도록 해준다.

 

따라서 시간이 지나면서 자연스레 node.js 도 특정 버전 이후부터는 ESM도 지원하게 되었다.

그러나 기본 컴파일 모듈은 commonJS 방식을 따른다.

 

2. node 와 ts-node의 상관관계

node는 기본적으로 commonJS 모듈로 컴파일된다.

ts-node는 원래 CommonJS 모듈 시스템을 사용하는 Node.js 환경에 맞춰져 있었으나, node가 ESM을 지원하게 되면서, ts-node 또한 특정 버전 이후부터는 ESM 방식으로 컴파일을 하게 되었다. <- 여기서 문제가 생기는 것이다.

 

3. ts-node 의 설정

내가 이때는 tsconfig.json 파일을 생성해주지 않았었다.

왜냐면 애초에 ts-node 자체가 tsc 없이 바로 노드에서 실행시킬 수 있는 인터프리터 환경이기 때문에, 그 편의성을 누려야 한다고 생각해서(?)였다.

 

ts-node는 따로 컴파일 옵션을 지정해줄 수 있는데 tsconfig.json 파일이 있으면 여기있는 설정을 따른다.

결국 나는 tsc 를 설치하고 기본 설정 파일을 생성해주었다..

 

그리고 바로 실행해보았다.

 

아주 잘 실행되었다..

여기서 해당 설정 부분은 

{
  "compilerOptions": {
  	"module": "commonjs",
    }
}

 

이 부분이다. 

 

이부분은 설정을 지워도 에러 없이 동작하는데, tsconfig.json의 기본 설정이 "module" : "commonJS" 여서 이 부분을 "ESNex" (ESM 방식으로 컴파일) 로 설정해 주지 않는 이상 commonJS 로 컴파일하도록 인식하기 때문인것 같다.

 

 

4. ESM 방식으로 실행

그렇다면 node.js 의 기본 설정 자체를 ESM 으로 바꾸면 어떻게 될까? 

ts-node의 실행 방식을 ESM으로 바꾸고 ts-node 의 컴파일 방식도 ESM 을 적용할시에도 문제없이 돌아갈까?

 

또 다른 추가 설정을 해줘야 했지만 결론은 O 였다.

 

node.js의 ESM 설정 > 

 

// package.json

{
...
	"type" : "module",
...
}

 

 

ts-node 의 ESM 설정 > 

여기서 헷갈렸던게 "ts-node는 따로 설정해주지 않아도 ESM 으로 돌아가지않나?" 라고 생각했으나 (애초에 그래서 node와 호환성 문제가 생겼던거니까),

막상 그냥 실행해보니 이번에는 또 다른 에러 (Must use import to load ES Module : commonJS 방식으로 작성된 파일을 ES 방식으로 읽으려다보니 규칙이 충돌하는 부분이 있음)가 생겨서.. 결국 tsconfig.json파일을 수정하여 또 다른 설정을 해줘야 했다.

 

// tsconfig.json

{
module : "NodeNext", // moduleResolution에 따라 맞춰줌
moduleResolution : "nodenext" // cjs 파일과 mjs 파일의 충돌을 없애주는 설정
}

 

 

// 실행시

node --loader ts-node/esm [파일명]

 

실행시에도 로더를 지정해줘야 했다.

commonJS 방식에서는 노드가 알아서 이해하기 때문에 ts-node가 알아서 ts -> js 로 변환해서 읽었지만 ,

ESM 방식에서는 node가 ts 파일을 읽으려면 로더를 지정해줘야 하기 때문이다.

 

 

위 세개의 설정을 각각 해주면 ESM 방식으로 ts 파일을 실행할 수 있었다.

 

commonJS와 esm 의 차이를 깊이있게 알지 못했는데 에러가 왜 났는지 살펴보면서 좀 더 근본적인 원인을 알게 된 것 같아서 좋은 경험이었따.

 

 

반응형