개발

[ 디자인 패턴 ] 1.5 싱글톤(Singleton)

Crmal 2023. 8. 30. 00:10

싱글톤패턴(Singleton pattern) 이란

싱글톤 패턴은 전체 시스템에서 하나의 인스턴스만 존재하도록 보장하는 패턴입니다.
new를 사용하여 클래스를 생성하여도 인스턴스는 하나만 존재합니다.

인스턴스란?
인스턴스를 알기전에 클래스(Class)의 의미를 알아야 합니다.
클래스란 설계도라고 생각하면 됩니다. 어떠한 반복적으로 만들어지는 것을 만드는 설계도가 클래스이고
인스턴스란 그 설계도로 만든 물건을 이야기합니다.

특징

  • 객제 자체에는 접근이 불가능해야 합니다.
  • 객체에 대한 접근자를 사용하여 객체를 제어 한다.
  • 객체는 단 한개이며 해당 객체를 공유합니다.
var singletonObj = {
    a : '값',
    b : function () {
    }
}

위와 같은 객체 리터널도 싱글톤 패턴입니다.
하지만, 객체 리터널로는 비공개 상태 및 함수를 정의할 수 없습니다.
JavaScirpt에서는 클로저(Closure)를 이용하여 구현 할 수 있습니다.

다음은 클로저를 이용하여 싱글톤 패턴 구현 예제 입니다.

var Singleton = (function () {

    /**
     * --------------------------------
     * 싱글톤 패턴 구현 코드
     * --------------------------------
     */

    // 비공개 변수, 메서드 정의
    var instantiaed;

    function init() {

        // 싱글톤 객체 정의
        return {
            // 공개 메서드 정의
            publicMethod : function () {
                return 'hello Singleton Pattern!!!';
            },
            // 공개 프로퍼티 정의
            publicProp : 'single value'
        }

    }

    // 공개 메서드인 getInstance() 를 정의한 객체.
    // 렉시컬 특성으로 인해 비공개 변수, 메서드에 접근 가능(클로저)
    return {
        getInstance : function () {
            if (!instantiaed) {
                instantiaed = init();
            }
            return instantiaed;
        }
    }

})();

// 싱글톤 객체 생성하여 publicMethod 호출 가능해짐
var first = Singleton.getInstance();
first.publicMethod();
console.log(first.publicMethod()); // hello Singleton Pattern!!!

var second = Singleton.getInstance();
second.publicMethod();
console.log(second.publicMethod()); // hello Singleton Pattern!!!

console.log(first === second); // true

렉시컬 스코프

렉시컬 스코프란(Lexical Scope)
함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정되는 것을 말합니다.
함수를 어디서 선언하였는지에 따라 상위 스코프를 결정하는뜻으로 함수의 선언에 따라 결정된다는 점입니다.

예시로 다음코드를 보았을때

var x = 1; // global

function first() {
  var x = 10;
  second();
}

function second() {
  console.log(x);
}

first(); // 1
second(); // 1

1, 10이 아닌 1, 1이 출력됩니다.

이유는?

자바스크립트에서는 위와 같은 코드를 작성할 때, 이미 실행 단계에서 코드들의 스코프를 결정한다.

  • global 범위에 있는 변수 x

  • first() 함수 안에 있는 변수 x

  • second() 함수 안에 있는 변수 x

위 예제의 실행 결과는 함수 second()의 상위 스코프가 무엇인지에 따라 결정된다.

자바스크립트는 렉시컬 스코프(Lexical Scope)를 따르므로 함수를 선언한 시점에 상위 스코프가 결정된다.

즉, 이 말은 함수를 어디에서 호출하였는지는 스코프 결정에 아무런 의미를 주지 않는다는 말이다.

그렇기 때문에, second() 함수가 first() 함수 안에서 호출된 것과 상관없이 second() 함수는 global 범위에 선언되어 있으므로, global 범위에 있는 변수 x의 값 1이 두 번 출력된 것이다.

참고

https://heecheolman.tistory.com/40
http://webclub.tistory.com/150
https://ljtaek2.tistory.com/145