이번에 바닐라 JS 로 채용 과제를 진행하면서, 스크립트 파일의 엔트리포인트를 설정하기 위해 경로를 지정하며 type의 module 이라는 속성을 사용했습니다.
module 속성값이 무엇인지 잘 모르고 썼는데, 자바스크립트 딥다이브를 읽다보니 해당 부분에 대한 내용이 나와 정리해보려고 합니다.
모듈이란
애플리케이션의 크기가 커질 때 이를 관심사별로 여러개의 파일로 분류하게 됩니다. 이 때 분리된 각 파일을 module 이라고 합니다. 이렇게 모듈화하여 유지보수성을 높이고 보다 체계적으로 코드를 관리할 수 있다는 장점이 있습니다.
모듈을 어떻게 쓰나요?
자바스크립트에서 모듈을 내보내고, 가져오는 문법은 단순합니다. 저희가 숨쉬듯 사용하는(?) import 와 export 키워드를 사용하면, 클래스나, 함수, 변수 등을 내보내고 다른 파일에서 이를 가져올 수 있습니다.
// 📁 sayHi.js
export function sayHi(user) {
alert(`Hello, ${user}!`);
}
// 📁 main.js
import {sayHi} from './sayHi.js';
alert(sayHi); // 함수
sayHi('John'); // Hello, John!
그리고 이를 활용하려면 아래와 같이 script 태그 내부에 ‘이 자바스크립트 파일은 모듈 방식으로 동작합니다’ 라고 명시해주어야 합니다.
이 코드가 없으면, 아래와 같이 에러메시지가 출력됩니다.
import 구문 어쩌구 하는 것 보니 모듈 관련된 내용인 것 같네요.
일반 스크립트와 모듈의 차이
여러가지 차이가 있지만, 가장 큰 특징으로는 “자신만의 스코프를 가진다”는 것입니다. 스코프란, 영역-범위를 의미하죠! 아래 예시를 볼게요.
다른 모듈에 위치한 값을 참조하려고 합니다.
참조 에러가 발생했네요.
각 모듈은 자신만의 스코프를 갖고 있기 때문에, 한 스크립트에서 다른 모듈 내부에 정의된 변수/함수에 접근할 수 없습니다. 공개하고 싶다면 import와 export 구문을 사용해야만 하니까요.
이렇게 스코프가 구분되어 있기 때문에, 전역변수를 사용하지 않을 수 있다는 장점이 있습니다. var 키워드는 함수에서 정의된 변수가 아니라면 모두 전역변수로 존재합니다.
if문에서 var 로 변수를 선언하면, 블록스코프인 조건문이나 반복문이 종료가 되어도 해당 변수는 여전히 남아있게 됩니다.
하지만 모듈을 사용하면 파일 자체의 독자적인 스코프 때문에 프로그램 전체에 영향을 주는 전역변수의 사용을 억제할 수 있게 되겠죠!
전역변수철머 어디서나 참조할 수 있고 또 어디서 어떻게 변경될 수 있는 변수가 프로그램의 안정성에 도움이 되지는 않겠죠.
모듈 번들러
하지만 실제로 ES6 모듈은 IE 같은 구형 브라우저에서는 동작하지 않습니다. 또 트랜스파일링이나 번들링 때문에 일반적으로는 웹팩같은 모듈 번들러를 사용하죠.
모듈 번들러는 여러개의 파일로 분리된 각 모듈을 번들링, 즉 하나로 묶어준다는 의미입니다. 배포를 위해 build를 실행하면, 여러개의 모듈로 존재하던 파일을 하나의 단일 자바스크립트 파일로 번들링해줍니다.
개별적인 리소스에 대해 각각 요청을 하는것이 아니라, 하나의 통합된 리소스를 요청하기 때문에 네트워크 비용을 절감할 수 있죠.
결론
- 모듈 번들러 없이 모듈을 사용하려면 html 태그의 src 속성에 type = “module” 을 명시해주면 된다.
- 하지만 일반적으로는 트랜스파일링, 번들링 때문에 모듈 번들러를 사용한다. (그럼 type=module 로 사용하면 각 리소스에 대해서 매번 요청을 하는지 궁금하네요. 이건 개인적으로 알아볼게요)
- 모듈의 장점으로는 유지보수성 뿐만 아니라, 전역변수의 사용이 억제가 된다는 점이 있다. 꿀팁~
'JavaScript > JavaScript' 카테고리의 다른 글
[JavaScript] 이벤트 위임, 이벤트 전파, e.target & e.currentTarget 차이 (2) | 2023.01.18 |
---|---|
[JavaScript] 비동기 흐름 제어 -2 : async / await 활용하기 (0) | 2022.07.28 |
[JavaScript] 비동기 흐름 제어 -1 : 콜백함수, promise (0) | 2022.07.28 |
[JavaScript] 클래스간의 상속 (프로토타입 상속) (0) | 2022.07.25 |
[JavaScript] 프로토타입 체인 (0) | 2022.07.25 |