CJS 와 ESM

·2023년 3월 9일
3

개발 지식

목록 보기
42/96
post-thumbnail

CJS와 ESM

개요

초창기 JS 에는 모듈별로 코드를 가져오거나, 내보내는 방법이 없어, 하나의 JS 파일에 모든 기능을 담아야 했다. 이러한 문제는 점차 시간이 지날수록 가독성이 떨어지고, 동일 변수 사용으로 인한 에러가 나타나는 결과를 초래하기도 했다. 더불어 node.js를 통해 JS 가 서버 사이드에서도 영향을 미치기 시작하며 모듈 시스템에 대한 고민이 생겨났고, 오늘날 사용하고 있는 CJS, ESM이 등장하게 되었다.

CJS

CJS는 Node.js에서 가장 일반적으로 사용되는 모듈 시스템입니다. CJS 모듈은 require() 함수로 가져올 수 있으며, module.exports 객체를 통해 모듈을 내보낼 수 있다.

// 가져오기
let {A,B} = require('index.js');

// 내보내기 index.js
const A = 20;
const B = 30;

module.exports = {
	A,
	B
}

ESM

ESM은 최신 JavaScript 버전에서 지원되는 모듈 시스템으로 ESM 모듈은 import 문으로 가져올 수 있으며, export 문을 사용하여 모듈을 내보낼 수 있다.

// 가져오기
import a,b from './index.js'

// 내보내기 1 index.js
const A = 20;
const B = 30;

export {A,B};

// 내보내기 2 index.js
export const A = 20;
export const B = 30;

CJS, ESM 특징 및 차이점

동적 코드의 유무

CJS는 런타임 시 동적으로 코드를 처리하는 반면, ESM은 정적으로 코드를 처리한다. ESM 은 코드를 가져오기 전, 실제 사용하는 부분과 사용하지 않는 부분을 미리 파악하는 작업이 진행이 된다. 이 단계는 총 3가지 작업으로 이루어지는데,

  1. 생성 ( 또는 파싱 ) : import를 재귀적으로 찾아가며 모든 파일의 내용을 적재한다.

  2. 인스턴스화 : 각 파일에서 export된 참조를 메모리에 유지하고, 각 종속성 관계를 추적한다.

  3. 평가 : 인스턴스가 끝났다면 이제 모든 준비가 된 것이므로 코드를 평가한다.

CJS 의 경우에는 동적으로 코드를 import 하기 때문에, 종속성이 모두 파악되기 전에 코드를 가져오고 실행하게 된다. CJS 가 최상단이 아닌 코드 중간에서 파일이나 코드를 가져오는 것이 가능한 것도 이러한 특성 때문이다.

if (a === true) {
	const { aModule } = require('a.js');
}

순환 종속성

순환 종속성은 코드 A, B 가 서로를 참조하는 상태이다. CJS 의 경우, 재참조를 대비하여 이전에 참조한 모듈을 캐싱하여 가지고 있는 과정을 수행하게 되는데, 이때 순환 참조를 통해, 상대의 어떤 값을 변경하게 되었다면 이후 해당 코드에 대한 참조가 또 한번 일어났을 때, 캐싱을 통해 업데이트 되지 않는 값을 가져오는 문제가 발생할 수 있다. 이를 순환 종속성 문제라 하는데, CJS에서는 이러한 문제가 나타날 수 있다. (최근에는 에러를 반환한다고 한다.)

ESM를 사용하는 경우에는 import 구문은 모든 코드의 최상위에서 선언되며, 가장 먼지 실행이 진행된다. ESM의 정적 코드의 특성 덕분에, 종속성을 모두 파악한 뒤에 실행이 이루어지기 때문에, 순환 참조성이 존재하는 상황에서도 모든 모듈이 다른 모듈의 최신 상태를 유지할 수 있다.

파일 확장자

CJS의 파일 확장자는 .js 이고, ESM의 파일 확장자는 .mjs 사용을 권장한다.

주석 처리 방식

CJS는 ///* */ 와 같은 주석 처리 방식을 사용한다. 반면 ESM은 ///* */ 외에도 # 과 같은 주석 처리 방식을 사용할 수 있다.

요약

CJS

  • require() 함수로 가져오기 가능
  • module.exports로 모듈 내보내기
  • 동적으로 코드 처리
  • 순환 종속성 문제 발생 가능
  • 확장자 .js
  • 주석 처리 방식은 ///* */ 사용

ESM

  • import 문으로 가져오기 가능
  • export 문으로 모듈 내보내기
  • 정적으로 코드 처리
  • 순환 종속성 문제 없음
  • 확장자 .mjs 사용 권장
  • 주석 처리 방식은 //, /* */, # 모두 사용 가능

참고
[javascript] CJS, AMD, UMD, ESM 이란? / 사용법
[javascript] 모듈 시스템 - CJS, ESM 동작원리 이해하기
CommonJS와 ESM에 모두 대응하는 라이브러리 개발하기: exports field
ESM과 CommonJS의 차이

profile
새로운 것에 관심이 많고, 프로젝트 설계 및 최적화를 좋아합니다.

0개의 댓글