Mark Juyoung Lee
Mar 25 · 4 min read

Babel과 node native es-module 기능 사용시 문제

Q.

#JavaScript 질문

init.js 에서 app.js 를 import 할 때

`./app` 로 실행하는 예제를 봤습니다. 하지만 전 안 돼서 `./app.js` 로 고치니까 되더라구요. (확장자 추가)

혹시 왜 이런지 아시는 분 계실까요? 둘이 같은 디렉토리 안에 있습니다.

에러메시지

`Error: Cannot find module app imported from init.js`

A.

확실치 않다는 것을 전제로 진행합니다.

babel에서는 import foo from "mod" 를 ImportDeclaration이라는 token으로 간주 합니다.

babel에서 JS 파일에서 해당 token을 처리하는 로직은 아래와 같습니다. 아래의 named 라는 로직이 처리 될 것으로 예상됩니다.

그리고 어디선가 addNamed 라는 로직이 처리되겠죠.


이쯤에서 node core를 파봅시다.

먼저 commonJS 가 어떻게 처리되는지 살펴보죠

여기 를 보시면 commonjs의 경우 단순히 read file 후에 compile을 통해서 모듈로 로드 된다는 것을 볼 수 있습니다.

그렇다면 type: module 을 통해 module 형태로 .js 확장자가 사용될 경우, 어떻게 될까요?

문제의 코드는 이부분인거 같은데요 여기서 보시면 source 를 load한 후에 ModuleWrap 이라는 native V8 코드로 감싸주는 부분이 있습니다 (…)

뭔지 정확히 모르겠지만, source 전체가 V8 엔진 core에서 관리 되는거죠.


다시 babel로 돌아와 봅시다.

addNamed에서 호출되는 _generatedImport 라는 함수를 확인해봅시다.

babel 설정에서 별도의 설정을 주지 않았다면 197번째줄의 importedType 이라는 변수가 commonJS 로 설정되어있을 것입니다. 따라서 로직에 따라서 default를 추가하는 등 babel에 의한 코드 수정이 일어나겠죠.


babel을 사용할 경우, 모든 import는 babel을 통한 코드 수정-> node 기본 로직의 단계로 수행 됩니다.

결국 질문자의 경우 code 가 babel에 의해서 commonjs로 변형된 후, node에서는 es-module이라고 판단된 상태에서 ModuleWrap 이라는 V8 CORE 코드에 의해 관리되겠죠.

결론적으로 babel + type: module 은 바람직하지 않다고 보여지고, 쓰시고 싶다면 babel에서 importedType 을 es6 로 하시고 모든 코드를 es-module 형식으로 작성하셔야 할 것 같습니다.

개발 싹다물어

소프트웨어 개발, 이제 혼자 고민하지마세요 :)

Mark Juyoung Lee

Written by

Dev Team Leader of HALFZ, https://www.nextunicorn.kr

개발 싹다물어

소프트웨어 개발, 이제 혼자 고민하지마세요 :)

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade