1. CommonJS, ES Modules는 무엇일까?
- 우리는 JS 모듈을 내보내거나 가져올 때 2가지 방식을 사용한다.
- 첫번째 방법은
module.exports
로 모듈을 내보내고require()
로 접근하는CJS
(CommonJS), - 두번째 방법은
export
로 모듈을 내보내고import
로 접근하는ESM
(ES Modules)이 있다.
// CJS 방법
module.exports = { ... } // 모듈 내보낼 때
const utils = require('utils'); // 모듈 가져올 때
// ESM 방법
export.default =()=> { ... }; // 모듈 내보낼 때
import utils from 'utils'; // 모듈 가져올 때
- 그런데
ESM
,CJS
는 같은 기능을 하는 것 같은데, 어떤 차이가 있는걸까? - 이번시간에는
ESM
,CJS
의 차이점에 대해 간단히 알아보았다 🙂 (출처)
2. CJS, MJS의 차이점
1) CJS 방식
(1) CJS는…
📌
require
로 모듈에 접근하고module.exports
로 모듈을 내보내는 ESM 방식
- NodeJS에서 지원하는 모듈 방식으로, 초기 Node버전부터 사용되었다.
- 별도의 설정이 없다면
CJS
가 기본값이다.
(2) 모듈에 접근할 때, require()
- 외부 모듈에 접근할 때는
require()
을 사용한다.
const utils = require('utils'); // utils 모듈에 접근하기
(3) 모듈을 내보낼 때, module.exports
module.exports
로 모듈을 내보낸다.- 모듈을 내보내는 방식은
named exports
,default exports
두가지가 있다.
module.exports.utils = { ... }; // named exports
module.exports = { ... } // default exports
named exports
의 경우 export 대상을 명명하여 내보내는 방식이다.- 한 파일에서 여러 개의 변수, 클래스, 함수를 내보낼 때 주로 사용한다.
// calculator.js
module.exports.add = (a, b) => a + b;
module.exports.sub = (a, b) => a - b;
named exports
모듈은 2가지 방식으로 접근할 수 있다.
const calculator = require("./calculator.js");
const { add } = require("./calculator.js");
console.log(calculator.add(2, 2)); // 출력: 4
console.log(add(2, 2)); // 출력: 4
default exports
의 경우, 별도의 명명없이 내보내는 방식이다.- 한 파일에서 하나의 변수, 클래스, 함수를 내보낼 때 쓰인다.
// calculator2.js
module.exports = (x, y) => x + y
default exports
모듈을 접근할 때는 원하는 이름으로 설정하여 사용할 수 있다.
const add = require("./calculator2.js"); // 모듈을 add로 명명하기
console.log(add(2, 2)); // 출력: 4
(4) CJS의 특징
require()
는 즉시 스크립트를 실행하는 구조이다.- top-level await가 불가능하므로 동기적으로 작동한다.
- 동기로 작동하므로
promise
를 리턴하지 않고,module.exports
에 설정된 값만을 리턴한다. import
순서에 따라 스크립트를 실행한다.
2) ESM 방식
(1) ESM은…
📌
import
로 모듈에 접근하고export
로 모듈을 내보내는 ESM 방식
ES Modules
(MJS)는 ECMAScript에서 지원하는 방식이다.- Node14에선
CJS
,MJS
이 공존하는데, 두 개를 동시에 사용하기 위해 별도의 처리가 필요하다. - 모듈 시스템을
CJS
(기본값)에서ESM
으로 변경할 시, JS 일부 동작이 변경된다. (호환성 문제)
(2) ESM 사용하는 법
- ESM 방식을 사용하기 위해선 package.json에
“type”: “module”
을 설정해야 한다.
// package.json
{
"type": "module",
}
(3) 모듈에 접근할 때, import()
- 모듈에 접근하기 위해서
import
을 사용한다.
import utils from 'utils';
import { add } from 'utils';
import { add as add_func } from "utils";
(4) 모듈을 내보낼 때, export
export
로 내보낸 모듈은import
로 접근할 수 있다.named exports
와default exports
를 두가지를 지원한다.- 아래는
named exports
의 예시이다.
// calculator.js
export const = (x, y) => x + y;
named exports
는 명명된 이름으로만 모듈을 불러올 수 있다.as
를 사용해 명명된 이름을 다른 별칭으로 수정할 수 있다. ( 아래 예시:sum
→sum_func
)
import { sum } from "./calculator.js";
import { sum as sum_func } from "./calculator.js"; // 다른 별칭으로 수정
console.log(sum(2, 4)); // 출력: 6
console.log(sum_func(2, 4)); // 출력: 6
- 만약 default 방식으로 접근할 시 SyntaxError가 발생한다.
// SyntaxError does not provide an export named 'default'
import calculator from "./calculator.js";
console.log(calculator.sum(2, 4)); // error
- 다음은
default export
의 예시다.CJS
와 마찬가지로, 별도로 이름을 지정하지 않는다.
// calculator2.js
export default (x, y) => x + y;
- 명명된 이름이 없으므로 원하는 이름으로
import
하면 된다.
import add from "./calculator2.js";
console.log(add(2, 4)); // 출력: 6
(4) ESM의 특징
- top-level await를 지원하므로 module loader가 비동기 환경에서 실행된다.
- 그러므로
CJS
처럼 스크립트를 바로 실행하지 않고import
,export
구문을 찾아 스크립트를 파싱한다. - 파싱 단계에서
import
,export
에러를 감지할 수 있다. - 모듈을 병렬로 다운로드하지만, 실행은 순차적으로 한다.
import
와export
를 지원하지 않는 브라우저가 있기에,ESM
사용을 위해 번들러가 필요하다.
이번 포스팅에선
CJS
,ESM
에 대해 알아보았다. 먼저CJS
는require
로 모듈에 접근하고module.exports
로 모듈을 내보내며,ESM
은import
로 모듈에 접근하고export
로 모듈을 내보낸다는 걸 알았다. 또한, 모듈은 기본적으로 CJS 방식으로 동작하므로 ESM을 사용하기 위해선 package.json 설정과 추가적인 번들러 설정이 필요하다는 것도 알 수 있었다. :)
반응형
'개발 기술 > 개발 이야기' 카테고리의 다른 글
husky로 Conventional Commit 체크하기 (2) | 2022.11.19 |
---|---|
[CSS] Media Query 비교연산자(<, >, =) (0) | 2022.11.09 |
[JS] Strict mode는 무엇일까? (0) | 2022.10.29 |
[github Actions] 파일 경로에 따라 라벨링하고 릴리즈하기(feat. 모놀리식 레포) (0) | 2022.10.19 |
[Git] 저장소를 다른 저장소로 통합하는 2가지 방법(git history 유지) (1) | 2022.10.03 |
댓글