hmk run dev

CommonJS와 ESM(esModule) 본문

javascript

CommonJS와 ESM(esModule)

hmk run dev 2024. 2. 24. 14:49

CommonJS:

 

- 파일 시스템에서 파일을 로드한다.
- 파일을 불러오는 동안 주 스레드를 차단한다.
- 그렇기에 파일 로드 - 구문 분석 - 인스턴스화 - 평가가 각 파일마다 바로 실행된다.
- 그렇기에 모듈 지정자에 변수를 넣을 수 있다.
- export 객체에 값을 복사해서 넣는다.


- 장점
널리 지원되는 표준: Node.js에서 기본적으로 사용되는 모듈 시스템이기 때문에 Node.js 환경에서는 자연스럽게 사용됩니다.
동기적 로딩: CommonJS는 동기적으로 모듈을 로딩하기 때문에, 런타임에서 모듈이 필요한 시점에 동기적으로 로딩할 수 있습니다.

- 단점

1. 파일 시스템에서 파일을 로드한다.
2. 비동기적 로딩의 부재: 브라우저 환경에서는 비동기적으로 모듈을 로딩할 수 있는 ESM과는 달리, CommonJS는 동기적으로 동작하기 때문에 브라우저에서 사용하기에는 성능 이슈가 있을 수 있습니다.

즉, 파일을 불러오는 동안 메인 스레드를 차단한다.

 

 

정적인 모듈 구조: CommonJS는 실행 시간에 동적으로 모듈을 로딩하기 어려워서 정적인 모듈 구조를 가지고 있습니다.



ECMAScript Modules (ESM):

 

- entry 파일의 구문 분석 후 의존성(import)을 확인해서 해당 의존성 파일을 찾아서 다시 구문 분석을 반복한다.
- 파일을 불러오는 동안 주 스레드를 차단하지 않는다.
- 인스턴스화, 평가는 더 이상 구문 분석할 의존성이 발견되지 않으면 실행한다
- 그렇기에 모듈 지정자에 변수를 넣을 수 없다(다만 동적 import를 쓰면 가능)
- export는 참조를 반환하는 함수를 정의한다.
- 동적 import는 별개의 entry 파일로 취급되어 새로운 그래프를 만든다.


- 장점
브라우저와 Node.js에서 사용 가능: 최신 브라우저와 Node.js에서 모두 지원되므로, 플랫폼 간 코드를 쉽게 공유할 수 있습니다.
비동기적 로딩: ESM은 비동기적으로 모듈을 로딩할 수 있어, 브라우저에서는 성능 향상에 기여할 수 있습니다.

- 단점
Node.js에서의 도입이 느림: Node.js에서는 예전 버전에서는 ESM이 실험적으로 제공되었고, 안정적인 지원은 상대적으로 최근에 이루어졌습니다.

구현의 어려움: ESM은 정적 모듈 구조를 갖고 있어, 일부 상황에서는 CommonJS보다 조금 더 복잡한 구현을 요구할 수 있습니다.



프론트엔드:
프론트엔드에서는 주로 ESM이 사용되고 있습니다. 브라우저에서의 비동기적 로딩과 플랫폼 간 호환성이 ESM을 선호하게 만들고 있습니다. 번들러(Bundler)가 일반적으로 ESM을 지원하며, 현대적인 프론트엔드 개발에서는 ESM을 사용하는 것이 일반적입니다.


Node.js에서:
Node.js에서는 CommonJS가 여전히 많이 사용되고 있습니다. 하지만 Node.js 13 버전 이후부터는 ESM을 실험적으로 지원하고, Node.js 14 버전부터는 안정적으로 사용 가능합니다. ESM은 특히 프로젝트가 CommonJS와 ESM을 혼용해야 하는 경우에 유용할 수 있습니다.

따라서 프론트엔드 개발에서는 주로 ESM을 사용하고, Node.js 개발에서는 프로젝트의 요구 사항에 따라 CommonJS 또는 ESM을 선택하는 것이 일반적입니다.

 


프로젝트에 적용하기

 

ESM (ECMAScript Modules)을 사용하려면 몇 가지 설정이 필요합니다. 주로 Node.js 환경에서 ESM을 사용하는 경우를 기준으로 설명하겠습니다.

Node.js 버전 확인:
먼저 프로젝트에서 사용 중인 Node.js 버전이 13 버전 이상인지 확인하세요. ESM은 Node.js 13 버전부터 실험적으로 도입되었고, 14 버전부터는 안정적으로 사용 가능합니다.

파일 확장자 .mjs 사용:
ESM을 사용하려면 파일 확장자를 .mjs로 사용해야 합니다. 파일 이름이나 package.json의 "type" 속성을 통해 모듈 형식을 명시할 수도 있습니다.

// 예시: app.mjs
import { someFunction } from './someModule.mjs';

 

 

package.json 설정:

package.json 파일에 "type" 속성을 "module"으로 설정하여 해당 프로젝트가 ESM을 사용하고 있다는 것을 명시할 수 있습니다.

{
  "type": "module",
  // 다른 속성들...
}

 

 

CommonJS 모듈과 함께 사용하기:

프로젝트에 CommonJS 모듈이 함께 사용되는 경우, .cjs 확장자를 가진 파일은 CommonJS 모듈로 간주됩니다. 파일 확장자를 통해 모듈 형식을 구분할 수 있습니다.

 

// 예시: commonjsModule.cjs
const someFunction = require('./someFunction')

 



번외(feat. GPT)

tsconfig에서 module을 commonjs로 설정해놔도 esm 형태의 import 구문을 사용해서 모듈을 사용할 수 있는 이유

 

Comments