본문 바로가기
Language

싱글턴(Singleton) 패턴: 객체의 유일성을 보장하는 설계 패턴 완벽 분석

by markbyun 2025. 4. 28.

프로그래밍에서 싱글턴(Singleton)은 프로그램 전체 실행 기간 동안 클래스의 인스턴스가 오직 하나만 존재하도록 보장하고, 그 인스턴스에 전역(Global)으로 접근할 수 있는 지점을 제공하는 디자인 패턴입니다. 싱글턴 패턴은 주로 데이터베이스 연결, 설정 파일 로딩, 무거운 머신러닝 모델 로딩처럼 자원을 효율적으로 관리해야 할 때 널리 사용됩니다.

왜 싱글턴을 사용할까요?

  • 메모리 사용 최적화
  • 자원 접근 제어
  • 애플리케이션 전체의 일관성 보장

파이썬에서 싱글턴을 구현하는 간단한 방법

class SingletonMeta(type):
    _instances = {}

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

class SingletonExample(metaclass=SingletonMeta):
    def __init__(self):
        print("Initializing SingletonExample")

# 사용 예시
a = SingletonExample()
b = SingletonExample()

print(a is b)  # True

위 예제에서는 SingletonExample 클래스를 몇 번이고 생성하려 해도, 항상 같은 객체(instance)가 반환됩니다!


실제 예시: PyTorch 모델 로딩에 싱글턴 적용하기

머신러닝 프로젝트에서는 모델 로딩이 매우 느리고 메모리를 많이 소모할 수 있습니다. 앱이 여러 번 모델을 불러오게 된다면, 심각한 성능 문제가 발생할 수 있습니다. 이때 싱글턴 패턴을 적용하면 모델을 한 번만 메모리에 로드하고, 계속 재사용할 수 있습니다.

PyTorch 모델 로더 싱글턴 예제

import torch
import torch.nn as nn

class SingletonMeta(type):
    _instances = {}

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

class ModelLoader(metaclass=SingletonMeta):
    def __init__(self, model_path):
        self.model = self.load_model(model_path)

    def load_model(self, model_path):
        print(f"Loading model from {model_path}...")
        model = nn.Sequential(
            nn.Linear(10, 20),
            nn.ReLU(),
            nn.Linear(20, 1)
        )
        model.load_state_dict(torch.load(model_path, map_location="cpu"))
        model.eval()
        return model

    def predict(self, input_tensor):
        with torch.no_grad():
            return self.model(input_tensor)

# 사용 예시
if __name__ == "__main__":
    loader1 = ModelLoader("model.pth")
    loader2 = ModelLoader("model.pth")

    print(f"loader1 is loader2: {loader1 is loader2}")

    dummy_input = torch.randn(1, 10)
    output = loader1.predict(dummy_input)
    print(f"Prediction: {output}")

핵심 포인트

  • ModelLoader 클래스는 모델을 단 한 번만 로드합니다.
  • loader1loader2는 동일한 객체(instance)입니다.
  • 메모리 사용량이 줄어들고, 예측(Prediction) 속도가 빨라집니다.

샘플 출력 예시

Loading model from model.pth...
loader1 is loader2: True
Prediction: tensor([[...]])

참고 자료 (References)

 

추가 팁

실제 ML 서비스에서는 모델을 한 번만 로드하고, 빠르게 서빙하여 메모리와 시간을 절약하는 것이 매우 중요합니다. 싱글턴 패턴은 BERT, ResNet 같은 대형 모델을 다룰 때 필수적인 기법입니다!