JavaScript 모듈 시스템은 코드의 모듈화를 통해 재사용성, 유지보수성, 가독성을 향상시키는 데 도움을 줍니다. ES6(ECMAScript 2015)부터 도입된 import
와 export
를 사용한 모듈 시스템은 표준화된 방법으로 JavaScript 모듈을 정의하고 사용하는 기능을 제공합니다. 이 문서에서는 JavaScript의 모듈 시스템을 매우 상세히 설명합니다.
1. 모듈 기본 개념
JavaScript 모듈은 코드의 재사용성과 캡슐화를 위한 독립적인 단위입니다. 각 모듈은 별도의 파일에 정의되며, 다른 모듈에서 import
와 export
를 통해 서로 상호작용할 수 있습니다.
2. export
– 모듈 내보내기
모듈 내보내기(export
)는 모듈이 다른 모듈에서 사용할 수 있는 변수, 함수, 클래스 등을 공개하는 방법입니다.
2.1 내보내기 방식
명명된 내보내기(Named Exports)
명명된 내보내기를 사용하면 모듈에서 여러 개의 변수를, 함수, 클래스를 내보낼 수 있습니다.
// lib.js
export const pi = 3.14;
export function add(x, y) {
return x + y;
}
export class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
기본 내보내기(Default Export)
기본 내보내기는 모듈에서 하나의 기본값만 내보낼 수 있습니다. 일반적으로 객체, 함수, 클래스 등을 내보낼 때 사용합니다.
// lib.js
const defaultValue = "Default Export";
export default defaultValue;
혼합 내보내기
명명된 내보내기와 기본 내보내기를 함께 사용할 수 있습니다.
// lib.js
export const pi = 3.14;
export function add(x, y) {
return x + y;
}
const defaultValue = "Default Export";
export default defaultValue;
3. import
– 모듈 가져오기
import
는 다른 모듈에서 내보낸 기능을 가져오는 방법입니다.
3.1 명명된 가져오기
모듈에서 명명된 내보내기를 가져오는 방법입니다.
// main.js
import { pi, add, Person } from './lib.js';
console.log(pi); // 3.14
console.log(add(2, 3)); // 5
const person = new Person('Alice');
person.greet(); // Hello, my name is Alice
3.2 기본 가져오기
모듈에서 기본 내보내기를 가져오는 방법입니다.
// main.js
import defaultValue from './lib.js';
console.log(defaultValue); // Default Export
3.3 명명된 가져오기와 기본 가져오기 함께 사용
명명된 내보내기와 기본 내보내기를 함께 가져올 수 있습니다.
// lib.js
const defaultValue = "Default Export";
export default defaultValue;
export const pi = 3.14;
export function add(x, y) {
return x + y;
}
// main.js
import defaultValue, { pi, add } from './lib.js';
console.log(defaultValue); // Default Export
console.log(pi); // 3.14
console.log(add(2, 3)); // 5
3.4 전체 모듈 가져오기
모듈 전체를 하나의 객체로 가져올 수 있습니다.
// main.js
import * as lib from './lib.js';
console.log(lib.pi); // 3.14
console.log(lib.add(2, 3)); // 5
console.log(lib.default); // Default Export
4. 모듈 로딩 시점
모듈은 기본적으로 동기적으로 로드됩니다. 즉, 모듈이 로드되기 전까지 코드 실행이 멈추며, 로드된 후에야 코드가 실행됩니다.
5. 모듈화된 코드의 장점
- 코드의 캡슐화: 모듈은 외부와 내부를 명확히 구분하여 코드의 가독성을 높입니다.
- 재사용성: 모듈화된 코드는 다른 프로젝트나 파일에서도 재사용할 수 있습니다.
- 의존성 관리: 모듈은 명확하게 의존성을 정의하므로, 코드 관리가 용이합니다.
- 테스트 용이성: 모듈 단위로 코드를 테스트하기 쉬워집니다.
6. 모듈의 동작 방식
모듈은 JavaScript의 실행 환경에 따라 다르게 동작할 수 있습니다. 브라우저와 Node.js의 모듈 처리 방식은 다음과 같습니다.
6.1 브라우저에서의 모듈
브라우저에서는 type="module"
을 사용하여 <script>
태그를 통해 모듈을 로드합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Module Example</title>
</head>
<body>
<script type="module">
import { pi, add } from './lib.js';
console.log(pi); // 3.14
console.log(add(2, 3)); // 5
</script>
</body>
</html>
6.2 Node.js에서의 모듈
Node.js는 CommonJS 모듈 시스템을 사용하지만, 최근에는 ES 모듈을 지원합니다. ES 모듈을 사용하려면 파일 확장자를 .mjs
로 설정하거나 package.json
에서 "type": "module"
을 설정합니다.
// lib.mjs
export const pi = 3.14;
export function add(x, y) {
return x + y;
}
// main.mjs
import { pi, add } from './lib.mjs';
console.log(pi); // 3.14
console.log(add(2, 3)); // 5
// package.json
{
"type": "module"
}
7. 모듈의 동적 import
ES6 모듈에서는 import()
함수를 사용하여 모듈을 동적으로 로드할 수 있습니다. 이는 코드 분할 및 지연 로딩을 가능하게 합니다.
// main.js
async function loadModule() {
const module = await import('./lib.js');
console.log(module.pi); // 3.14
console.log(module.add(2, 3)); // 5
}
loadModule();
8. 사이드 이펙트와 모듈
모듈을 임포트할 때, 사이드 이펙트(즉, 모듈이 실행되는 시점에 발생하는 코드 실행)를 방지하거나 관리하기 위해 의도적으로 import
할 수 있습니다.
// lib.js
console.log('This will execute when the module is imported');
export const pi = 3.14;
// main.js
import './lib.js'; // 사이드 이펙트 발생
결론
JavaScript의 모듈 시스템은 코드의 구조화와 관리에 많은 이점을 제공합니다. import
와 export
를 통해 모듈을 정의하고, 재사용 가능한 코드로 분리할 수 있습니다. ES6부터 도입된 표준 모듈 시스템은 다양한 상황에서 코드의 가독성과 유지보수성을 높이는 데 큰 도움을 줍니다. 모듈을 효과적으로 사용하면 더 깔끔하고 관리하기 쉬운 코드를 작성할 수 있습니다.