eatthefrog
모던 자바스크립트 모듈 본문
ES6 모듈 VS 일반 스크립트 (Script)

주요 특징
- 변수 범위 (Scoped to module):
- 모듈 내부의 변수는 기본적으로 모듈 범위(scope) 내에만 접근 가능합니다.
- 전역(global) 스코프에 영향을 주지 않습니다.
- 기본 모드 (Default mode):
- ES6 모듈은 기본적으로 **엄격 모드(Strict mode)**에서 실행됩니다.
- 오류를 방지하고 안전한 코드를 작성하도록 돕습니다.
- this 키워드:
- 최상위 레벨에서의 this는 undefined로 설정됩니다. (전역 객체를 참조하지 않음)
- import와 export 지원:
- 모듈에서 데이터를 내보내(export)고 가져오기(import)가 가능합니다.
사용법
(1) 내보내기 (Export)
- Named Export: 이름이 있는 변수, 함수, 객체 등을 내보냄.
// math.js
export function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
export const pi = 3.14;
- Default Export: 기본 내보내기로 하나의 값을 지정.
// utils.js
export default function greet(name) {
return `Hello, ${name}`;
}
(2) 가져오기 (Import)
- Named Import: 내보낸 이름과 동일한 이름으로 가져옴.
import { rand, pi } from './math.js';
console.log(rand(1, 10)); // 랜덤 숫자
console.log(pi); // 3.14
- Default Import: 기본으로 내보낸 값을 가져올 때.
import greet from './utils.js';
console.log(greet('NewJeans')); // "Hello, NewJeans"
- 모두 가져오기:
import * as MathUtils from './math.js';
console.log(MathUtils.rand(1, 10));
console.log(MathUtils.pi);

