☝ 이번 시간에는 JS 디자인 패턴 중 하나인, 모듈 패턴에 대해 알아보자!
1. 모듈이란?
- 코드의 일부를 독립된 형태로 분리한 걸 말한다.
- 모듈은 하나의 클래스로 구성되거나 특정 목적을 가진 복수의 함수(라이브러리 형태)로 구성된다.
export
,import
지시자를 사용해 모듈을 내보내거나 불러올 수 있는데, 아래는 그 예시이다.print()
는export
를 사용해 외부로 내보낼 수 있다.
// 📁 test.js
export function print() {
console.log('hello!');
}
export
된print()
는import
를 사용해 불러올 수 있다.
// 📁 main.js
import { print } from './test.js';
print(); // hello
2. 모듈 패턴?
1) 클로저와 객체리터럴
- 모듈 패턴은 외부에서 클래스의 상태나 동작에 접근하지 못하도록 캡슐화한다.
- 이는 곧 public, private과 같은 접근 권한 설정이 가능함을 뜻한다.
- 해당 패턴을 사용해 접근 권한 설정을 하면 내부 로직이 전역 스코프로 유출되는 걸 막을 수 있으며, 함수명이 같아도 충돌이 발생하지 않는다.
🤔 어라랏? 그런데, 자바스크립트에서는 private가 없지 않나? 어떻게 권한을 설정할까?
(1) 클로저 사용하기
🙂 클로저를 사용하면 권한 설정이 가능하다!
- 클로저는 중첩 함수에서 외부 함수가 종료되어도 내부 함수에서 외부 함수에 접근할 수 있는 환경을 말한다.
- 클로저를 사용하게 되면, 바깥에서 내부함수를 호출할 수 없기에 private 설정이 가능하다.
- 이 말은 상태와 동작을 캡슐화시켜 private로 만들 수 있다는 것이다!
- 아래 예시를 보면
inner
는 private으로 설정되여, 외부에서 바로 호출할 수 없다.
function outer(){
const inner = function() {
console.log('hello')
}
inner();
}
inner(); // inner is not defined
(2) 객체 리터럴 방식 사용하기
- 클로저 방식을 이용해 private한 함수를 선언할 때, 객체 리터럴 방식을 쓸 수 있다.
- 여기서 객체 리터럴이란, 생성자 함수(
new
)로 객체를 생성치 않고 객체의 속성과 값을 바로 적는 것이다. - 아래는 객체 리터럴 방식을 사용해 private
inner()
를 만든 모습이다.
const outer = {
inner() {
console.log('hello');
}
}
outer.inner(); // hello
inner(); // error: inner() is undefined
2) 모듈 패턴의 다른 구현 방법
(1) IIFE로 구현하기
- IIFE(Immediately Invoked Function Expression)는 즉시실행함수라고 불리며, 이름 그대로 함수가 정의되자마자 즉시 실행된다.
- 형태는 아래와 같이 함수가
()
로 감싸져 있으며, 정의되자마자 “여기”부분의 코드가 바로 실행된다.
(function() {
// 여기
})();
- 아래 예시는 콘솔을 출력하는 함수를 즉시실행함수로 선언한 모습이다.
- 예상했다시피 함수를 정의하자마자 콘솔이 출력되었다.
(function () {
const consolePrint = () => {
console.log('print 내부 open');
}
consolePrint();
})();
- 즉시실행함수 내부의
consolePrint()
를 전역에서 호출하면 에러가 발생한다.
consolePrint();
🧐 왜 모듈패턴에서 IIFE를 쓸까?
- 앞서 살펴봤듯이 IIFE 내부에 선언된 함수는 외부에서 호출할 수 없다.
- 이는 특정 동작을 private로 정의할 수 있음을 의미하여, 또한 IIFE는 선언과 동시에 실행이 되므로 동일한 함수명을 만들어도 충돌이 발생하지 않는 장점이 있다.
(function () {
const consolePrint = () => {
console.log('print 내부 open1');
}
consolePrint();
})();
(function () {
const consolePrint = () => {
console.log('print 내부 open2');
}
consolePrint();
})();
🤔 만약 외부에서 IIFE 내부의 변수에 접근하려고 할 때 코드를 어떻게 구성해야할까?
- IIFE에서 내부 변수에 접근할 수 있는 값을 리턴해주면 된다.
lunch.getFood
를 하면 IIFE 내부의 food 변수에 접근할 수 있다.
const lunch = (() => {
const food = ['딸기', '바나나', '오렌지'];
return { getFood: food };
})();
console.log(lunch.getFood); // ['딸기', '바나나', '오렌지']
(2) ES2019, Class와 #으로 구현하기
- JS Class의 속성은 public이므로, 외부에서 값을 읽거나 수정할 수 있다.
- 그러나 ES2019에서는
#
이 추가되면서 class에서 private 설정이 가능해졌다. - private로 설정하고 싶은 변수 앞에
#
을 붙이면 외부에서 해당값에 접근할 수 없게 된다.
class Food {
#foodList = ['orange', 'apple'];
get getFood() {
return this.#foodList;
}
}
const food = new Food();
console.log(food.getFood); // ['orange', 'apple']
console.log(food.#foodList); // 접근X
반응형
'개발 기술 > 개발 이야기' 카테고리의 다른 글
indexedDB에 대해 알아보자! (0) | 2022.01.24 |
---|---|
JS 클린코드 <변수편> (0) | 2022.01.15 |
이중배열(2d array)에서 최고, 최저값 찾기 (0) | 2022.01.02 |
[JS] 호이스팅(hoisting) (0) | 2021.12.21 |
디자인 패턴1, 옵저버란? (0) | 2021.12.08 |
댓글