NodeJS Singleton pattern

00_8_3·2021년 2월 12일
2
post-thumbnail

NodeJS Singleton pattern

NodeJS의 여러 디자인 패턴 중 하나인 Singleton Design Pattern을 소개 하고자 한다.

What is Design Pattern?

디자인 패턴이란 소프트웨어 공학에서 소프트웨어 디자인에서 특정 문맥에서 공통적으로 발생하는 문제에 대해 재사용 가능한 해결책이다.
소스나 기계 코드로 바로 전환될수 있는 완성된 디자인은 아니며, 다른 상황에 맞게 사용될 수 있는 문제들을 해결하는데에 쓰이는 서술이나 템플릿이다.

Design이라는 표현보다 Pattern에 중점을 두면 좋을 것 같다.

What is Singleton?

  • Singleton이란 전체 시스템에서 하나의 인스턴스만 존재하도록 보장하는 객체 생성패턴 이라고 한다.

  • 그래서 싱글톤은 특정 클래스의 인스턴스를 오직 하나만 유지하고, 동일 클래스에서 새로운 객체를 생성한다 해도 처음 만들어진 객체를 얻습니다.

  • 싱글톤은 OOP 언어에서 여러 개의 인스턴스 생성을 피하기 위한 유용한 패턴입니다. 하지만 클래스 기반 언어라고 할 수 없는 JS에서는 유용한 편은 아니라고 합니다.

  • JS에서의 객체 리터럴이 싱글톤의 대표적인 예입니다. 하지만 모든 속성이 공개 되어있기 때문에 이것을 비공개로 하는 것이 제대로 된 싱글톤이라 할 수 있습니다.

    • 객체 리터럴 만 으로 비공개 상태로 함수를 정의 할 수 없어 클로저가 필요 합니다. 즉 객체 리터럴 + 클로저의 조합이 필요 합니다.

When Using?

  • 인스턴스가 절대적으로 한 개만 존재한다는 것을 보증하고 싶을 때

  • 예를들어, 게임을 만들 때 게임 객체를 싱글턴으로 만든다. 게임 내의 모든 것을 감싸고 있는 객체를 말합니다. 게임이 실행 되었을 때, 게임은 한 번만 켜져야 하기 때문에 싱글턴이 적절합니다.

사용함에 있어 얻는 이점?

  • 인스턴스가 오직 하나만 생성되므로, 메모리상 이점이 있다.

  • 두 번째 호출 부터는 객체 로딩시간이 줄어들어 성능 향상이 있다.

  • 다른 인스턴스들과 데이터 공유가 쉽다.

단점?

  • 싱글톤 인스턴스가 너무 많은 일을 하거나 많은 데이터를 공유할 때 다른 클래스간의 결합도가 높아져 OCP를 위배하게 된다.
    • 즉 OOP설계 원칙에 어긋나게 되며 수정테스트가 어려워진다.

들어가기 앞서

constructor 란?

  • class는 constructor란 특별한 함수를 하나만 가질 수 있다.

  • 생성자 메서드는 super라는 키워드로 상위 클래스의 생성자 메서드를 호출 할 수 있다.

constructor

예제 1 - IIFE로 객체 생성

var singleton = (function() {
  var instance;
  var a = 'singleton';
  function init() {
    return {
      a: a,
      b: function() {
        console.log(a);
      }
    };
  }
  return {
    getInstance: function() {
      if (!instance) {
        instance = init();
      }
      return instance;
    }
  }
})();
var singletone1 = singleton.getInstance();
var singletone2 = singleton.getInstance();
console.log(singletone1 === singletone2); // true;

예제 2 - class로 생성자

2.1 singleton.js

class PrivateSingleton {
    constructor() {
        this.message = 'I am an instance';
    }
}
class Singleton {
    constructor() {
        throw new Error('Use Singleton.getInstance()');
    }
    static getInstance() {
        if (!Singleton.instance) {
            Singleton.instance = new PrivateSingleton();
        }
        return Singleton.instance;
    }
}
module.exports = Singleton;

2.2 인스턴스를 불러올 때

const Singleton = require('./Singleton');
const object = Singleton.getInstance(); 
console.log(object.message);   // Prints out: 'I am an instance'
object.message = 'Foo Bar';    // Overwrite message property
const instance = Singleton.getInstance();
console.log(instance.message); // Prints out: 'Foo Bar'

예제 3 - Cached Singleton

NodeJS의 Module 캐싱의 이점을 사용 하겠다.

Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.

NodeJS Module Cache

3.1

class Singleton {
    constructor() {
        this.message = 'I am an instance';
    }
}
module.exports = new Singleton();

엄청 간단해 보인다. 예제 2와 다른 것은 getInstance() 메소드가 없어 보인다. 왜일까??

예제 2와 같이
module.exports = Singleton; // 대신
module.exports = new Singleton(); // 처럼 export 해주었기 때문이다.

3.2

const Singleton = require('./Singleton');
const object = Singleton;

console.log(object.message); // Prints out: 'I am an instance'
object.message = 'Foo Bar'; // Overwrite message property

const instance = Singleton;
console.log(instance.message); // Prints out: 'Foo Bar'

예제 2예제 3은 같은 결과를 갖지만 NodeJS의 caching에서 이점을 얻기 때문에 후자를 추천한다.

참고

이 글은 CommonJS를 기반으로 작성 되었습니다.
NodeJS가 ECMAScript 로 전환되고 있습니다.
ECMAScript로 이주 할 때 다음 링크를 참조 하시면 됩니다.

NodeJS Singleton

0개의 댓글