한양과학기술고등학교

에듀테크 프로젝트 대시보드

싱글턴 패턴

싱글턴 패턴(Singleton Pattern)은 어떤 클래스의 인스턴스가 프로그램 전체에서 단 하나만 존재하도록 강제하고, 그 하나뿐인 인스턴스에 어디서든 접근할 수 있는 전역 접근점을 제공하는 디자인 패턴이다. 로그 기록기, 설정(Config) 객체, DB 커넥션 풀처럼 "여러 개가 있으면 오히려 곤란한" 대상에 주로 쓴다. 아래에서 일반 클래스와 싱글턴 클래스에 각각 "인스턴스 생성"을 여러 번 눌러 차이를 눈으로 확인해 보자.
🧱 일반 클래스 Logger()
생성 시도 횟수 0
실제 생성된 객체 수 0
호출할 때마다 서로 다른 메모리 주소를 가진 새 객체가 매번 만들어진다. 로그 파일 핸들을 여러 번 열거나, 설정값이 객체마다 따로 노는 문제가 생길 수 있다.
🔒 싱글턴 클래스 Logger.instance()
생성 시도 횟수 0
실제 생성된 객체 수 0
처음 호출될 때만 객체를 만들고(게으른 초기화, Lazy Init), 이후 호출은 이미 만들어둔 그 객체를 그대로 돌려준다. 몇 번을 호출해도 메모리 주소가 동일하다.
🐍 코드로 보는 구현
class Logger: _instance = None # 클래스 변수 — 인스턴스를 여기 보관 def __new__(cls): if cls._instance is None: # 아직 없으면 딱 한 번만 생성 cls._instance = super().__new__(cls) cls._instance.logs = [] return cls._instance # 있으면 그대로 반환 def write(self, msg): self.logs.append(msg) a = Logger() b = Logger() assert a is b # True — 완전히 같은 객체!
왜 스레드 안전이 문제될까? 두 스레드가 if cls._instance is None을 "동시에" 통과하면 객체가 두 번 만들어질 수 있다. 락(Lock)으로 "생성 구간"을 한 번에 하나의 스레드만 지나가게 막아야 진짜 하나만 보장된다.
🌍 실전에서 쓰이는 곳
로거 (Logger)
모든 모듈이 같은 로그 파일에 순서대로 기록하려면 로거 객체가 하나여야 한다.
설정 관리자
환경변수·설정값을 앱 전체에서 동일하게 읽도록 하나의 Config 객체로 통일한다.
DB 커넥션 풀
연결 풀 객체가 여러 개면 각자 다른 연결을 관리해 자원 낭비·설정 불일치가 생긴다.
⚠️ 주의점 — 만능이 아니다
① 숨겨진 전역 상태
어디서든 접근 가능하다는 건, 어디서든 값을 몰래 바꿀 수 있다는 뜻이다. 코드 흐름을 추적하기 어려워진다.

② 테스트가 어려움
테스트마다 상태를 초기화하기 힘들고, 가짜 객체(Mock)로 바꿔 끼우기도 까다롭다.

③ 대안
전역 싱글턴 대신, 필요한 객체를 함수/생성자 인자로 명시적으로 넘겨주는 의존성 주입(Dependency Injection)이 최근에는 더 선호된다.