NodeJS의 여러 디자인 패턴 중 하나인 Singleton Design Pattern
을 소개 하고자 한다.
Design Pattern
?디자인 패턴
이란 소프트웨어 공학에서 소프트웨어 디자인에서 특정 문맥에서 공통적으로 발생하는 문제에 대해 재사용 가능한 해결책이다.
소스나 기계 코드로 바로 전환될수 있는 완성된 디자인은 아니며, 다른 상황에 맞게 사용될 수 있는 문제들을 해결하는데에 쓰이는 서술이나 템플릿이다.
Design
이라는 표현보다Pattern
에 중점을 두면 좋을 것 같다.
Singleton
이란 전체 시스템에서 하나의 인스턴스만 존재하도록 보장하는 객체 생성패턴 이라고 한다.
그래서 싱글톤은 특정 클래스의 인스턴스를 오직 하나만 유지하고, 동일 클래스에서 새로운 객체를 생성한다 해도 처음 만들어진 객체를 얻습니다.
싱글톤
은 OOP 언어에서 여러 개의 인스턴스 생성을 피하기 위한 유용한 패턴입니다. 하지만 클래스 기반 언어라고 할 수 없는 JS에서는 유용한 편은 아니라고 합니다.
JS에서의 객체 리터럴
이 싱글톤의 대표적인 예입니다. 하지만 모든 속성이 공개 되어있기 때문에 이것을 비공개로 하는 것이 제대로 된 싱글톤이라 할 수 있습니다.
객체 리터럴
만 으로 비공개 상태로 함수를 정의 할 수 없어 클로저
가 필요 합니다. 즉 객체 리터럴 + 클로저
의 조합이 필요 합니다.인스턴스가 절대적으로 한 개만 존재한다는 것을 보증하고 싶을 때
예를들어, 게임을 만들 때 게임 객체를 싱글턴으로 만든다. 게임 내의 모든 것을 감싸고 있는 객체를 말합니다. 게임이 실행 되었을 때, 게임은 한 번만 켜져야 하기 때문에 싱글턴이 적절합니다.
인스턴스가 오직 하나만 생성되므로, 메모리상 이점이 있다.
두 번째 호출 부터는 객체 로딩시간이 줄어들어 성능 향상이 있다.
다른 인스턴스들과 데이터 공유가 쉽다.
OCP
를 위배하게 된다.수정
과 테스트
가 어려워진다.constructor
란?class는 constructor란 특별한 함수를 하나만 가질 수 있다.
생성자 메서드는 super
라는 키워드로 상위 클래스의 생성자 메서드를 호출 할 수 있다.
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;
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;
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'
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.
class Singleton {
constructor() {
this.message = 'I am an instance';
}
}
module.exports = new Singleton();
엄청 간단해 보인다. 예제 2
와 다른 것은 getInstance()
메소드가 없어 보인다. 왜일까??
예제 2와 같이
module.exports = Singleton; // 대신
module.exports = new Singleton(); // 처럼 export 해주었기 때문이다.
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
로 이주 할 때 다음 링크를 참조 하시면 됩니다.