[Why JavaScript 01] .mjs는 뭔가요?

JS-WH-01calendar_today2026-05-04 23:10#Why #JavaScript #Node #ESM #CommonJS

.mjs는 뭔가요?

빠른 요약

  • .mjs로 끝나는 파일은 ECMAScript Modules(ESM)형식을 사용하는 JavaScript 파일이다.
    • Node.js는 과거 CommonJS방식을 사용하여 require로 다른 js 파일을 가져오는 방식을 사용
    • 이후 JavaScript의 모듈 시스템의 표준인 ESM이 도입되며 import/export를 사용하여 다른 js 파일을 가져오는 방식을 사용
    • 참고) 설명을 위해 "다른 js 파일을 가져온다"는 문장을 사용하였다. 실제로는 파일뿐 아니라 패키지, Node.js 내장 모듈, URL 등 다양한 모듈 식별자를 가져올 수 있다.
  • CommonJSESM 방식의 구분을 위해 파일 식별자가 달라진다.
    • .js → 환경 설정에 따라 CommonJS 또는 ESM
    • .mjs → 항상 ESM으로 해석
    • .cjs → 항상 CommonJS로 해석

문법 차이

js
// .mjs
import fs from 'fs';

export function hello() {
  console.log('hello');  
}

// .cjs
const fs = require('fs');

module.exports = function hello() {
  console.log('hello');
};

어라? 그런데 저는 .mjs를 쓰지 않고도 import/export를 잘 쓰고 있는데요?

  • .mjs, .cjs를 사용하지 않고도 사용할 수 있는 방법이 있음.
  • 바로, package.json에 아래와 같은 설정을 추가하는 것
json
{
  "name": "my-app",
  "version": "1.0.0",
  "type": "module"
}
  • 핵심은 "type": "module" 설정이다.

그럼 별도 설정 없이 기본값은 CommonJS인가요? 아니면 ESM인가요?

  • 명시적인 설정만 놓고 보면 package.jsontype 설정이 없을 때 .js 파일의 기본 해석은 CommonJS이다.
    • 그래서 일반적으로 .js 파일을 ESM으로 쓰고 싶다면 "type": "module"을 넣거나 .mjs 확장자를 사용한다.
  • 파일의 확장자, package.json의 설정에 따른 해석 방식은 아래 표와 같다.
파일/설정 해석 방식
.mjs 항상 ESM
.cjs 항상 CommonJS
.js + "type": "module" ESM
.js + "type": "commonjs" CommonJS
.js + "type" 없음 기본은 CommonJS

최신 Node.js에서는 예외가 있나요?

  • 있다. 최신 Node.js는 명시적인 표식이 없는 애매한 .js 파일에서 ESM 문법을 감지하면 ESM으로 다시 해석할 수 있다.
    • 여기서 명시적인 표식은 .mjs, .cjs, package.json"type": "module" 또는 "type": "commonjs" 같은 설정을 말한다.
    • 애매한 .js 파일에 import, export, import.meta, 최상위 await 같은 ESM 전용 문법이 있으면 Node.js가 ESM으로 판단할 수 있다.
  • 다만 이 동작에 기대기보다는 명시적으로 작성하는 편이 좋다.
    • ESM 파일이면 .mjs를 쓰거나, 패키지 단위로 "type": "module"을 둔다.
    • CommonJS 파일이면 .cjs를 쓰거나, 패키지 단위로 "type": "commonjs"를 둔다.
    • 이렇게 해야 사람, Node.js, 번들러, 테스트 도구가 같은 방식으로 파일을 이해한다.