kakasoo

싱글턴(Singleton) 패턴이란? 본문

프로그래밍/TypeScript

싱글턴(Singleton) 패턴이란?

카카수(kakasoo) 2023. 1. 13. 01:18
반응형

싱글턴 패턴은 한 클래스의 인스턴스가 하나만 존재하도록 강제하는 패턴이다.

이런 패턴은 동일한 기능을 하는 여러 인스턴스가 생성되는 것을 막아 메모리 낭비를 줄이기 위해 사용된다.

간혹 우리가 데스크탑의 파일을 여러 번 클릭할 때, 파일이 한 번만 열리는 경우가 있는데 이런 게 싱글턴이다.

다른 객체지향 언어에서는 이걸 구현하기 위해 여러 줄의 코드를 작성하지만, node.js에서는 한 줄로도 된다.

 

export default new (class singleton {})();

node.js에서는 이처럼, 파일에서 다른 파일로 내보낼 때 이미 생성된 인스턴스를 내보내기만 하면 된다.

이러면 어느 파일에서 부르든 동일한 객체를 가져오기 때문에 싱글턴과 동일한 효과를 낼 수 있다.

하지만 자바스크립트는 클래스가 아닌 프로토타입 기반의 언어이다.

그래서 엄밀히 말해 이 방법은 완벽하지 않다.

 

function Person(name){
    this.name = name;
}

// new 키워드는 객체를 생성하며, 함수 역시 객체기 때문에 아래는 각각의 객체 (=함수)를 생성하는 코드가 된다.
const kakasoo1 = new Person('kakasoo1');
const kakasoo2 = new Person('kakasoo2');

console.log(Person.prototype === kakasoo1._proto_);   //true
console.log(Person.prototype.constructor === Person); //true

인스턴스 객체는 자신을 생성한 함수 객체로 이어질 수 있는, _proto_ 라는 내부 프로퍼티를 가진다.

 

const wtf = new kakasoo1._proto_.constuctor();

그래서 다른 언어에서는 상상도 못할 이런 기상천외한 일이 가능하다.

그래서 자바스크립트, 그리고 node.js에서 파일구조를 이용해 만드는 싱글턴은 엄밀히 말해 완벽하지 못하다.

따라서 자바스크립트에서는 ES2019에 추가된 private field를 이용해 접근 불가능한 객체를 만들어야 한다.

 

class ClassWithPrivateField {
  #privateField() {}
}

보통은 위 코드와 같이 private한 메서드를 두고, 클래스의 static한 변수에 instance를 저장, 반환하게끔 구현하곤 한다.

이 내용을 타입스크립트에서는 언어 스펙 외에 아래와 같은 디자인 패턴으로도 구현이 가능하다.

 

namespace SingletonPattern {
  export class Singleton {
    // 싱글턴 클래스는 모든 인스턴스 ( 하나만 생성되겠지만 ) 에서 접근가능한 객체 하나만을 지닌다.
    private static singleton: Singleton;

    // 어떤 인스턴스도 더 생성하지 않고, 또 생성하지 못하게 하기 위해 생성자를 private로 한다.
    private constructor() {}

    public static getInstance(): Singleton {
      // 이미 생성된 객체가 존재하는지 체크한다.
      if (!Singleton.singleton) {
        // 아직 생성된 적 없다면 생성하여 singleton static 변수에 저장한다.
        Singleton.singleton = new Singleton();
      }

      // 생성한 적이 있다면 이미 생성된 것을 반환한다.
      return Singleton.singleton;
    }
  }
}

순수한 자바스크립트에선 # 기호를 통해 생성자 함수를 private로 바꾸는 게 불가능하다.

하지만 타입스크립트에서는 생성자 또한 접근을 제한할 수 있기 때문에 기존 생성자를 제거할 수 있다.

그 다음 생성자를 대신할 메서드를 구현하고, 생성자를 제외한 모든 것들 static method로 변경하면 된다.

순수한 자바스크립트에 비해 더 길고 복잡하지만 가독성과 코드 이해는 훨씬 쉬워진 것으로 보인다.

반응형

'프로그래밍 > TypeScript' 카테고리의 다른 글

NTuple 타입 정의하기  (0) 2023.01.21
type Push = <T extends any[], value> = […T, value]  (0) 2023.01.20
배열의 Length를 뽑는 타입  (0) 2023.01.20
Extract<Type, Union>  (0) 2023.01.18
new (…args): T 타입이란?  (4) 2023.01.03