모듈은 왜 필요한가요?
- 애플리케이션이 고도화되면, 스크립트 소스코드의 양도 증가합니다.
- 결국 많은 양의 소스코드를 효율적으로 관리하기 위해서 모듈이라는 개념이 필요해집니다.
- 초기의 자바스크립트는 간단한 스크립트를 지향했기 때문에 모듈을 문법 차원에서 지원하지 않았습니다.
- ES6 (ES2015) 이후부터 공식적으로 모듈 문법인
export
,import
문법을 지원합니다.
자바스크립트의 모듈이란 무엇인가요?
- 단지 하나의
.js
파일을 의미합니다. .js
파일 내부에서는export
와import
문법을 이용해 함수, 변수 등을 교환하여 사용할 수 있습니다.- 가져올
js
파일이 모듈이라면<script type="module">
와 같이script
태그에type
이module
임을 명시하면 됩니다.
// 📁 sayHi.js
export function sayHi(user) {
console.log(`Hello, ${user}!`);
}
// 📁 main.js
import { sayHi } from "./sayHi.js";
sayHi("Jake"); // Hello, Jake!
모듈은 브라우저에서 어떻게 실행되나요?
- 브라우저가 모듈을 가져오고 평가 후에 실행합니다.
모듈의 특징을 알고 있나요?
로컬에서는 동작하지 않고 HTTPS
로만 동작합니다.
- 로컬에 있는 파일을 대상으로
import/export
를 적용하면, 동작하지 않습니다. - 모듈을 테스트하고 싶다면, 라이브 서버를 열어야 합니다.
언제나 strict mode
로만 작동합니다.
<script type="module">
a = 5; // error
</script>
strict mode
로 작동하기 때문에 위의 코드는 에러를 던집니다.
각 모듈은 Module-level scope
를 가집니다.
// 📁 user.js
const user = "Jake";
// 📁 hello.js
console.log(user);
<!-- 📁 index.html -->
<!DOCTYPE html>
<script type="module" src="user.js"></script>
<script type="module" src="hello.js"></script>
Module-level scope
로 각 모듈의 스코프가 나누어져hello.js
는user.js
의 변수에 접근할 수 없습니다.
여러번 import
를 수행해도 단 한번만 평가됩니다.
// alert.js
alert("HELLO!");
<!DOCTYPE html>
<script type="module">
import "./alert.js";
import "./alert.js";
import "./alert.js";
import "./alert.js";
</script>
여러번 import
를 해도 HELLO!
는 단 한번만 출력됩니다.
한번만 평가되기 때문에 불러온 모듈의 값을 변경하고 다시 불러와도 유지됩니다.
export const person = {
name: "Jake",
};
<!DOCTYPE html>
<html lang="ko">
<head>
<title>모듈 테스트</title>
</head>
<body>
<script type="module">
import { person } from "./person.js";
console.log(person); // Jake
person.name = "Jax";
console.log(person); // Jax
</script>
<script type="module">
import { person } from "./person.js";
console.log(person); // Jax
person.name = "Jax";
console.log(person); // Jax
</script>
</body>
</html>
- 한번
import
한 모듈의 오브젝트 프로퍼티 값을 바꾸면 다시 불러와도 유지됩니다. import
를 두번해도 처음 불러온person.js
를 재사용하기 때문입니다.- 이러한 기능은 많은 자바스크립트 파일에서 같은 모듈을 쓸 때 같은 모듈을 여러번 불러오지 않아도 되게 만들어줍니다.
- 이 특징을 이용해 모듈 설정 (module configuration) 이 가능합니다.
- 회원 정보를 가지고 있는 객체를
import
한 뒤에 이름을 설정해주면 해당 회원 정보를import
하여 쓰는 모든 객체에 영향을 미칩니다.
- 회원 정보를 가지고 있는 객체를
import.meta
- 현재 모듈에 대한 정보를 제공해줍니다.
import.meta.url
은 모듈의 위치를 가리킵니다.
모듈의 this
는 undefined
입니다.
- 일반 브라우저에서의
this
는 전역 객체이며, Node 환경에서의this
는 전역 객체인 것과 차이가 있습니다.
<script>
console.log(this); // window 객체가 출력됨
</script>
<script type="module">
console.log(this); // undefined 가 출력됨
</script>
브라우저에 특화된 모듈의 특징을 알고 있나요?
지연 실행
- 모듈 스크립트는 항상
defer
속성을 붙인 것과 동일하게 실행됩니다.defer
속성에 대한 자세한 내용은 이 포스팅에서 확인할 수 있습니다.
- 모듈 스크립트도
defer
속성의 특징을 동일하게 가지고 있기 때문에 모듈 스크립트는 항상 완전한 HTML 페이지를 볼 수 있습니다.- DOM 요소에도 접근 가능합니다.
<script type="module">
console.log("모듈 스크립트:" + typeof button); // undefined
console.log("모듈 스크립트:" + document.getElementById("button")); // null
</script>
<script>
console.log("일반 스크립트:" + typeof button); // object
console.log("일반 스크립트:" + document.getElementById("button")); // [object HTMLButtonElement]
</script>
<button id="button">Button</button>
단, HTML 문서에서
button
엘리먼트를 사용하지 않는다면,typeof button
은 계속undefined
를 출력합니다.button
변수는 DOM 에서button
엘리먼트에 접근할 때 생성되기 때문입니다.
인라인 스크립트에도 async
적용이 가능합니다.
- 일반
script
태그에서는src
속성이 없다면async
적용이 불가능합니다. type="module"
인 경우에는src
속성이 없는 인라인 스크립트여도async
적용이 가능해집니다.- 외부 스크립트나 DOM 에 의존하지 않는 스크립트를 작성할 때 유용합니다.
<script async type="module">
import { counter } from "./analytics.js";
counter.count();
</script>
이전에 언급했지만, src
속성값이 동일한 외부 스크립트는 한번만 평가됩니다.
<script type="module" src="a.js"></script>
<script type="module" src="a.js"></script>
외부 사이트에서 모듈 스크립트를 불러오려면 CORS 헤더가 필요합니다.
- 외부 웹사이트에서 CORS 헤더를 제공받아야 합니다.
Access-Control-Allow-Origin: *
<script type="module" src="http://cross-site.com/source.js"></script>
경로가 없는 모듈은 금지됩니다.
Node.js
나 번들링 도구가 있다면, 경로가 없는 모듈도 가능합니다.- 그러나 기본 스펙을 사용할 때 경로가 없는 모듈은 금지됩니다.
import { sayHi } from "sayHi"; // Error!
import { sayHi } from "sayHi.js"; // OK!
호환성을 위한 nomodule
속성이 있습니다.
- 모듈이 없는 경우에만
nomodule
속성의 스크립트가 동작합니다.
<script type="module">
console.log("this browser supports module");
</script>
<script nomodule>
console.log("this browser does not support module");
</script>
빌드 도구를 사용한다면, 모듈에 어떤 일이 벌어지나요?
<script type="module" src="entry.js"><script>
에서src
에 들어갈 메인 진입점 모듈을 선택합니다.- 주요 모듈을 분석하여 모듈간의 의존관계를 파악합니다.
- 모듈 전체를 한데 모아 큰 파일을 만듭니다. (설정에 따라 여러 개의 파일을 만드는 것도 가능합니다.)
- 이 과정에서
import
문이 번들러 내의 함수로 변환되어 기존 기능은 그대로 유지됩니다.
- 이 과정에서
- 기타 변형 및 최적화를 진행합니다.
- 사용되지 않는 코드 (구조적으로 도달 불가능한 코드) 는 삭제됩니다.
- 쓰임새가 없는 모듈을 삭제합니다. (트리 쉐이킹 (tree-shaking))
console
,debug
와 같은 개발 관련 코드는 삭제합니다.- 바벨에 설정된 타겟 버전이 있다면, 해당 버전으로 코드를 변환합니다.
- 공백 제거, 변수 이름 줄이기 등으로 산출물의 크기를 줄입니다.
- 번들을 거치면, 일반 스크립트를 취급하는 것과 동일하게 취급할 수 있습니다.
<!-- 웹팩과 같은 툴로 번들링 과정을 거친 스크립트인 bundle.js -->
<script src="bundle.js"></script>
레퍼런스
반응형
'자바스크립트 > 인터뷰' 카테고리의 다른 글
클로저 (Closure) 란 무엇인지 설명해주세요. (0) | 2023.02.08 |
---|---|
호이스팅이란 무엇인가요? (0) | 2023.01.26 |
메모이제이션이란 무엇인가요? (0) | 2023.01.26 |
자바스크립트에서 URL 을 인코드하거나 디코드하는 방법에 대해서 알고 있나요? (0) | 2023.01.26 |
자바스크립트의 TDZ (Temporal Dead Zone) 에 대해서 간단히 설명해주실 수 있나요? (0) | 2023.01.18 |