[정리] JS 모듈 시스템, ESM

낙서·2022년 5월 28일
2

Study Note

목록 보기
4/6

자바스크립트 모듈 시스템 등장

자바스크립트 환경 발전, 많은 코드 관리를 위한 모듈 시스템 등장

자바스크립트 생태계가 더 많은 양의 코드를 빠르게 해석할 수 있도록 발전하였습니다. 이러한 발전은 자바스크립트 코드의 양이 많아지도록 하였습니다. 많아진 코드들의 사용성과 유지보수성을 위해 모듈 단위로 분할하거나 로드하여 사용 할 수 있는 모듈 시스템 매커니즘이 개발되었습니다.

모듈 사용

최상위 스크립트는 HTML에 script 태그를 이용하여 포함시킵니다. 스크립트 내부에서는 import, export 구문을 통하여 다른 모듈들을 불러오거나 내보낼 수 있습니다.

예) <script type="module" src="main.js"></script>

Naming conflicts

여러 모듈들을 가져오다보면 함수 이름의 중복으로 인해 충돌이 발생할 수 있습니다. 다음과 같은 방법들을 통해 충돌을 해결 할 수 있습니다.

  • as 키워드 사용: import/export 시 as 키워드로 각각 이름을 변경시켜주는 방법입니다.
import { draw as triangleDraw } from './modules/triangle.js'
import { draw as CircleDraw } from './modules/circle.js'

triangleDraw();
CircleDraw();
  • module 객체 생성: export 되는 값들을 하나의 객체로 묶는 방법입니다.
import * as Triangle from './modules/triangle.js'
import * as Circle from './modules/circle.js'

Triangle.draw();
Circle.draw();

Dynamic module loading

최상위 스크립트에서 시작하여 모든 모듈들을 한번에 불러오게되면 로딩시간이 오래 걸릴 수 있습니다. 이 문제를 해결하기 위한 방법으로 필요할 때에만 동적으로 모듈을 불러와 사용할 수 있는 동적 모듈 로딩이 있습니다. 이를 사용하는 이유는 앞서 설명했듯이 성능적인 이점이 있기 때문입니다.

triangleBtn.addEventListener('click', () => {
	import('/modules/triangle.js').then((Module) => {
    	let triangle = new Module.Triangle();
      	triangle.draw();
    });
});

ES modules

표준화된 자바스크립트 모듈 시스템으로 ES 모듈이 있습니다. 대부분의 브라우저가 이 ES 모듈을 지원하고 있습니다. import/export 키워드로 브라우저에서 모듈 시스템을 사용하는 것이 ES 모듈 시스템을 사용하는 것이라고 할 수 있습니다.

모듈 시스템 종류

Common JS(CJS) > Node.js 환경, ES Module(ESM) > 브라우저 환경

현재 많이 사용되고 있는 모듈 시스템은 ESM(ES Modules), CJS(Common JS) 두가지가 있습니다. 브라우저는 ES 모듈을 지원하고 Node.js 환경에서는 CJS를 사용합니다. 추가로 Node.js에서는 현재 ES 모듈 지원을 추가 중 입니다.

모듈 사용의 장점

코드 분리를 통한 유지보수성 향상, 문제 발생시 모듈 단위로 나누어져 있어서 문제 책임 부분 파악이 용이

자바스크립트에서 많은 변수를 관리하는 것은 중요한 포인트입니다. 변수를 스코프 외부로 공유하고 싶을 때는 상위 스코프로 변수를 배치하는 방법이 있습니다. 이 때 코드 양이 많다면 코드 배치 순서를 잘 정리하고 지켜야합니다. 코드의 순서가 지켜지지 않으면 문제가 발생할 수 있습니다.

모듈은 코드의 양이 방대 할 때, 관리의 어려움 문제를 대폭 해소시켜줍니다. 함수와 변수를 모듈 스코프로 분리 할 수 있고 모듈간의 의존성이 명시적으로 보이기 때문에 프로그램 오류 발생 시 어떤 모듈에서 발생한 문제인지 파악하기가 쉬울 것입니다.

ES 모듈 동작의 세가지 단계

Construction (구성) > Instantiation (인스턴스화) > Evaluation (평가)

ES 모듈은 구성, 인스턴스화, 평가 이렇게 세가지 단계를 거쳐 동작합니다. 구성 단계에서는 Entry point부터 시작하여 모든 모듈 파일들을 찾아서 가져옵니다. 그리고 가져온 파일들을 파싱하여 모듈 레코드라는 데이터 구조로 만듭니다. 다음 단계인 인스턴스화 단계에서는 모듈의 변수를 담을 메모리 공간을 찾아 그 주소를 변수 값들이 가리키도록 연결합니다. 인스턴스화 단계에서는 변수와 메모리의 연결만 이루어지고 마지막 평가 단계에서 코드를 실행하면서 메모리 공간에 값들을 실제 변수의 값으로 채우는 과정을 거칩니다.

1. Construction (구성)

브라우저 로더를 사용해 entry point부터 시작하여 모든 모듈 파일 로드, 파싱하여 모듈 레코드로 변환

브라우저에서 로더를 통해 entry point 파일에서 시작해서 import문을 따라 불러올 파일들을 찾아냅니다. 이 과정을 module resolution이라고 합니다.

그 다음 자바스크립트 파일을 파싱하여 모듈 레코드(Module Record)라는 데이터 구조로 변환하고 이는 Module Map에 추가됩니다.

2. Instantiation (인스턴스화)

모듈 변수 인스턴스들을 메모리에 연결

인스턴스화 단계는 모든 import/export된 변수 인스턴스들을 메모리에 연결하는 단계입니다. 실제 값을 메모리에 채우지는 않습니다. 실제 값을 채우는 과정은 평가 단계에서 이루어집니다.

3. Evaluation (평가)

Entry point부터 시작해서 코드를 실행하며 연결되어있던 메모리들을 실제 값으로 채웁니다.

CommonJS ES 모듈의 차이

1. 동작 차이

ES 모듈은 구성, 인스턴스화, 평가 단계가 독립적으로 수행될 수 있지만 Common JS에서는 의존성 로드, 인스턴스화, 평가가 한번에 이루어집니다.

ES modules는 실제 사용되는 부분만을 import 합니다. (tree shaking)

2. 문법 차이

Common JS에서는 모듈 지정자에 유동적인 변수를 넣을 수 있지만 ES Module에서는 그럴 수 없습니다.

require(`${path}/counter.js`).count; // ok
import { count } from `${path}/counter.js`; // not ok

참고 링크

profile
Deprecated

0개의 댓글