싱글톤 패턴
IT 위키
더 많은 작업
싱글톤 패턴(Singleton Pattern)은 클래스의 인스턴스가 프로그램 전체에서 하나만 만들어지도록 보장하고, 그 인스턴스에 어디서든 접근할 수 있는 통로를 제공하는 생성 패턴이다.
싱글톤 패턴은 GoF 디자인 패턴의 생성(Creational) 패턴 다섯 가지 중 하나다. 설정 정보, 커넥션 풀, 로그 기록기처럼 프로그램 안에 여러 개가 있으면 오히려 문제가 되는 객체에 쓴다. 생성자를 외부에서 부를 수 없게 막고, 클래스가 스스로 만든 유일한 인스턴스를 정적(static) 메서드로 돌려준다.
| 요소 | 역할 |
|---|---|
| private 생성자 | 외부에서 new 로 객체를 만들지 못하게 막는다
|
| private static 필드 | 유일한 인스턴스를 담아 둔다. 클래스에 하나만 존재한다 → 자바 static |
| public static 접근 메서드 | 인스턴스가 없으면 만들고, 있으면 이미 만든 것을 돌려준다(getInstance(), get() 등)
|
class Connection {
private static Connection _inst = null;
private int count = 0;
static public Connection get() {
if (_inst == null) {
_inst = new Connection(); // 처음 한 번만 생성
}
return _inst; // 이후에는 같은 객체를 반환
}
public void count() { count++; }
public int getCount() { return count; }
}
public class Main {
public static void main(String[] args) {
Connection conn1 = Connection.get();
conn1.count();
Connection conn2 = Connection.get();
conn2.count();
Connection conn3 = Connection.get();
conn3.count();
conn1.count();
System.out.print(conn1.getCount()); // 4
}
}
conn1,conn2,conn3은 이름만 다를 뿐 모두 같은 객체를 가리킨다.conn1 == conn2는true다.- 그래서 어느 변수로
count()를 부르든 같은count필드가 늘어난다. 네 번 불렀으므로 4가 출력된다. count자체는 static 이 아닌 인스턴스 필드다. 값이 공유되는 이유는 필드가 static 이어서가 아니라 인스턴스가 하나뿐이어서다.
| 방식 | 내용 | 특징 |
|---|---|---|
| 지연 초기화(Lazy) | 처음 요청할 때 만든다(위 예제) | 쓰지 않으면 만들지 않는다. 멀티스레드에서 동시에 들어오면 두 개가 만들어질 수 있다 |
| 이른 초기화(Eager) | 클래스가 로드될 때 static 필드에서 바로 만든다 | 스레드에 안전하다. 쓰지 않아도 만들어진다 |
| 동기화 메서드 | 접근 메서드에 synchronized 를 붙인다 |
안전하지만 호출할 때마다 잠금 비용이 든다 |
| DCL(Double-Checked Locking) | null 검사 → 잠금 → 다시 null 검사. 필드는 volatile |
생성 시점에만 잠근다 |
| 홀더(Holder) 클래스 | 내부 정적 클래스가 로드될 때 인스턴스를 만든다 | 지연 초기화이면서 스레드에 안전하다 |
| enum | enum Singleton { INSTANCE; } |
직렬화·리플렉션으로도 두 번째 인스턴스를 만들 수 없다 |
- 장점
- 인스턴스가 하나라 메모리 낭비가 적고, 생성 비용이 큰 객체를 한 번만 만든다.
- 여러 곳에서 같은 상태를 공유할 수 있다.
- 단점
- 사실상 전역 변수라 클래스 사이의 결합도가 높아진다.
- 단위 테스트에서 가짜 객체로 바꾸기 어렵다.
- 멀티스레드 환경에서는 생성 시점과 공유 상태의 동기화를 따로 신경 써야 한다.