Jaeilit

JS - Module System 본문

TIL

JS - Module System

Jaeilit 2023. 8. 20. 17:04
728x90

JS 모듈 시스템

 

모듈 시스템은 코드를 모듈이라는 독립적인 단위로 구성하고, 이를 필요한 곳에서 재사용할 수 있도록 하는 개념입니다.

 

1. CommonJs

CommonJS 는 모듈 시스템의 일종으로, Javascript 를 서버사이드에서 사용하기 위해서 설계되었습니다.

주로 Node.js 환경에서 사용되며, 파일 단위로 코드를 모듈화하고 필요한 곳에서 재사용할수있게 해줍니다. (범용적인 사용)

CoomonJS 는 ES6 이전에 널리 사용되었던 모듈 시스템 중 하나입니다.

 

CJS 는 동기적으로 동작하기 때문에 해당 모듈의 내용이 완전히 로드 될때까지 다음 모듈은 기다려야합니다.

또한 동기적이란 말과 헷갈릴수도 있는 동적 로딩입니다. 동적 로딩이란 런타임 시에 필요한 모듈을 동적으로 결정하고 로딩할 수 있는 장점을 가지며, 필요한 모듈이 런타임에 결정되는 상황에 유용합니다. 동적로딩은 어떤 모듈이나 파일을 가져올지 정적으로 분석하기 어렵기 때문에 트리쉐이킹이 어렵다는 단점이 있습니다.

 

 

CommonJS 는 import 와 export 가 아닌 module.exports, require 을 사용하여 import, export 합니다.

// math.js (모듈 파일)
function add(a, b) {
  return a + b;
}

function subtract(a, b) {
  return a - b;
}

module.exports = {
  add,
  subtract
};


// main.js (메인 파일)
const mathModule = require('./math.js');

console.log(mathModule.add(5, 3));      // 출력: 8
console.log(mathModule.subtract(10, 4)); // 출력: 6

2. AMD

AMD 는 Asynchronous Module Definition 의 약자로 말 그대로 비동기적으로 작동합니다.

CommonJs 와 동일하게 서버사이드에서도 동작이 가능하지만 주로 브라우저에서 비동기적으로 모듈을 로드하고 사용하기 위해 설계되었습니다. AMD 로 유명한 라이브러리는 RequireJs 가 있습니다.

 

AMD 는 비동기적으로 로드하기 때문에 브라우저에서 모듈을 로딩하는 동안 페이지의 다른 작업이 중단되지 않도록 합니다. 모듈을 내보낼 대는 define() 함수를 사용하며 로드할때는 Commonjs 와 마찬가지로 require 함수를 사용합니다. 하지만 비동기로 로드하게 됩니다.

// math.js (모듈 파일)
define(function () {
  function add(a, b) {
    return a + b;
  }

  function subtract(a, b) {
    return a - b;
  }

  return {
    add,
    subtract
  };
});


// main.js (메인 파일)
require(['./math'], function (mathModule) {
  console.log(mathModule.add(5, 3));      // 출력: 8
  console.log(mathModule.subtract(10, 4)); // 출력: 6
});

3. UMD

UMD 는 Universal Module Definition 의 약자로 Universal 이라는 이름의 뜻에서도 알 수 있듯이 CommonJs와 AMD 방식을 모두 호환할수 있도록 조건문으로 분기하고, 이를 팩토리 패턴으로 구현했습니다.

 

모듈 로더를 확인하는 즉시실행함수(IIFE)로 전역 범위 root 와 모듈을 선언하는 함수 factory 2개의 파라미터를 가집니다.

(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD 환경에서 모듈 정의
    define(['dependency'], factory);
  } else if (typeof exports === 'object' && typeof module === 'object') {
    // CommonJS 환경에서 모듈 정의
    module.exports = factory(require('dependency'));
  } else {
    // 전역 네임스페이스에 모듈 할당
    root.myModule = factory(root.dependency);
  }
}(this, function (dependency) {
  // 모듈 코드
  var myModule = {};

  myModule.doSomething = function () {
    // ...
  };

  return myModule;
}));

 

4. ESM

ES6 이후 공식적으로 ESM 이라는 표준 모듈 시스템이 등장합니다. ESM 은 기존의 CommonJS 나 AMD 와는 다른 형식으로 모듈을 정의하고 사용하는데 주로 브라우저와 Node.js 에서 사용합니다.

 

ESM는 import 와 export 키워드를 사용하여 모듈을 정의하고 사용합니다. ESM 은 비동기적으로 실행되고, CJS 와 다르게 정적으로 로딩하기 때문에 빌드 시점에 모듈의 의존성을 파악할수 있으므로 트리쉐이킹이 가능합니다.

 

ESM 사용하는 방법은 3가지가 있습니다.

 

1. 확장자는 .mjs를 사용하기

2. script tag 의 type 을 module 로 설정해줍니다.

3. package.json 의 type 은 default 가 cjs 입니다. module 로 변경하여 사용할수 있습니다. ts.config 도 마찬가지입니다.

<!DOCTYPE html>
<html>
<body>
  <script type="module" src="foo.mjs"></script>
  <script type="module" src="bar.mjs"></script>
</body>
</html>

 

ESM 모듈 작동방식

 

 

ESM 은 모듈은 빌드 시 종속성 그래프(graph of dependencies)를 작성합니다.

entry(최초실행파일)를 기점으로 import 구문을 따라 나머지 코드들을 찾고 모듈 레코드라는 데이터 구조를 생성하고 변환하기 위해 모든 파일을 분석해야합니다.

import Entries 를 보면 moduleRequest 는 display.js 이지만 실제로 import 할 때 사용한 이름인 render 가 importName 으로 기록되어있는걸 볼 수 있습니다. 이 모듈 레코드를 인스턴스로 전환해야합니다. 모듈 레코드를 인스턴스로 전환한다는것은 모듈 레코드를 메모리 공간에 올리는 것을 말합니다.

 

인스턴스는 코드와 상태라는 두 가지를 결합합니다.

export 한 모든 값을 저장 할 메모리 공간을 찾고 export/import 가 모두 저장할 메모리 공간을 가리키도록 연결합니다.

 

ESM 은 3가지의 프로세스를 나뉘어 동작힙니다. 

 

1. 구성 (constrouction) [fetch, parse]

   - 모든 파일을 찾아 다운로드하고 모듈 레코드로 구문 분석합니다.

2. 인스턴스화 (instanstion)

   -  내보낸 모든 값을 저장 할 메모리 공간을 찾습니다. 그 다음 export import 가 모두 메모리의 해당 상자를 가리키도록 합니다.

3. 평가 (evaludation)

    - 코드를 실행하여 변수의 실제 값으로 메모리 공간을 채웁니다

 

참고자료

https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/

 

ES modules: A cartoon deep-dive – Mozilla Hacks - the Web developer blog

ES modules bring an official, standardized module system to JavaScript. With the release of Firefox 60 in May, all major browsers will support ES modules, and there is current work ...

hacks.mozilla.org

https://blog.naver.com/pjt3591oo/222834625061

 

[javascript] 모듈 시스템 - CJS, ESM 동작원리 이해하기

안녕하세요 멍개입니다. 지난 시간의 자바스크립트 모듈 시스템을 다뤘습니다. https://blog.naver.com/pjt...

blog.naver.com

 

728x90