코어 자바스크립트 - 모듈(module)
개발하는 어플리케이션의 크기가 커지면 파일을 여러 개로 분리해야 한다.
이 때, 분리된 파일 각각을 모듈(module)이라고 부른다.
모듈은 대개 클래스 하나 혹은 특정한 목적을 가진 여러개의 함수로 구성된 라이브러리 하나로 구성된다.
모듈이란?
모듈은 단지 파일 하나에 불과하다.
스크립트 하나는 모듈 하나이다.
모듈에 특수한 지시자 export와 import를 적용하면
다른 모듈을 불러와 불러온 모듈에 있는 함수를 호출하는 것과 같은 기능 공유가 가능하다.
export 지시자를 변수나 함수 앞에 붙이면 외부 모듈에서 해당 변수나 함수에 접근할 수 있다.
import 지시자를 사용하면 외부 모듈의 기능을 가져올 수 있다.
위 예시에서 import 지시자는 상대경로(./sayHi.js)를 이용해 모듈을 가져오고
sayHi.js에서 내보낸 함수 sayHi를 상응하는 변수에 할당한다.
모듈은 특수한 키워드나 기능과 함께 사용되므로 <script type="module"> 같은 속성을 설정해
해당 스크립트가 모듈이란 걸 브라우저가 알 수 있게 해주어야 한다.
모듈의 핵심 기능
일반 스크립트와 모듈의 차이는 무엇일까?
모든 호스트 환경에 공통적으로 적용되는 모듈의 핵심 기능에 대해 알아보자.
엄격모드로 실행됨
모듈은 항상 엄격 모드(use strict)로 실행된다.
선언되지 않은 변수에 값을 할당하는 등의 코드는 에러를 발생시킨다.
모듈 레벨 스코프
모듈은 자신만의 스코프가 있다.
따라서 모듈 내부에서 정의한 변수나 함수는 다른 스크립트에서 접근할 수 없다.
외부에 공개하려는 모듈은 export 해야 하고, 내보내진 모듈을 가져와 사용하려면 import 해줘야 한다.
전역변수를 대신하여 hello.js에 user.js를 가져와 필요한 기능을 얻을 수 있다.
단 한 번만 평가됨
동일한 모듈이 여러 곳에서 사용되더라도 모듈은 최초 호출 시 단 한 번만 실행된다.
실행 후 결과는 이 모듈을 가져가려는 모든 모듈에 내보내진다.
이런 작동방식은 중요한 결과를 초래하는데, 예시를 통해 이야기하겠다.
alert 함수가 있는 모듈(alert.js)을 여러 모듈에서 가져오기로 해보자.
alert 창은 단 한 번만 나타난다.
실무에선 최상위 레벨 모듈을 대개 초기화나 내부 데이터 구조를 만들 때 사용한다.
이것들을 내보내 재사용하는 것이다.
이번엔 객체를 내보내는 모듈을 만들어보자.
이 모듈을 가져오는 모듈이 여러 개이더라도 앞서 설명한 것처럼 모듈은 최초 호출 시 단 한 번만 평가된다.
이 때 admin 객체가 만들어지고 이 모듈을 가져오는 모든 모듈에 admin 객체가 전달된다.
각 모듈에 동일한 admin 객체가 전달되는 것이다.
그러므로 어느 한 모듈에서 admin 객체를 수정하면 다른 모듈에서도 변경사항을 확인할 수 있다.
이런 특징을 이용하면 모듈 설정을 쉽게 할 수 있다.
최초로 실행되는 모듈의 객체 프로퍼티를 원하는 대로 설정하면 다른 모듈에서 이 설정을 그대로 사용할 수 있기 때문이다.
'this'는 undefined
모듈 최상위 레벨의 this 는 undefined이다.
모듈이 아닌 일반 스크립트의 this는 전역 객체인것과 대조된다.
브라우저 특정 기능
지연 실행
모듈 스크립트는 항상 지연실행된다.
외부 스크립트, 인라인 스크립트와 관계없이 마치 defer 속성을 붙인 것처럼 실행된다.
인라인 스크립트의 비동기 처리
모듈이 아닌 일반 스크립트에서 async 속성은 외부 스크립트를 불러올 때만 유효하다.
async 속성이 붙은 스크립트는 로딩이 끝나면 다른 스크립트나 HTML 문서가 처리되길 기다리지 않고 바로 실행된다.
반면, 모듈 스크립트에선 async 속성을 인라인 스크립트에도 적용할 수 있다.
빌드 툴
브라우저 환경에서 모듈을 단독으로 사용하는 경우는 흔치 않다.
대개 웹팩(Webpack)과 같은 특별한 툴을 사용해 모듈을 한 데 묶어(번들링) 프로덕션 서버에 올리는 방식을 사용한다.
번들러를 사용하면 모듈 분해를 통제할 수 있다.
여기에 더하여 경로가 없는 모듈이나 CSS, HTML 포맷의 모듈을 사용할 수 있게 해준다는 장점이 있다.
빌드툴의 역할
1. HTML의 <script type="module">에 넣을 주요 모듈(진입점 역할을 하는 모듈)을 선택한다.
2. 주요 모듈에 의존하고 있는 모듈 분석을 시작으로 모듈 간의 의존 관계를 파악한다.
3. 모듈 전체를 한 데 모아 하나의 큰 파일을 만든다.(설정에 따라 여러 개 파일을 만드는 것도 가능)
4. 이런 과정 중에 변형이나 최적화도 함께 수행한다.
- 도달 가능하지 않은 코드는 삭제한다.
- 내보내진 모듈 중 쓰임처가 없는 모듈을 삭제한다.
- console, debugger 같은 개발 관련 코드를 삭제한다.
- 최신 자바스크립트 문법이 사용된 경우 바벨(Babel)을 사용하여 같은 기능을 하는 낮은 버전의 스크립트로 변환한다.
- 공백 제거, 변수 이름 줄이기 등으로 산출물의 크기를 줄인다.
번들링 툴을 사용하면 스크립트들은 하나 혹은 여러 개의 파일로 번들링된다.[
이 때 번들링 전 스크립트에 있던 import/export 문은 특별한 번들러 함수로 대체된다.
번들링 과정이 끝나면 기존 스크립트에서 import/export 가 사라지기 때문에 type="module"이 필요 없어진다.
따라서 아래와 같이 번들링 과정을 거친 스크립트는 일반 스크립트처럼 취급할 수 있다.
요약
1. 모듈은 하나의 파일이다.
2. 브라우저에서 import/export 지시자를 사용하려면 <script type="module">같은 속성이 필요하다.
3. 모듈은 아래와 같은 특징을 지닌다.
- 지연실행된다.
- 인라인 모듈 스크립트도 비동기 처리 할 수 있다.
- 외부 오리진(도메인, 프로토콜, 포트)에서 스크립트를 불러오려면 CORS 헤더가 있어야 한다.
- 중복된 외부 스크립트는 무시한다.
4. 모듈은 자신만의 스코프를 갖는다.
5. 모듈 간 기능 공유는 import/export로 할 수 있다.
6. 항상 엄격 모드로 실행(use strict)된다.
7. 모듈 내 코드는 단 한번만 실행된다. 모듈을 내보내면 이 모듈을 가져오기 하는 모듈 모두가 내보내진 모듈을 공유한다.
모듈 내 함수나 객체 등은 export 키워드로 내보낼 수 있다.
이렇게 내보내진 기능은 import 키워드를 사용해 가져와 사용할 수 있다.
브라우저는 자동으로 스크립트를 불러오고 평가한다.
실제 애플리케이션을 출시할 땐 성능 개선 등의 이점 때문에 웹팩과 같은 번들러를 사용한다.
'언어 > JavaScript' 카테고리의 다른 글
[React] Effect Hook 사용하기 (0) | 2021.03.31 |
---|---|
[React] State Hook 사용하기 (0) | 2021.03.30 |
[React] Hook 개요 (0) | 2021.03.30 |
[React] Hook 소개 (0) | 2021.03.30 |
코어 자바스크립트 - 모듈 내보내고 가져오기 (0) | 2020.12.07 |