보통 일반적인 클래스사용시
JS에서는 클래스명을 export default로 보내어
new 클래스명(...); 명령어로 인스턴스화해서 사용하는 것이 일반적이다.
하지만 싱글턴패턴을 구현하려면, 어떻게 해야할까?
구현 방법
다른 언어에서도 사용가능한 가장 보편적인 구현법은
클래스선언의 생성자에서 단일 인스턴스를 기억하고있다가
만약 기존생성된 인스턴스가 존재하면
그것을 반환하는식으로 구현한다.
JS에서도 위와같이 클래스 방식을 쓰기도하고,
좀 더 간략한 표현을위해 클로저(Closure)를 이용하여 구현하기도 한다.
하지만 JS의 모듈캐시의 특성을 이용한다면 훨씬 간단명료하게 구현할 수 있다.
// mySingleton.js
class MySingleton {
constructor() {
this.value = 0;
}
setValue(value) {
this.value = value;
}
}
const instance = new MySingleton();
export default instance;
// someFile.js
import mySingleton from "./mySingleton.js";
mySingleton.setValue(5);
console.log(mySingleton.value); // 5
// anotherFile.js
import mySingleton from "./mySingleton.js";
console.log(mySingleton.value); // 5
너무 간단해서 놀라시거나 의아해 하실수도 있지만,
보시는 바와 같이 JS에서는 노드에서실행하든, Browser에서실행하든
인스턴스화 한 것을 리턴해주고 import하기만하면 싱글턴 인스턴스가 보장된다.
someFile에서 someMethod()를 통해 바꾼 객체의 상태값이 유지된채로
anotherFile에서 import할때 그 상태 그대로 넘어온다.
이유 : JS실행환경(노드, 브라우저)에서 제공하는 모듈시스템의 모듈 캐시 기능이 작동하기 때문이다.
JS에서는 모듈시스템(CJS, ESM)을 이용하여 다른 파일의 코드를 가져서 쓰게 되는데(import, require)
이 모듈 시스템을 이용하여 가져오는 값은
'모듈 캐시' 기능을 통해 캐싱이 되며,
2번째 이후의 호출에서는 그 코드를 실행시키지않고 캐싱된 데이터를사용한다.
따라서,
여러번 호출(import, require)을 하더라도
한 페이지를 로딩하는 데 있어서 딱 한번만 실행되는 것이 보장된다.
즉 mySingleton.js 코드는 someFile.js와 anotherFile.js중 먼저실행되는 코드부분에서만 단 한번실행되고,
객체의 상태값까지포함해서 저장/유지 하고 있다가
재차 import시 동일한 해당 객체에 접근할수있게끔해준다.
JS는
1. node환경 이나,
2. 브라우저환경(ECMA Script Modules)에서
실행되게되는데,
각 환경에서의 모듈시스템은 아래와 같다.
1. Node.js : CommonJS(CJS), ECMA Script Modules(ESM)
2. 브라우저 : ECMA Script Modules
CJS와 ESM 모두 모듈 캐시를 사용하는 것이 기본동작이기때문에
두 실행환경 모두에서 '모듈 캐시'가 보장된다.
모듈 캐시가 작동하는것이 일반적인/정상적인 환경이고,
의식적으로 비정상적인환경을 만들려고 상당히 노력을 한 게 아닌 정상적인환경에서는 항상 모듈캐시가 작동한다.
localStorage
sessionStroage
cookies
localStorage와 sessionStorage
쿠키
IndexedDB
싱글턴 패턴에서 시작하여, 모듈시스템, 모듈캐시, 스토리지에 대해 알아보았다.
스토리지중에서는 대용량 인스턴스를 담기에는 IndexedDB가 상당히 좋았다.
저용량 간소한 데이터를 담기에는 웹스토리지(localStorage, sessionStorage)에 직렬화하여 사용하는 것이 좋다는 것을 알아보았다.
다음에는 IndexedDB의 구현에 대해 간단히 알아보면 더 좋을 거 같다.
https://gist.github.com/dmnsgn/4a6ad76de1b5928f13f68f406c70bb09
https://dmnsgn.medium.com/singleton-pattern-in-es6-d2d021d150ae