Common js와 ESM

zmin·2022년 8월 16일
0

자바스크립트 파일들이 script 태그로 추가되면 브라우저 전역 객체를 기반으로 공통의 스코프를 생성하기 때문에 다른 파일임에도 서로의 변수에 접근할 수 있었다 → 이런 점을 방지하기 위해 모듈을 이용. 코드를 캡슐화 하기 때문에 각자의 스코프를 유지할 수 있다.

https://medium.com/@cgcrutch18/commonjs-what-why-and-how-64ed9f31aa46 를 읽고 작성한 글

Common js

브라우저에서 벗어나는 api들을 정의하고 사용할 수 있도록 도와주는 common js

초반의 node js에서 이를 사용했음(지금은 esm을 주로 사용하는 듯)

모듈 포맷터. 모듈을 정의하고 module.exports 라는 객체에 내보내고 싶은 정보들만 담아 내보내고 require 을 이용하여 해당 모듈을 사용하는 것이 common js 모듈의 일반적인 형태

module.exports 객체의 프로퍼티에 함수 등을 할당하여 export 할 때는 require 를 named export 처럼 사용해야한다.

module.exports = a; // default export
module.exports.fn = () => console.log('hi'); // named export

사용 형태도 형태이지만 일단 common js의 require은 동기적인 작업이다. 프로미스나 콜백 등이 아님.

모듈을 전부 불러올 때 까지 다음 줄의 코드를 실행하지 않는다고 생각할 수 있다.
모듈 내부의 스크립트를 모두 바로 시행한 뒤에 module.exports에 정의한 값들을 return한다.

호출되는 위치에서 모듈을 전부 불러오고 실행한뒤 다음 코드로 넘어감 -> 코드 실행이 blocking 됨

ESM (ESMAscript modules)

지금 내가 많이 쓰고있는 export import 구문으로 표현되는 모듈들을 말한다.
ES6에서 도입

common js와 다른 점은 import가 비동기적으로 작업한다. import된 모듈들을 바로 실행하는 것이 아니라 내부의 import/export 구문을 찾아 파싱하며 그래서 이런 의존성있는 코드를 실행하지 않고도 typo error를 감지할 수 있다.

또한 이런 import export구문들을 파싱하면서 해당 모듈에서 사용된 또 다른 모듈을 detect할 수 있다. → 이 과정에서 코드를 실행하지 않고도 종속성 모듈 그래프를 만들어 낼 수 있음

이렇게 종속성에 대한 판단이 끝나야지만 인스턴스화하고 평가를 하는 등 코드가 실행된다.

이 그래프를 이용하여 종속성을 파악하고 있기 때문에 모듈의 임포트 순서가 크게 영향이 없다. 그리고 다른 구문들 보다도 import문이 가장 위에 위치해야하는 것 또한 특징. 해당 코드의 차례가 됐을 때 바로 불러오고 실행하는 cjs와는 달리 import/export에 대해 파싱을 먼저 진행하기 때문에 특정 위치를 지정해주는 것이 사실상 의미가 없음. 호이스팅이라고 생각할 수 있겠다.

한가지 또 특징은 트리 셰이킹을 지원해준다는 것. 각 모듈을 파싱하고 어떤 파일에서 어떤 값을 참조하고 다른 파일에서 내부 값중 어떤 것을 이용하는지가 파악되기 때문에 사용하지 않는 코드들을 삭제하여 최적화가 가능해진다는 점


하지만 해당 medium에서 말하길

Common js는 ESM의 등장 이전부터 사용되어 왔고, cjs에 비해 esm이 기본으로 설정해줘야하는 것(’use strict’, 바인딩되고 지정되지 않은 this들이 전역객체를 참조하지 않는다. 등)들이 많아 여전히 cjs는 default로써 사용되고 있다.
그래서 <script> 태그에서 src로 esm 모듈을 이용하려 하면 type='module' 이라는 어트리뷰트를 덧붙여줘야한다.

또한 cjs에서 esm모듈을 불러오는 것은 추가적인 번들러 설정 등 더 많은 것들이 필요하지만 반대로 esm에서 cjs모듈을 불러오는 것은 default import만 가능하다는 제한점이 있지만 역으로 사용되는 것보단 덜 번거롭게 사용할 수 있다.

→ 그래서 모듈을 만들어 배포하고 싶다면 cjs를 기본으로 설계하여 배포하되 esm형태의 사용을 지원하도록 추가로 설정해주는 것이 좋다고 한다.


타입스크립트를 사용할 때 tsconfig.json의 compilerOptions에 module을 적어주는 것도 자바스크립트로 컴파일할 때 어떤 모듈 포맷으로 컴파일할 것인지 명시해주는 것이다.

"compilerOprions": {
	"module": "commonjs",
}

다른 모듈 포맷

AMD

define 함수를 이용하여 모듈의 정의
아래와 같이 의존성으로 사용할 모듈과 모듈 내부 로직이 작성된 콜백함수를 전달한다.

define(['dep1', 'dep2'], function (dep1, dep2) {
	//모듈을 정의하고 export/module.exports 하던 것을 아래 return value로 대체
    return function () {};
});

이름부터가 비동기 모듈 정의이기 때문에 비동기로 작동한다.
동기적으로 작동하는 common js를 보완하기 위해 등장

profile
308 Permanent Redirect

0개의 댓글