- 모듈 시스템이란?
초창기 자바스크립트의 크기가 작았을땐 하나의 자바스크립트 파일로도 페이지가 동작했지만 점점 시간이 지나면서 스크립트의 크기가 커지고 복잡해지면서 여러 문제가 생기게 되었다.
특히 여러 스크립트파일을 하나의 전역 스코프에서 관리하기 때문에 파일의 순서가 잘못되면 전역 변수가 쉽게 오염이 되고 많은 버그가 생기게 된다. 그래서 결국 브라우저에서도 이러한 자바스크립트를 위한 모듈시스템을 도입하게 되는데, 모듈시스템을 통해 각 모듈의 import, export를 제외한 나머지것들은 타 모듈에서 신경쓰지 않아도 되었으며, 무엇보다 파일의 단위를 나누기 수월해 졌다.
브라우저에서는 esm모듈 시스템, Node.js에서는 commonJs란 모듈시스템을 현재까지 사용중이며 그 과정에는 AMD와 UMD도 함께 하였다. 하지만 가장 많이 쓰이는 CJS와 ESM에 대해 알아 보고자 한다.
- CJS (CommonJS)
서버사이드에서 사용되는 모듈시스템이며, 기본적으로 동기적으로 파일시스템에서 모듈을 불러온다. NodeJs에서 초창기부터 썻었으므로 ESM보다 먼저 사용되었다. cjs는 동기적이기 때문에 빌드타임에서 정적 분석을 적용하기가 어렵다. 또한 특정 모듈을 require할때 불러오는 모듈에 대한 작업이 모두 수행된 뒤에 그 결과를 export값의 사본으로 받는다. 그래서 require할때 사용하는 url안에 값을 넣을 수가 있다.
또한 CommonJS에서 ESM파일을 불러올 수 없다. 만약 이걸 가능하게 하려면 불러오는 패키지가 cjs에 대한 버전으로도 만들어져 있어야하며 exports때의 모듈시스템에 맞춰서 타입을 지정해 줘야한다.
또한 주스레드로 파일시스템을 불러오기 때문에 불러오는 과정에서 blocking된다. 그렇기 때문에 페이지렌더링을 중요시 여기는 브라우저에서는 파일을 불러오는 동안 렌더링할수 없기 때문에 브라우저에서는 맞지 않는 구조이기도 하다.
- ESM
브라우저에서 사용되는 모듈시스템이다. url을 통해 다운로드 하기 때문에 CJS보다는 다운로드하는 시간이 길어진다. 하지만 그대신 구문분석, 인스턴스화, 평가를 통해 코드 최적화나 공통 모듈 캐싱등의 기능을 사용할수 있고 순환 참조시에 올바른 값을 가져올 수 있다. 먼저 구문분석 단계에서는 해당 entry모듈에서 import하는 모든 모듈들을 그래프로 그리게 된다. 또한 모듈 레코딩을 만들어서 기록하게 된다. 모듈 레코드가 만들어지고 나면, 그 레코드는 모듈맵에 추가가 된다. 그 이후에 로더가 필요한 모듈을 해당 모듈맵에서 찾아서 가져오게 된다. 브라우저에서는 script태그의 type속성이 module인지, 노드에서는 .mjs 확장자인지를 확인 후에 모듈인지 인식하고 가져오게 된다.
다음은 인스턴스화 단계인데, 코드와 상태를 결합하는 단계이다. 아직 값을 채우는 단계는 아니고 export되는 상태들에 대해 메모리의 위치를 매핑시켜준다. 특히 이떄 import보다 export되는걸 먼저 연결함으로써 import들이 모두 각각의 export주소에 연결되는걸 보장할 수 있다. 또한 참조값을 연결시켜 주기 때문에 export한 모듈의 내용이 나중에 바뀌게 되더라도 그걸 Import하는 곳에서는 바뀐 내용을 가져올 수 있다.
마지막으로 평가단계를 거치며, 인스턴스화 단계에서 매핑했던 메모리 위치에 값을 채워준다. 이떄 중요한건 이 과정은 모듈당 한번씩만 수행된다. 만약 이과정에서 값을 가져오기위해 서버에서 무언가 요청을 하거나 했을때 다른값을 채울수 있기 때문이다. 모듈당 한번씩만 수행하기 위해 위에서 말한 모듈맵이 사용되며, 같은 url에 대해서 캐싱하여 가져온다.
만약 모듈사이에 순환참조가 이루어진다면 cjs의 경우 동기적으로 이루어지며 export된 값이 사본으로 복사되기 때문에 처음 참조되는 변수가 상대 모듈이 완료되야 얻을 수 있다면 undefiend를 반환하게 된다.
하지만 esm의 경우 구문분석을 거쳐서 모듈그래프를 그리고 값이 메모리에 참조 되기 때문에 올바른 상대값을 얻을 수 있다.
참고 자료
'프론트엔드' 카테고리의 다른 글
개인 이력서 - 반응형 웹 디자인 적용기 (0) | 2023.10.22 |
---|---|
(파일시스템) Blob, Base64, arrayBuffer, Buffer (0) | 2023.09.10 |
(프론트엔드) Refresh토큰과 Access토큰 인증처리 (0) | 2023.06.11 |
(프론트엔드)yarn berry (0) | 2022.10.07 |
OpenApi-Generator (0) | 2022.08.07 |