1. 싱글톤 패턴의 정의
싱글톤 패턴은 특정 클래스의 인스턴스를 하나만 생성하고, 이를 전역적으로 접근할 수 있도록 제공하는 디자인 패턴입니다.
2. 싱글톤 패턴을 사용하는 이유
- 하나의 인스턴스만 필요할 때
특정 클래스가 여러 개의 인스턴스를 가질 필요가 없고, 공유 자원이나 글로벌 설정 정보를 관리하는 경우 유용합니다. - 자원의 낭비 방지
객체를 여러 개 생성하는 것은 메모리와 CPU 자원을 소모하므로, 하나의 인스턴스를 공유함으로써 자원을 절약합니다. - 전역 상태 관리
애플리케이션의 설정, 로깅, 데이터베이스 연결 등 공유된 상태를 관리하는 데 적합합니다.
쉽게 설명하면 - 싱글톤 패턴은 "딱 하나의 물건(인스턴스)만 만들고, 모두가 그걸 공유해서 쓰게 하겠다"는 약속입니다.
왜? 자원을 절약하고, 하나의 상태를 유지하기 위해서요.
현실 비유로는 커피 머신이 집에 하나밖에 없다고 생각해보세요. 가족 모두가 그 하나의 커피 머신을 공유해서 사용하는 거예요.굳이 여러 대의 커피 머신을 살 필요가 없죠.
3. 싱글톤 패턴을 사용하는 상황
- 로그(Log) 관리
로그를 기록하는 클래스는 시스템 전역에서 하나의 인스턴스만 필요합니다. - 설정(Configuration) 관리
애플리케이션의 환경 설정 정보를 관리할 때 사용됩니다. - 데이터베이스 연결 관리
데이터베이스 연결 풀(Connection Pool)을 관리하는 데 사용합니다. - 캐시(Cache) 관리
자주 사용되는 데이터를 메모리에 캐싱하고 공유할 때 사용합니다. - 스레드 관리
스레드 풀(Thread Pool)처럼 공유되는 리소스를 관리할 때 사용됩니다.
4. 자바로 싱글톤 패턴 구현하기
(1) 싱글톤 패턴 기본 구현
public class Singleton {
// 클래스 내부에 단일 인스턴스를 static으로 선언
private static Singleton instance;
// 생성자를 private으로 설정하여 외부에서 new 키워드로 인스턴스 생성 불가능
private Singleton() {
System.out.println("Singleton Instance Created!");
}
// public 메서드를 통해 인스턴스를 제공
public static Singleton getInstance() {
if (instance == null) { // 최초 호출 시에만 인스턴스를 생성
instance = new Singleton();
}
return instance;
}
}
(2) 사용 방법
public class Main {
public static void main(String[] args) {
// 싱글톤 인스턴스 가져오기
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
// 동일한 인스턴스인지 확인
System.out.println(singleton1 == singleton2); // true
}
}
5. 개선된 싱글톤 패턴
(1) 멀티스레드 환경에서의 문제
위 기본 구현은 멀티스레드 환경에서 안전하지 않습니다.
- 두 개 이상의 스레드가 동시에 getInstance()를 호출하면, 인스턴스가 두 번 생성될 수 있습니다.
(2) 해결 방법: 스레드 안전한 싱글톤 구현
방법 : 동기화 (Synchronized)
public class Singleton {
private static Singleton instance;
private static Object _locking = new Object();
private Singleton() { }
public static Singleton getInstance() {
// 첫 번째 검사
if (instance == null) {
synchronized (_locking) { // 잠금
// 두 번째 검사
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
위 코드는 DCL(Double-Checked Locking, 이중 검사 잠금) 기법을 활용하여 멀티스레드 환경에서 안전하게 싱글톤 인스턴스를 생성하는 방식입니다.
DCL(Double-Checked Locking)의 핵심 원리
- 첫 번째 검사 (if (instance == null))
- 이미 인스턴스가 생성되어 있다면, 굳이 synchronized 블록에 들어가지 않습니다.
- 이렇게 하면 불필요한 성능 저하를 방지할 수 있습니다.
- 두 번째 검사 (if (instance == null) 내부)
- synchronized 블록 안에서 다시 _instance == null인지 확인합니다.
- 이는 여러 스레드가 동시에 첫 번째 검사를 통과했을 때, 중복된 인스턴스 생성을 방지하기 위해 필요합니다.
- synchronized 키워드
- 특정 스레드가 synchronized 블록 안으로 들어가면 다른 스레드는 대기하게 됩니다.
- 이렇게 하면 인스턴스 생성 과정이 여러 스레드에 의해 중복 실행되지 않도록 보장합니다.
반응형