프론트엔드 개발자라면, require()와 import를 통한 라이브러리 호출은 자주 볼 수 밖에 없는 문법입니다.

그렇지만 왜 두 가지 버전의 호출이 존재하는지는 잘 모르고, 과거의 어떤 일이 있었길래 비슷한 두 개가 존재하는지 알아야 의문점을 해소하고 넘어갈 수 있을 것 같아서 작성하고 가고자 합니다.

물론, 저는 이 페이지에선 깊은 내용들을 다루진 않을것이고, 어떤 차이들이 존재하고 왜 이렇게 두 버전이 존재하는지와 같은 수박 겉핥기 수준의 내용들을 다룰 예정입니다


모듈 차이 발생의 이유

브라우저 환경에서 JS의 import, export 를 통해서 가져오기, 내보내기 를 수행합니다. ESM(EcmaScript Module)은 JS 공식 표준형태이고, 대다수의 브라우저는 해당 기능을 지원하는데요.

2024년인 지금, 우리는 NodeJS를 사용하는 것을 당연하게 생각합니다만 아주 예전엔, JavaScript는 그저 브라우저에서 DOM을 다루는 언어 정도였습니다. 옛날 분들은 만나면 “나때는 JS는 언어로 취급도 안 했고, 나도 인정하지 않았었다”라는 말을 종종 들어본 경험이 있으실거라고 생각됩니다. 게다가, <script>태그를 이용해 작성하는 코드 양이 많지 않던 정말 옛날에는, 굳이 모듈을 이용해 소스코드를 나눠가면서 작업 할 필요가 없었을 겁니다. 양이 적으니까요.

그치만, JS는 점점 브라우저의 세계에서만 있는 언어가 아닐 수 있게 발전되기 시작했고, NodeJS를 통해서 브라우저가 아닌 환경에서도 JS를 실행할 수 있게 되었습니다. 이제는 프론트엔드 영역에서도 벗어나 백엔드 영역을 다룰 수도 있는 언어가 되었고, 모듈 시스템에 대해 요구하는 사람이 늘어남에 따라, NodeJS에서 CommonJS라는 모듈 시스템이 탄생하게 됩니다.

하지만 JS가 아닌 NodeJS이었기 때문이었을까요? 결국 표준 시스템이 되진 못합니다. 그래서 EcmaScript가 ESM(EcmaScript Module)이라는 표준 시스템을 만들게 됩니다. (JS의 급격한 성장과 더불어 탄생하게 된 슬픈 CommonJS의 운명 같은 것 아닐까요🥲)

ESM과 CJS의 호환 가능성

그렇다면, ESM과 CJS라는 두 가지의 다른 모듈 시스템은 서로서로 호환이 가능할까요?

결론적으로는, 원래는 안됐었는데요. 이제는 가능합니다 현재 NodeJS 버전이 v20.12.2 입니다. v13.2.0 때부터는 안정적으로 ESM을 지원할 수 있게끔 NodeJS의 모듈시스템이 개선되었다고 하네요.

뭘 쓰지..?

그럼 이제, 이런 생각이 들 확률이 높을 겁니다 아…알겠는데 뭘로 모듈 시스템을 구축해야하는거지?

항상 명심해야할 것을 얘기하라고 하면, 전 ESM이 JS의 공식 모듈 시스템이다 인 것 같습니다. 물론, 가파른 JS의 성장에 따른 CJS라는 성장통에서, 이미 CommonJS로 NodeJS의 라이브러리와 모듈이 작성된 것들이 많습니다. 그치만, Babel 과 같은 Transpiler 를 통해 ESM이 지원되는 NodeJS 이전 버전으로 ESM문법을 require, module.exports = {} 의 CJS 형태로 변환시킬 수 있으며, 이미 다른 언어들에서 그러하듯이, ESM이 훨씬 직관적으로 파악하기 쉽습니다(이미 그런 문법들을 학습해왔으니)

그럼에도, 이미 오래전부터 작성되어온 프로젝트가 있는 경우엔 CJS로 진행해왔을테니 그대로 진행하는게 훨씬 나을 수도 있겠죠..?


참고 자료

Node.JS에서 CommonJS vs ES modules

ESM과 CommonJS의 차이