왜쓰는가?
=> ES6 모듈로 전역 오염 방지
전역 네임스페이스 오염은
모든 스크립트가 같은 전역 스코프를 공유
할 때 발생합니다. 하나의 파일에서 정의된 변수, 함수, 객체가 의도치 않게 다른 파일이나 스크립트에 영향을 줄 수 있습니다.
ES6 모듈을 사용하면 각 파일(모듈)은
독립된 스코프
를 가집니다. 전역 변수와 함수가 기본적으로 외부에 노출되지 않으므로, 충돌을 방지할 수 있습니다.
// script1.js
export const appName = "WeatherApp";
export function logAppName() {
console.log(`App: ${appName}`);
}
// script2.js
import { appName, logAppName } from './script1.js';
var appName = "TodoApp"; // 같은 이름의 전역 변수이지만, 이 변수는 script2.js 내부에서만 유효
logAppName(); // 출력: App: WeatherApp
결과:
- appName과 logAppName은 모듈 스코프 안에 캡슐화되어 전역 스코프를 오염시키지 않습니다.
- import로 가져온 appName은 Script1.js의 appName입니다.
- var appName = "TodoApp";은 script2.js의 로컬 변수로, logAppName() 함수와는 전혀 관련이 없습니다.
- 다른 파일에서 동일한 변수 이름(appName)을 사용해도 문제가 없습니다.
다른 구체적인 예: 라이브러리 충돌 방지
문제 상황: 여러 라이브러리가 같은 전역 이름 사용
<script src="library1.js"></script> <!-- library1.js에서 `utils`를 정의 -->
<script src="library2.js"></script> <!-- library2.js에서도 `utils`를 정의 -->
<script>
// library1.js와 library2.js의 `utils`가 충돌
utils.doSomething(); // 어떤 utils가 호출될지 불확실
</script>
ES6 모듈 사용 시 :
// library1.js
export const utils = {
doSomething: () => console.log("Library1 Utils"),
};
// library2.js
export const utils = {
doSomething: () => console.log("Library2 Utils"),
};
// app.js
import { utils as utils1 } from './library1.js';
import { utils as utils2 } from './library2.js';
utils1.doSomething(); // 출력: Library1 Utils
utils2.doSomething(); // 출력: Library2 Utils
결과:
- utils 객체를 독립적으로 가져와 이름 충돌 없이 사용 가능합니다.
- as 키워드를 사용해 이름을 바꿔 충돌을 피할 수 있습니다.
😉Bonus
자바스크립트의 as 문법
as는 주로 모듈 가져오기(import/export) 또는 TypeScript에서 사용됩니다. 순수 JavaScript에서는 as 키워드 자체는 존재하지 않지만, ES6 모듈을 사용할 때 import와 함께 별칭(alias)을 지정하는 데 사용됩니다.
1. ES6 모듈에서의 as 사용
모듈에서 특정 이름으로 내보낸(export) 값을 다른 이름으로 가져오고 싶을 때 사용합니다.
// module.js
export const myFunction = () => console.log("Hello, world!");
export const anotherFunction = () => console.log("Another function");
// main.js
import { myFunction as newFunctionName } from './module.js';
newFunctionName(); // Hello, world!
위 예시에서 myFunction을 newFunctionName이라는 이름으로 가져왔습니다. 이는 이름 충돌을 방지하거나 더 의미 있는 이름을 사용할 때 유용합니다.
모듈 가져오기가 단순 복사가 아닌 이유
모듈 시스템이 단순히 코드를 복사해 오는 방식이 아니라, 참조(reference)를 통해 값을 관리하기 때문입니다.
1. 모듈은 기본적으로 싱글톤(singleton)
모듈은 한 번 로드되면 해당 모듈의 상태가 공유됩니다. 즉, 동일한 모듈을 여러 곳에서 가져와도 모듈의 상태는 한 곳에서 관리됩니다.
// counter.js
let count = 0;
export const increment = () => count++;
export const getCount = () => count;
// main.js
import { increment, getCount } from './counter.js';
increment();
console.log(getCount()); // 1
increment();
console.log(getCount()); // 2
위 예제에서 increment 함수가 count 값을 변경하면, 다른 파일에서 가져온 getCount를 호출할 때도 변경된 값이 유지됩니다. 이처럼 모듈은 단순 복사본이 아니라 원본 상태를 참조합니다.
2. 모듈 캐싱(module caching)
모듈(공유되는 데이터) 은 한 번 로드되면 캐시에 저장되어, 이후 같은 모듈을 가져올 때는 반복해서 새로 가져오지 않고, 이미 로드된 캐시된 버전을 재사용합니다. (변경사항들이 축적됨)
// module.js
console.log("Module loaded");
export const sayHello = () => console.log("Hello");
// main.js
import { sayHello } from './module.js';
import { sayHello as sayHiAgain } from './module.js';
// 출력
// Module loaded
sayHello(); // Hello
sayHiAgain(); // Hello
모듈 로드 시 console.log("Module loaded")가 한 번만 출력되는 이유는, 모듈이 한 번 로드된 후에는 캐시된 버전을 사용하기 때문입니다.
3. 변수 상태 공유와 동기화
모듈 내의 변수나 함수는 원본 상태를 공유하며, 한 번 데이터를 바꾸면 모두가 그 변화를 관찰할 수 있습니다.
// shared.js
export const sharedArray = [];
// moduleA.js
import { sharedArray } from './shared.js';
sharedArray.push('A');
// moduleB.js
import { sharedArray } from './shared.js';
sharedArray.push('B');
// main.js
import './moduleA.js';
import './moduleB.js';
import { sharedArray } from './shared.js';
console.log(sharedArray); // ['A', 'B']
모든 파일에서 동일한 sharedArray를 참조하기 때문에, 어떤 모듈에서 값을 추가하거나 수정하면 전체에 영향을 미칩니다.
요약
- as는 주로 모듈 가져오기에서 별칭(alias)을 지정하거나 TypeScript에서 타입 단언에 사용됩니다.
- 모듈 가져오기는 단순 복사가 아닌 참조를 통해 관리되며, 모듈은 싱글톤으로 동작하고 상태를 공유합니다.
- 모듈 캐싱과 상태 공유 덕분에 효율적으로 동기화된 데이터를 관리할 수 있습니다.
'프론트엔드 노트' 카테고리의 다른 글
| 모던 자바스크립트_Module Pattern(import,export) (1) | 2025.01.02 |
|---|---|
| 모던 자바스크립트 모듈 Top-Level await (ES2022) (0) | 2025.01.02 |
| CSS) 자식박스를 가운데 정렬시키기 위해서 부모 박스에 flex box 설정하는 이유 (1) | 2025.01.01 |
| 모던 자바스크립트_ES6 모듈 VS 스크립트 2탄(파일로딩,다운로드) (1) | 2024.12.31 |
| 모던 자바스크립트 모듈,클래스,함수 정리 (0) | 2024.12.31 |