본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] 파이썬 싱글톤(Singleton) 패턴을 구현하는 세련된 7가지 방법과 차이 해결

by Papa Martino V 2026. 3. 29.
728x90

싱글톤(Singleton) 패턴
싱글톤(Singleton) 패턴

 

 

소프트웨어 설계에서 싱글톤(Singleton) 패턴은 특정 클래스의 인스턴스가 오직 하나만 존재하도록 보장하고, 이에 대한 전역적인 접근점을 제공하는 디자인 패턴입니다. 파이썬은 언어 자체의 유연성 덕분에 Java나 C++ 같은 정적 언어와는 다른, 매우 독창적이고 효율적인 싱글톤 구현 방식들을 지원합니다. 본 포스팅에서는 단순한 이론을 넘어, 실무 개발 환경에서 발생할 수 있는 멀티스레딩 이슈, 상속 문제, 그리고 코드의 가독성을 모두 고려한 7가지의 세련된 구현 기법을 심도 있게 다룹니다. 각 방식의 내부 동작 원리와 장단점의 차이를 명확히 분석하여 상황에 맞는 최적의 해결책을 제시합니다.


1. 왜 파이썬에서 싱글톤이 중요한가?

데이터베이스 커넥션 풀, 로깅 설정, 하드웨어 제어 리소스 관리 등 시스템 전체에서 하나의 상태를 공유해야 하는 경우 싱글톤은 필수적입니다. 자칫 잘못 구현하면 메모리 낭비나 상태 불일치 오류를 야기할 수 있으므로, 파이썬의 특성을 살린 'Pythonic'한 접근이 필요합니다.


2. 싱글톤 구현 방식의 핵심 비교 및 차이

구현 방식 주요 특징 스레드 안전성 난이도 추천 상황
Module-level 파이썬 임포트 시스템 활용 매우 높음 가장 단순한 공유 자원
__new__ Override 객체 생성 단계 제어 보통 (Lock 필요) 일반적인 클래스 구조 유지
Metaclass 클래스의 클래스를 정의 높음 프레임워크 수준의 설계
Decorator 함수형 래퍼 사용 낮음 (보완 가능) 기존 클래스 확장 시
Borg (Monostate) 상태만 공유 (인스턴스 다름) 높음 상속이 빈번한 경우

3. 실무 적용을 위한 7가지 Sample Examples

개발자가 현업 프로젝트에서 즉시 복사하여 사용할 수 있는 수준의 고도화된 예제들입니다.

Example 1: 메타클래스(Metaclass)를 이용한 표준 싱글톤

가장 세련되고 확장성이 좋은 방식입니다. 클래스의 생성 로직 자체를 메타클래스에서 관리합니다.


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

class DatabaseConnector(metaclass=SingletonMeta):
    def __init__(self):
        self.connection = "Connected to DB"

# 실무 적용: 어디서 호출해도 동일한 객체 반환
db1 = DatabaseConnector()
db2 = DatabaseConnector()
print(db1 is db2)  # True

Example 2: Thread-Safe(멀티스레드 안전) 싱글톤

실제 서버 환경에서는 여러 스레드가 동시에 인스턴스를 생성하려 할 때 문제가 생깁니다. Lock을 활용해 이를 해결합니다.


import threading

class ThreadSafeSingleton:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls):
        if not cls._instance:
            with cls._lock:
                if not cls._instance:
                    cls._instance = super().__new__(cls)
        return cls._instance

# 실무 적용: 로깅 시스템 등 멀티스레드 환경
logger = ThreadSafeSingleton()

Example 3: Decorator를 활용한 싱글톤 (가독성 중심)

클래스 정의 위에 `@singleton`만 붙여 간단히 해결하는 방식입니다.


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 AppConfig:
    def __init__(self):
        self.api_key = "12345-ABCDE"

Example 4: Borg 패턴 (Monostate)

인스턴스는 다르지만 `__dict__`를 공유하여 상태를 일치시키는 독특한 파이썬 패턴입니다.


class Borg:
    _shared_state = {}
    def __init__(self):
        self.__dict__ = self._shared_state

class SharedService(Borg):
    def __init__(self, value=None):
        super().__init__()
        if value:
            self.value = value

# 실무 적용: 상속 관계가 복잡할 때 유용
s1 = SharedService("Alpha")
s2 = SharedService()
print(s1.value == s2.value)  # True

Example 5: Module-level 싱글톤 (가장 Pythonic한 해결)

파이썬의 모듈은 첫 로딩 시에만 실행된다는 점을 이용합니다.


# config_manager.py
class _ConfigManager:
    def __init__(self):
        self.env = "Production"

config = _ConfigManager()

# main.py에서 사용 시
# from config_manager import config

Example 6: __new__ 메서드 직접 제어 방식

가장 기초적이면서도 직관적인 인스턴스 생성 제어 방법입니다.


class SimpleSingleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__new__(cls)
        return cls._instance

instance_a = SimpleSingleton()

Example 7: Lazy Initialization(지연 초기화) 싱글톤

자원이 많이 소모되는 객체를 실제 사용 시점에 생성하여 효율을 높이는 방식입니다.


class HeavyResource:
    _instance = None
    
    @classmethod
    def get_resource(cls):
        if cls._instance is None:
            print("자원 로딩 중... (시간 소요)")
            cls._instance = cls()
        return cls._instance

# 실제 호출 전까지는 객체가 생성되지 않음
resource = HeavyResource.get_resource()

4. 결론 및 아키텍처 가이드

파이썬에서 싱글톤을 구현할 때는 메타클래스(Metaclass) 방식이 가장 깔끔하며, 프레임워크와의 호환성도 뛰어납니다. 하지만 팀의 코드 컨벤션이나 요구되는 동시성 수준에 따라 Module-level이나 Thread-safe 방식을 적절히 선택해야 합니다. 무분별한 싱글톤 사용은 단위 테스트(Unit Test)를 어렵게 만들 수 있으므로 의존성 주입(DI)과 함께 고민하는 것이 바람직합니다.


5. 출처 및 참고 문헌

  • Design Patterns: Elements of Reusable Object-Oriented Software (Gang of Four)
  • Python 공식 문서: Data Model - Metaclasses (docs.python.org)
  • Refactoring.Guru: Singleton Pattern in Python
  • Effective Python 
728x90