싱글톤 디자인 패턴

싱글톤 디자인 패턴

DesignPattern
싱글톤 디자인 패턴
Author

gabriel yang

Published

November 11, 2024


싱글톤(Singleton) 패턴은 객체를 하나만 생성해 어디에서든지 동일한 인스턴스를 참조할 수 있게 하는 디자인 패턴입니다. 파이썬에서 싱글톤 패턴을 구현하는 방법과 이를 사용하는 이유에 대해 설명하겠습니다.

싱글톤 패턴이란?

싱글톤 패턴은 특정 클래스의 인스턴스가 오직 하나만 존재하도록 제한하는 패턴입니다. 예를 들어 데이터베이스 연결, 로깅 시스템, 설정 정보 관리 등의 경우, 여러 개의 인스턴스가 생성되면 비효율적이거나 일관성을 유지하기 어렵기 때문에 싱글톤 패턴이 유용합니다.

싱글톤을 사용하는 이유

  1. 자원의 효율적 사용: 객체를 하나만 생성하여 메모리나 시스템 자원을 절약합니다.
  2. 데이터 일관성 유지: 동일한 인스턴스를 참조하기 때문에 데이터를 일관되게 유지할 수 있습니다.
  3. 전역 상태 관리: 특정 클래스의 인스턴스를 애플리케이션 전역에서 접근할 수 있도록 만들어 프로그램 전반에서 공유하는 데이터를 손쉽게 관리할 수 있습니다.

예를 들어, 데이터베이스 연결 객체는 프로그램 전체에서 하나만 있어야 효율적입니다. 만약 여러 개의 객체가 생성되면, 비효율적인 자원 사용 및 불필요한 연결이 발생할 수 있습니다.

파이썬에서 싱글톤 패턴 구현하기

파이썬에서는 다양한 방법으로 싱글톤 패턴을 구현할 수 있습니다. 아래에서 대표적인 세 가지 방법을 소개합니다.

방법 1: 모듈을 싱글톤처럼 사용하기

파이썬에서는 모듈이 최초로 import될 때 한번만 로드되므로, 이를 싱글톤처럼 사용할 수 있습니다. 단, 이 방식은 클래스를 사용하지 않기 때문에 특정 클래스의 인스턴스를 싱글톤으로 만들고자 하는 경우에는 적합하지 않을 수 있습니다.

# singleton_module.py

# 싱글톤처럼 사용할 변수와 함수
shared_data = {}

def set_data(key, value):
    shared_data[key] = value

def get_data(key):
    return shared_data.get(key)

위 코드에서 shared_data는 하나의 인스턴스로 여러 곳에서 공유되어 사용됩니다.

방법 2: 클래스에 __new__ 메서드 오버라이딩

__new__ 메서드를 오버라이딩하여 객체를 한 번만 생성하고, 이후에 생성 요청이 들어올 때 기존 객체를 반환하는 방법입니다.

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

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

# 사용 예시
s1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # True, 같은 인스턴스를 참조합니다.

__new__ 메서드에서는 최초 생성 시 _instance를 할당하고, 이후에는 기존 인스턴스를 반환함으로써 싱글톤 패턴을 구현합니다.

방법 3: 데코레이터 활용

싱글톤을 데코레이터로 구현하면, 해당 클래스를 쉽게 싱글톤으로 만들 수 있습니다.

def singleton(cls):
    instances = {}

    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]

    return get_instance

@singleton
class SingletonClass:
    pass

# 사용 예시
s1 = SingletonClass()
s2 = SingletonClass()
print(s1 is s2)  # True

데코레이터 singleton을 사용하면 해당 클래스를 싱글톤으로 만들어주기 때문에, 코드가 간결해지는 장점이 있습니다.

방법 4: 메타클래스를 이용한 싱글톤 구현

메타클래스(Metaclass)를 사용하여 싱글톤 패턴을 구현할 수도 있습니다. 이 방법은 클래스의 생성을 제어할 수 있는 메타클래스의 특성을 이용합니다.

class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class SingletonClass(metaclass=SingletonMeta):
    pass

# 사용 예시
s1 = SingletonClass()
s2 = SingletonClass()
print(s1 is s2)  # True

메타클래스를 이용하면 객체 생성 시 자동으로 싱글톤 패턴을 적용할 수 있습니다. 다른 객체 생성 방식과 호환성이 좋아 대규모 애플리케이션에서 유용하게 사용할 수 있습니다.

싱글톤 패턴의 사용 사례

  1. 로그 관리: 애플리케이션 전체에서 하나의 로그 객체를 사용해 로그를 기록하는 경우.
  2. 설정 관리: 프로그램의 설정 정보를 하나의 객체로 관리하여 어디에서든 참조할 수 있도록 함.
  3. 데이터베이스 연결 관리: 데이터베이스 연결을 하나의 인스턴스로 관리해 효율성을 높임.

싱글톤 패턴은 특히 큰 애플리케이션에서 전역 상태나 공유 자원을 관리할 때 필수적인 디자인 패턴입니다. 다만, 모든 상황에 싱글톤 패턴이 필요한 것은 아니므로, 필요에 따라 적절히 사용하는 것이 좋습니다.