[디자인 패턴] - Singleton
by 볼빵빵오춘기Singleton 패턴
- Singleton 패턴은 클래스의 인스턴스를 단 하나만 생성하고, 그 인스턴스를 전역적으로 접근할 수 있도록 하는 디자인 패턴이다.
- 주로 전역적으로 하나의 객체만 유지해야 할 때 사용된다.
Singleton 패턴의 특징
- 하나의 인스턴스만 존재 (중복 생성 방지)
- 전역적으로 접근 가능 (getInstance() 메서드로 동일한 객체 반환)
- 객체 생성 비용 절감 (불필요한 객체 생성을 방지)
예제 코드
Eager Initialization (이른 초기화)
- 장점: 멀티스레드 환경에서 안전하다.( ⇒ synchronized 필요 없음)
- 단점: 사용하지 않더라도 클래스 로딩 시 객체가 생성된다.(⇒ 메모리 낭비 가능)
public class Singleton {
private static final Singleton instance = new Singleton(); // 미리 생성
private Singleton() {} // 외부에서 인스턴스 생성 방지
public static Singleton getInstance() {
return instance; // 항상 같은 객체 반환
}
}
Lazy Initialization (지연 초기화)
- 장점: 필요할 때 객체를 생성하여 메모리 절약된다.
- 단점: 멀티스레드 환경에서 동시 접근 시 여러 객체가 생성될 위험하다.
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) { // 객체가 없을 때만 생성
instance = new Singleton();
}
return instance;
}
}
Thread-Safe Singleton (멀티스레드 안전)
- 장점: 멀티스레드 환경에서도 안전하다.
- 단점: synchronized로 인해 성능 저하 가능성이 있다.
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() { // synchronized 추가
if (instance == null) {
instance = new Singleton();
}
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;
}
}
Bill Pugh Singleton (권장 방법)
- 장점: Lazy Initialization + Thread-Safe + 성능 최적화이다.
- 단점: 내부 정적 클래스를 사용하여 코드가 약간 복잡할 수 있다.
public class Singleton {
private Singleton() {}
private static class SingletonHelper {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHelper.INSTANCE;
}
}
Singleton 패턴의 장점
메모리 절약 (객체 1개만 생성)
동일한 객체를 계속 재사용하므로 불필요한 객체 생성을 방지하여 메모리 사용을 줄일 수 있다.
전역 인스턴스 제공 (데이터 공유 가능)
한 번 생성된 객체를 여러 클래스에서 공유하여 전역 상태 유지가 가능하다.
객체 생성을 제한하여 안정성 증가
하나의 인스턴스만 사용하므로 리소스 낭비와 예기치 않은 동작을 방지한다.
멀티스레드 환경에서 안전하게 사용 가능 (적절한 구현 시)
synchronized, volatile, Bill Pugh Singleton 등을 사용하면 멀티스레드 환경에서도 안전하게 사용 가능하다.
Singleton 패턴의 단점
테스트가 어렵다.
- 전역 상태를 유지하므로 유닛 테스트 시 객체를 재설정(reset)하기 어렵다.
- Mock 객체를 만들기 어렵다.
멀티스레드 환경에서 동기화 문제 발생 가능
적절한 동기화(synchronized, volatile)가 없으면 멀티스레드 환경에서 여러 개의 인스턴스가 생성될 수 있다.
클래스 간 강한 결합 (결합도 증가)
전역적으로 접근 가능하기 때문에 여러 클래스가 Singleton 인스턴스를 공유하면 코드의 결합도가 증가할 수 있다.
의존성 주입(DI)과 충돌 가능
- Spring 등의 DI(Dependency Injection) 환경에서는 싱글턴 객체를 관리하기 어렵다.
- 대신 Spring에서는 @Component 또는 @Bean을 이용한 싱글턴 관리가 더 적절할 수도 있다.
Singleton 패턴을 언제 사용하나?
공유 리소스 관리
- 데이터베이스 연결 (DB Connection Pool)
- 설정(Configuration) 관리 클래스
- 로깅(Logger) 시스템
멀티스레드 환경에서 공유 데이터 관리
- 캐시(Cache) 시스템
- 쓰레드 풀(Thread Pool) 관리
객체 생성 비용이 큰 경우
- 서버의 주요 컴포넌트 (예: Spring Bean, HTTP 클라이언트)
- 게임에서 전역 상태를 관리하는 매니저 클래스
정리하자면
- Singleton 패턴은 하나의 인스턴스를 유지하면서 공유 리소스를 관리할 때 매우 유용하다.
- 하지만 과도한 사용은 코드 결합도를 높이고, 테스트를 어렵게 만들 수 있으므로 신중하게 사용해야 한다.
'👩🏻💻 About 프로그래밍 > Spring, Spring boot' 카테고리의 다른 글
[디자인 패턴] - Bridge (0) | 2025.04.07 |
---|---|
[디자인 패턴] - Adapter (0) | 2025.04.07 |
[디자인 패턴] - Prototype (0) | 2025.03.25 |
[디자인 패턴] - Factory Method (0) | 2025.03.25 |
[디자인 패턴] - Builder (0) | 2025.03.25 |
블로그의 정보
Hello 춘기's world
볼빵빵오춘기