싱글톤 패턴(Singleton Pattern)
Aug 19, 2024
싱글톤 패턴(Singleton Pattern)은 객체지향 디자인 패턴 중 하나로, 특정 클래스에 대해 하나의 인스턴스만 존재하도록 보장하며, 그 인스턴스에 접근할 수 있는 전역적인 접근점을 제공하는 패턴입니다. 이 패턴은 주로 애플리케이션 전체에서 공유해야 하는 리소스(예: 데이터베이스 연결, 설정 파일 등)에 사용됩니다.
싱글톤 패턴의 특징
- 유일한 인스턴스: 싱글톤 패턴을 적용한 클래스는 하나의 인스턴스만을 생성하며, 이 인스턴스는 전역적으로 접근할 수 있습니다.
- 전역 접근: 싱글톤 인스턴스는 전역적으로 접근할 수 있으므로, 애플리케이션의 모든 부분에서 이 인스턴스를 사용할 수 있습니다.
- 인스턴스의 수명 관리: 인스턴스의 생성과 소멸을 관리하기 때문에 메모리 관리에 유리할 수 있습니다.
싱글톤 패턴 구현 방법
Java에서 싱글톤 패턴을 구현하는 기본적인 방법을 살펴보겠습니다.
1. 고전적인 싱글톤 패턴 구현
public class Singleton {
// 유일한 인스턴스를 저장하기 위한 정적 변수
private static Singleton instance;
// 생성자를 private으로 선언하여 외부에서 인스턴스 생성 금지
private Singleton() {
// 추가적인 초기화 코드가 필요하면 여기에 작성
}
// 유일한 인스턴스를 반환하는 정적 메서드
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton(); // 인스턴스가 없으면 생성
}
return instance; // 이미 있으면 기존 인스턴스 반환
}
}
2. 스레드 안전한 싱글톤 구현
싱글톤 패턴은 멀티스레드 환경에서 동시 접근 시 문제를 일으킬 수 있습니다. 이를 방지하기 위해 스레드 안전한 구현 방법을 사용할 수 있습니다.
- synchronized 키워드 사용
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
synchronized
키워드를 사용하면 멀티스레드 환경에서 동시 접근을 방지할 수 있지만, 성능에 영향을 줄 수 있습니다.- 이른 초기화(Eager Initialization)
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
이른 초기화 방법은 클래스 로드 시점에 인스턴스를 생성하므로, 스레드 안전성을 보장할 수 있습니다. 하지만 이 방법은 클래스가 사용되지 않더라도 인스턴스가 생성된다는 단점이 있습니다.
- 이중 검사 잠금(Double-Checked Locking)
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
이 방법은 성능과 스레드 안전성 모두를 고려한 방법으로,
instance
가 null
인 경우에만 동기화를 수행하므로 성능 저하를 최소화합니다. volatile
키워드는 인스턴스 변수에 대한 변경이 다른 스레드에 즉시 반영되도록 보장합니다.3. Bill Pugh 싱글톤 구현
가장 권장되는 방법 중 하나로, 내부 정적 클래스(Inner Static Class)를 사용하는 방법입니다.
public class Singleton {
private Singleton() {}
private static class SingletonHelper {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHelper.INSTANCE;
}
}
이 방법은 클래스가 로드될 때
SingletonHelper
클래스는 로드되지 않으며, getInstance()
메서드가 호출될 때 SingletonHelper
클래스가 로드되면서 인스턴스가 생성됩니다. 이 방식은 지연 초기화(Lazy Initialization)와 스레드 안전성을 자연스럽게 제공하며, 코드도 간결합니다.싱글톤 패턴의 장단점
장점
- 단일 인스턴스 관리: 하나의 인스턴스만 존재하도록 보장하여 메모리 낭비를 줄일 수 있습니다.
- 전역적인 접근점 제공: 애플리케이션 전역에서 동일한 인스턴스를 사용하므로, 코드 일관성을 유지할 수 있습니다.
- 인스턴스의 수명 관리 용이: 인스턴스의 생성과 소멸을 명확하게 관리할 수 있습니다.
단점
- 테스트 어려움: 싱글톤 인스턴스는 전역적이기 때문에, 단위 테스트 시 서로 다른 테스트 케이스 간의 인스턴스 상태 공유로 인해 테스트가 복잡해질 수 있습니다.
- 멀티스레드 환경 문제: 스레드 안전성을 보장하지 않으면 동시 접근 시 문제를 일으킬 수 있습니다.
- 의존성 숨기기: 싱글톤 패턴을 사용하면 클래스 간의 의존성을 명시적으로 드러내지 않게 되어, 코드의 이해가 어려울 수 있습니다.
싱글톤 패턴은 신중하게 사용해야 하며, 모든 상황에 적합한 것은 아닙니다. 단일 인스턴스가 필요한 경우에만 사용하고, 멀티스레드 환경에서는 스레드 안전성을 반드시 고려해야 합니다.
Share article