💫

[JS] 싱글톤 패턴 (Singleton Pattern)


싱글톤 패턴?

싱글톤 패턴은 전체 시스템에서 클래스에 대한 인스턴스가 하나만 존재하도록 보장하는 '객체 생성' 패턴이다.

싱글톤 패턴을 사용하면 고정된 메모리 영역에 인스턴스 하나만을 사용하기 때문에 메모리 낭비를 방지할 수 있다. 또한, 싱글톤으로 만들어진 인스턴스는 전역이기 때문에 다른 클래스의 인스턴스들이 데이터를 공유하기 쉬워진다.

하지만, 싱글톤 인스턴스가 너무 많은 일을 하거나 많은 데이터를 공유한다면, 시스템의 결합도가 높아지기 때문에 주의해야 한다. 결합도가 높아지면 유지보수가 어려워진다.

구현

싱글톤을 구현할 수 있는 방법은 다양하다.

단순 전역 변수에 객체 리터럴로 생성하는 것도 싱글톤이라고 할 수 있다. 하지만, 전역 변수를 사용하기 보다는 클래스 자신이 자기의 유일한 인스턴스로 접근하는 방법을 자체적으로 관리하게 하는 것이 더 좋은 방법이다. 이 방법을 통해 클래스 외부에서는 인스턴스를 생성하지 못하게 하고, 내부에는 단 하나의 인스턴스를 생성해 외부에서 그 인스턴스에 접근할 수 있는 방법을 제공할 수 있다.

싱글톤의 구현은 보통 다음 세 가지를 지킨다.

  • 외부 클래스로부터 인스턴스 생성을 차단한다.
  • 인스턴스에 직접 접근하는 것을 차단한다.
  • 인스턴스에 대한 접점을 제공한다.

클로저를 이용한 싱글톤

클로저를 사용해 인스턴스를 숨기는 방법이다.

1let Singleton = (function() {
2 let instance;
3 let 비밀 = "나는 숨겨진 변수";
4 function init() {
5 return {
6 foo: function() {
7 console.log(비밀);
8 }
9 }
10 }
11 return {
12 getInstance: function() {
13 if(!instance) instance = init();
14 return instance;
15 }
16 }
17})();
18
19let a = Singleton.getInstance();
20let b = Singleton.getInstance();
21console.log(a === b);
22// -> true

instancegetInstance의 외부 렉시컬 환경에 숨겨져 있기 때문에 직접 접근할 수 없다. init의 리턴 값에 없는 변수 또한 모두 숨길 수 있다.

ES10(ES2019)

ES10부터는 클래스에 #를 사용해 private 클래스 필드를 선언할 수 있게 됐다. 따라서 다음과 같은 싱글톤 구현이 가능해졌다.

1class Singleton {
2 static #instance;
3 constructor() {
4 if(Singleton.#instance) return Singleton.#instance;
5 this.phrase = "Hello World!";
6 Singleton.#instance = this;
7 }
8}
9
10let a = new Singleton();
11let b = new Singleton();
12console.log(a === b);
13// -> true

참조:
https://readystory.tistory.com/116
https://heecheolman.tistory.com/40
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes/Private_class_fields