728x90
JavaScript 의 모듈 패턴 (Module Pattern)
- 모듈 패턴 : 정보 은닉 (Encapsulation) 을 활용해 코드의 구조를 정리하는 디자인 패턴 중 하나
- 전역 변수 오염 방지 : 네임스페이스 충돌 방지
- 데이터를 안전하게 보호하여 필요한 부분만 외부에 노출 가능 : 캡슐화(Encapsulation)
- 코드 재사용성 용이, 유지보수 용
- ES6 의 모듈 (import/export) 등장 전까지는 주로 IIFE (즉시 실행 함수 표현) 을 이용해 모듈화하는 방식 사용
- 예시
const ModuleTest = (function () {
// private 변수 및 함수
let privateVar = "private 변수 : 외부에서 접근 불가";
function privateFunction() {
console.log("private 함수 : 외부에서 접근 불가");
}
const publicVar = "public 변수 : 외부에서 접근 가능";
// 공개할 메서드 및 변수
return {
publicVar: publicVar,
publicFunction: function () {
console.log("public 함수 : 외부에서 접근 가능");
console.log("privateVar 출력 : " + privateVar);
},
};
})();
console.log(ModuleTest.publicVar); // public 변수 : 외부에서 접근 가능
ModuleTest.publicFunction(); // public 함수 : 외부에서 접근 가능
// privateVar 출력 : private 변수 : 외부에서 접근 불가
console.log(ModuleTest.privateVar); // undefined
ModuleTest.privateFunction(); // 에러 발생 (외부 접근 불가)
- 즉시 실행 함수 표현 (IIFE) 를 활용하여 private 데이터 보호
- return 문을 통해 외부에 공개할 속성 및 메서드만 노출
즉시 실행 함수 표현식 (IIFE : Immediately Invoked Function Expression)
- 즉시 실행 함수 : 정의되자마자 즉시 실행되는 함수로, 함수를 선언하고 그 즉시 해당 함수를 호출하는 방식으로 작동
- 정의되자마자 즉시 실행
- 전역 네임스페이스 오염 방지
- 모듈 패턴에서 캡슐화 용도로 사용
IIFE 기본 문법
(function () {
console.log("즉시 실행되는 함수");
})();
- `function () { ... }` : 익명 함수
- `()` 로 감싸는 이유 : 함수 선언과 실행을 동시에 하기 위해
- 마지막 `()` : 즉시 실행을 의미
만약 `()` 로 감싸지 않으면 SyntaxError 발생 : 함수 선언문은 이름 필요
IIFE 활용 방법
- 기본 IIFE (익명 함수)
(function () {
console.log("기본 IIFE 실행");
})();
- 화살표 함수 사용
(() => {
console.log("화살표 함수 IIFE 실행");
})();
- 매개변수가 있는 IIFE
(function (name) {
console.log(`Hello, ${name}!`);
})("Cyyy");
- 반환값이 있는 IIFE
const message = (function () {
return "즉시 반환";
})();
console.log(message); // 즉시 반환
IIFE 사용 이유
(function () {
let count = 0; // private 변수
console.log("초기 값:", count);
})();
console.log(count); // ReferenceError: count is not defined
- 전역 변수 오염 방지 : IIFE 는 변수를 함수 내부에서만 사용하도록 제한 가능
- count 변수는 IIFE 내부에 있으므로 외부에서 접근 불가 → 전역 변수 오염 방지
const CounterModule = (function () {
let count = 0;
function increment() {
count++;
console.log("Count:", count);
}
return {
increment,
};
})();
CounterModule.increment(); // Count: 1
CounterModule.increment(); // Count: 2
console.log(CounterModule.count); // undefined (private 변수 보호됨)
- 모듈 패턴에서 사용 (정보 은닉)
- count 변수는 외부에서 직접 접근 불가, `increment()` 메서드 통해서만 조작 가능
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// 결과: 3, 3, 3 (의도한 0, 1, 2가 아님)
// setTimeout 은 비동기 함수로, 루프가 끝난 후 i 값이 3이 된 상태에서 실행
for (var i = 0; i < 3; i++) {
(function (index) {
setTimeout(() => console.log(index), 1000);
})(i);
}
// 결과: 0, 1, 2 (의도한 대로 실행)
- 비동기 코드에서 사용
- IIFE 를 활용 시 각 i의 값을 개별적으로 저장하는 클로저 (Closure) 역할 수행
ES6 모듈 (ES6 Module)
- ES6 모듈 : JavaScript 에 공식적으로 도입된 모듈 시스템으로, `import` 와 `export` 키워드를 활용해 코드 모듈화 가능
- 전역 네임스페이스 오염 방지
- 코드 재사용 용이
- 선택적으로 import 하여 사용 가능
ES6 모듈 기본 문법
- `export` : 모듈에서 코드 내보내기
// math.js
export const pi = 3.14159;
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
- `import` : 모듈에서 코드 가져오기
// main.js
import { pi, add, multiply } from "./math.js";
console.log(pi); // 3.14159
console.log(add(2, 3)); // 5
console.log(multiply(4, 5)); // 20
ES6 모듈 활용
- `export default` : 모듈에서 하나의 기본 값 내보낼 때 사용, `import` 시 이름을 자유롭게 정할 수 있음
// logger.js
export default function log(message) {
console.log(`[LOG]: ${message}`);
}
// app.js
import log from "./logger.js"; // import할 때 {} 없이 사용
log("Hello, world!"); // [LOG]: Hello, world!
- `import * as` : `export` 된 것을 한 객체로 가져올 수 있음
// main.js
import * as math from "./math.js";
console.log(math.pi); // 3.14159
console.log(math.add(10, 20)); // 30
console.log(math.multiply(5, 6)); // 30
- `import { as }` : 별칭 (Alias) 를 이용해 `import`
// main.js
import { add as sum, multiply as product } from "./math.js";
console.log(sum(5, 5)); // 10
console.log(product(3, 4)); // 12
브라우저에서 ES6 모듈 사용
- 브라우저에서 `<script>` 태그 내에서 모듈을 사용하기 위해서는 `type="module"` 추가 필요
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>ES6 Modules</title>
</head>
<body>
<script type="module" src="main.js"></script>
</body>
</html>
IIFE 모듈 패턴 vs ES6 모듈
- 모듈 패턴은 ES6 모듈이 등장하기 전에 널리 사용, 현재는 ES6 모듈이 표준
- 브라우저 환경에서 모듈 번들러 없이 사용할 경우 모듈 패턴이 유용할 수 있음
| 모듈 패턴 | ES6 모듈 | |
| 사용 방식 | IIFE 와 객체 반환 | `import`, `export` 사용 |
| private 변수 보호 | 가능 | 불가능 (export 시 외부에서 접근 가능) |
| 브라우저 지원 | 모든 환경 | 모듈 지원 환경에서만 가능 |
| 유지보수성 | 비교적 제한적 | 더 구조적인 관리 가능 |
JavaScript의 모듈 패턴은 코드의 캡슐화와 전역 네임스페이스 오염 방지를 위해 유용한 패턴이지만,
ES6 모듈의 등장으로 기본적인 모듈 시스템이 제공되므로 최신 프로젝트에서는 ES6 모듈 활용하는 것이 적절.
728x90
'JavaScript' 카테고리의 다른 글
| [JavaScript] 프로토타입 (Prototype) 성능 최적화 (1) | 2025.03.14 |
|---|---|
| [JavaScript] 프로토타입 (Prototype) 활용 방법 (0) | 2025.03.14 |
| [JavaScript] 프로토타입 (Prototype) 기본 개념 (1) | 2025.03.13 |
| [JavaScript] 자바스크립트 ES6 문법 정리 (1) | 2025.03.13 |
| [JavaScript] 익명 함수, 화살표 함수 (1) | 2025.03.07 |