웹개발/javascript

[자바스크립트] 싱글톤(Singleton) 패턴

joamashi 2025. 3. 17. 16:16
반응형

싱글톤(Singleton) 패턴이란?

싱글톤 패턴은 하나의 클래스에 단 하나의 객체만 생성되도록 보장하는 디자인 패턴입니다. 즉, 프로그램이 실행되는 동안 오직 하나의 인스턴스만 유지하며, 그 인스턴스를 어디서든 접근할 수 있도록 합니다.


왜 사용할까?

  1. 하나의 객체만 있어야 하는 경우
    • 설정 정보 관리 (Configuration Manager)
    • 데이터베이스 연결 (Database Connection)
    • 로깅 시스템 (Logger)
    • 윈도우 관리자 (Window Manager)
  2. 불필요한 객체 생성을 막아 메모리 절약
    • 동일한 객체를 계속 생성하는 대신, 한 번만 생성하여 사용하면 성능 최적화에 도움이 됩니다.

싱글톤 패턴 구현 (Python 예제)

class Singleton:
    _instance = None  # 클래스 변수로 인스턴스를 저장

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

# 객체 생성
s1 = Singleton()
s2 = Singleton()

print(s1 is s2)  # True (같은 객체)
  • _instance 변수에 객체를 저장하여, 이후 새로운 객체 요청이 오더라도 기존 객체를 반환합니다.

싱글톤 패턴의 특징

하나의 객체만 존재
전역적으로 접근 가능
불필요한 객체 생성을 방지하여 성능 최적화

싱글톤 패턴을 잘 활용하면 효율적인 자원 관리가 가능하지만, 너무 남발하면 코드의 의존성이 증가할 수 있으니 필요할 때만 사용하세요! 😊


1. 객체 리터럴을 사용한 싱글톤

const Singleton = {
    name: "SingletonInstance",
    getName() {
        return this.name;
    }
};

console.log(Singleton.getName()); // SingletonInstance

설명: const 객체를 사용하여 단 하나의 인스턴스를 유지한다.


2. 즉시 실행 함수(IIFE) 사용

const Singleton = (function() {
    const instance = {
        name: "SingletonInstance",
        getName() {
            return this.name;
        }
    };
    return instance;
})();

console.log(Singleton.getName()); // SingletonInstance

설명: 즉시 실행 함수(IIFE)를 사용하여 인스턴스를 생성하고 반환한다.


3. 클래스 기반 싱글톤

class Singleton {
    constructor() {
        if (!Singleton.instance) {
            this.name = "SingletonInstance";
            Singleton.instance = this;
        }
        return Singleton.instance;
    }

    getName() {
        return this.name;
    }
}

const s1 = new Singleton();
const s2 = new Singleton();

console.log(s1 === s2); // true
console.log(s1.getName()); // SingletonInstance

설명: 클래스의 static 프로퍼티를 활용해 하나의 인스턴스만 생성한다.


4. 클로저를 활용한 싱글톤

const Singleton = (function() {
    let instance;

    function createInstance() {
        return {
            name: "SingletonInstance",
            getName() {
                return this.name;
            }
        };
    }

    return {
        getInstance() {
            if (!instance) {
                instance = createInstance();
            }
            return instance;
        }
    };
})();

const s1 = Singleton.getInstance();
const s2 = Singleton.getInstance();

console.log(s1 === s2); // true
console.log(s1.getName()); // SingletonInstance

설명: getInstance()를 호출할 때마다 같은 인스턴스를 반환한다.


5. 모듈 패턴을 사용한 싱글톤

const Singleton = (() => {
    let instance;
    return {
        getInstance() {
            if (!instance) {
                instance = { name: "SingletonInstance" };
            }
            return instance;
        }
    };
})();

console.log(Singleton.getInstance()); // 같은 객체 반환

설명: JavaScript 모듈 패턴을 이용하여 싱글톤을 구현한다.


6. ES6 모듈을 활용한 싱글톤

// singleton.js
class Singleton {
    constructor() {
        if (!Singleton.instance) {
            this.name = "SingletonInstance";
            Singleton.instance = this;
        }
        return Singleton.instance;
    }
}

export default new Singleton();
// main.js
import Singleton from './singleton.js';

console.log(Singleton.name); // SingletonInstance

설명: export default로 유일한 인스턴스를 제공한다.


7. Symbol을 활용한 싱글톤

const Singleton = (function() {
    const INSTANCE = Symbol('instance');

    class Singleton {
        constructor() {
            if (!Singleton[INSTANCE]) {
                this.name = "SingletonInstance";
                Singleton[INSTANCE] = this;
            }
            return Singleton[INSTANCE];
        }
    }

    return Singleton;
})();

const s1 = new Singleton();
const s2 = new Singleton();

console.log(s1 === s2); // true

설명: Symbol을 사용하여 외부에서 접근할 수 없는 고유한 인스턴스를 유지한다.


8. Proxy를 활용한 싱글톤

const Singleton = new Proxy(new (class {
    constructor() {
        this.name = "SingletonInstance";
    }
})(), {
    construct() {
        throw new Error("Cannot instantiate Singleton");
    }
});

console.log(Singleton.name); // SingletonInstance

설명: Proxy를 사용하여 추가적인 인스턴스 생성을 방지한다.


9. WeakMap을 활용한 싱글톤

const Singleton = (function() {
    const instances = new WeakMap();

    class Singleton {
        constructor() {
            if (!instances.has(Singleton)) {
                instances.set(Singleton, this);
                this.name = "SingletonInstance";
            }
            return instances.get(Singleton);
        }
    }

    return Singleton;
})();

const s1 = new Singleton();
const s2 = new Singleton();

console.log(s1 === s2); // true

설명: WeakMap을 사용하여 인스턴스를 저장하고 보호한다.


10. Reflect을 활용한 싱글톤

const Singleton = (function() {
    let instance;

    return new Proxy(class {
        constructor() {
            if (!instance) {
                instance = Reflect.construct(Object, []);
                instance.name = "SingletonInstance";
            }
            return instance;
        }
    }, {
        construct() {
            throw new Error("Cannot create new Singleton instances.");
        }
    });
})();

const s1 = new Singleton();
console.log(s1.name); // SingletonInstance

설명: Reflect API를 사용하여 싱글톤을 구현하고 Proxy로 인스턴스 생성을 차단한다.

728x90
반응형