개발블로그

[디자인패턴] 싱글톤 패턴 본문

STUDY/CS

[디자인패턴] 싱글톤 패턴

devmel 2026. 9. 4. 19:06
Contents 접기
 

개념

 

필요성

프로그램을 만들다 보면 어떤 객체는 여러 개 만들어질 필요가 없거나, 여러 개 만들어지면 문제가 되는 경우가 있다.

 

EX] 애플리케이션 설정 정보를 관리하는 객체

config1 = AppConfig()
config2 = AppConfig()

 

만약 설정 객체가 여러 개 만들어지고, 각각 다른 상태를 가지게 된다면 프로그램 안에서 사용하는 설정값이 달라질 수 있음

=> 이런 상황에서는 어느 설정값이 실제 기준인지 헷갈릴 수 있음

 

또 데이터베이스 연결 관리자, 로거, 캐시 관리자처럼 애플리케이션 전체에서 하나의 기준으로 관리하는 객체도 있다.

이런 객체가 불필요하게 여러 개 만들어지면 상태 관리가 어려워지거나 자원이 낭비될 수 있음

 

 

의미

특정 클래스의 인스턴스를 하나만 생성하고, 그 인스턴스에 접근할 수 있는 방법을 제공하는 패턴

 

구분 의미
하나의 인스턴스 특정 클래스의 객체가 프로그램 안에서 하나만 존재한다.
접근 지점 제공 그 하나의 객체를 사용할 수 있는 방법을 제공한다.
생성 제어 외부에서 객체를 마음대로 여러 개 만들지 못하게 한다.

 

 

핵심 구조

구성 요소 역할
Singleton Class 하나의 인스턴스만 생성되도록 관리하는 클래스
Instance 저장 공간 생성된 하나의 인스턴스를 저장하는 변수
접근 메서드 저장된 인스턴스를 반환하는 메서드

 

흐름]

인스턴스 요청
→ 이미 만들어진 인스턴스가 있는지 확인
→ 없으면 새로 생성
→ 있으면 기존 인스턴스 반환

 

 


 

예시

 

EX]

애플리케이션 설정을 관리하는 AppConfig 

class AppConfig:
    def __init__(self):
        self.database_url = None

 

이 클래스를 여러 곳에서 각각 생성하면 서로 다른 설정 객체가 만들어짐

config1 = AppConfig()
config2 = AppConfig()

config1.database_url = "db-main"
config2.database_url = "db-test"

이제 config1과 config2는 서로 다른 상태를 가짐


객체 database_url
config1 db-main
config2 db-test

 

문제는 애플리케이션 안에서 어떤 설정 객체를 기준으로 봐야 하는지 모호해질 수 있음

def connect_database(config):
    return f"{config.database_url}에 연결"
connect_database(config1)  # db-main에 연결
connect_database(config2)  # db-test에 연결

어떤 곳에서는 config1을 넘기고, 다른 곳에서는 config2를 넘기면 실행 위치에 따라 다른 설정값을 사용할 수 있음

 

설정값처럼 애플리케이션 전체에서 하나의 기준으로 관리되어야 하는 객체라면, 

여러 인스턴스가 만들어지는 구조가 문제가 될 수 있음 


문제 설명
상태 불일치 같은 설정 객체라고 생각했지만 서로 다른 값을 가질 수 있다.
기준 모호 어떤 인스턴스가 실제 기준인지 알기 어렵다.
자원 낭비 데이터베이스 연결 관리자처럼 무거운 객체가 여러 번 생성될 수 있다.
변경 추적 어려움 어느 객체의 상태가 언제 바뀌었는지 추적하기 어렵다.

 

이런 경우는 하나의 인스턴스만 생성되도록 관리할 필요가 있음.

 

싱글톤으로 인스턴스 하나만 관리할 필요가 있음.

class AppConfig:
	# _instance = 생성된 객체를 저장하는 변수
    _instance = None

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

 

여러 변 생성하더라도 같은 객체가 반환됨

config1 = AppConfig()
config2 = AppConfig()

config1.database_url = "db-main"

print(config2.database_url)  # db-main
print(config1 is config2)    # True

 

 

 


 

장점

 

장점

장점 설명
인스턴스 중복 생성 방지 같은 객체가 여러 번 생성되는 것을 막을 수 있다.
일관된 상태 관리 여러 곳에서 같은 인스턴스를 사용하므로 기준 상태를 통일할 수 있다.
공통 자원 접근 관리 설정, 로거, 연결 관리자 같은 공용 자원을 한곳에서 관리할 수 있다.
접근 지점 단순화 필요한 곳에서 같은 인스턴스에 접근하는 방식을 제공할 수 있다.

 

 

효과적인 상황

상황 이유
설정 정보를 한곳에서 관리해야 하는 경우 여러 객체가 서로 다른 설정값을 가지는 문제를 줄일 수 있다.
로거처럼 공통으로 사용하는 객체가 필요한 경우 프로그램 전체에서 같은 로깅 기준을 사용할 수 있다.
데이터베이스 연결 관리자처럼 생성 비용이 큰 객체가 있는 경우 불필요한 중복 생성을 줄일 수 있다.
하나의 상태를 기준으로 여러 곳에서 접근해야 하는 경우 같은 인스턴스를 공유해 일관성을 유지할 수 있다.

 

 

 


 

주의점

 

주의점

주의점 설명
전역 상태 문제 여러 곳에서 같은 상태를 공유하면 변경 영향이 넓게 퍼질 수 있다.
테스트 어려움 테스트마다 독립적인 상태를 만들기 어렵고, 이전 테스트의 상태가 남을 수 있다.
의존 관계 숨김 코드 안에서 싱글톤을 직접 호출하면 어떤 의존성이 필요한지 겉으로 드러나지 않는다.
동시성 문제 여러 흐름에서 동시에 같은 객체를 수정하면 상태 충돌이 생길 수 있다.
생명주기 관리 어려움 언제 생성되고 언제 초기화되는지 명확하지 않으면 관리가 어려워질 수 있다.

 

 

고려사항

질문 의미
정말 하나만 존재해야 하는 객체인가? 단순히 편해서 싱글톤을 쓰는 것은 아닌지 확인한다.
상태 변경이 여러 곳에 영향을 줘도 괜찮은가? 공유 상태의 변경 범위를 고려한다.
테스트마다 상태를 분리할 수 있는가? 테스트 독립성을 해치지 않는지 확인한다.
의존성이 코드 밖으로 드러나는가? 숨겨진 의존성이 생기지 않도록 한다.
동시 접근 상황에서 안전한가? 여러 흐름이 동시에 사용할 때 문제가 없는지 확인한다.

 

'STUDY > CS' 카테고리의 다른 글

[디자인패턴] 데코레이터 패턴  (0) 2026.09.04
[디자인패턴] 어댑터 패턴  (0) 2026.09.04
[디자인패턴] 옵저버 패턴  (0) 2026.09.04
[디자인패턴] 팩토리 패턴  (1) 2026.09.04
[디자인 패턴] 전략패턴  (0) 2026.09.04