.mjs는 뭔가요?
빠른 요약
.mjs로 끝나는 파일은 ECMAScript Modules(ESM)형식을 사용하는 JavaScript 파일이다.
Node.js는 과거 CommonJS방식을 사용하여 require로 다른 js 파일을 가져오는 방식을 사용
- 이후 JavaScript의 모듈 시스템의 표준인
ESM이 도입되며 import/export를 사용하여 다른 js 파일을 가져오는 방식을 사용
- 참고) 설명을 위해 "다른 js 파일을 가져온다"는 문장을 사용하였다. 실제로는 파일뿐 아니라 패키지, Node.js 내장 모듈, URL 등 다양한 모듈 식별자를 가져올 수 있다.
CommonJS와 ESM 방식의 구분을 위해 파일 식별자가 달라진다.
.js → 환경 설정에 따라 CommonJS 또는 ESM
.mjs → 항상 ESM으로 해석
.cjs → 항상 CommonJS로 해석
문법 차이
// .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에 아래와 같은 설정을 추가하는 것
{
"name": "my-app",
"version": "1.0.0",
"type": "module"
}
- 핵심은
"type": "module" 설정이다.
그럼 별도 설정 없이 기본값은 CommonJS인가요? 아니면 ESM인가요?
- 명시적인 설정만 놓고 보면
package.json에 type 설정이 없을 때 .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, 번들러, 테스트 도구가 같은 방식으로 파일을 이해한다.