1. 디자인 패턴
소프트웨어 설계 시 반복적으로 발생하는 문제들을 해결하기 위한 일반적인 해결책이다.
이는 코드에서 반복되는 설계 문제를 해결하기 위한 청사진으로 볼 수 있다.
2. 싱글톤 패턴(Singleton Pattern)
- 특정 클래스의 인스턴스를 오직 하나만 생성.
- 인스턴스를 전역적으로 접근할 수 있도록 하는 디자인 패턴.
- 프로그램 전체에서 동일한 객체를 공유하여 메모리 낭비를 방지, 데이터 일관성 유지.
- 보통 데이터베이스 연결 모듈에 많이 사용.
3. JavaScript의 싱글톤 패턴
class Singleton{
constructor(){
if(!Singleton.instance){
Singleton.instance = this
}
return Singleton.instance
}
getInstance(){
return this
}
}
const a = new Singleton()
const b = new Singleton()
console.log(a===b)
코드 분석
1. 클래스 선언: Singleton이라는 클래스를 정의
2. constructor() === 생성자 메서드
- 인스턴스를 생성할 때 호출.
if(!Singleton.instance)조건문을 통해Singleton.instance가 존재하지 않으면 현재 인스턴스(this)를Singleton.instance에 할당.- 그 후에,
Singleton.instance를 반환.
3. getInstance 메서드: 현재 인스턴스(this)를 반환.
4. const a와 const b를 통해 인스턴스를 생성하여 테스트.
실행 과정
1. 첫번째 인스턴스 생성(const a)
new Singleton()을 호출하면constructor()실행.Singleton.instance가 아직 정의되지 않았으므로, 조건문이true가 되어 현재 인스턴스(this)가Singleton.instance에 할당.
2. 두번째 인스턴스 생성(const b)
- 다시
new Singleton()을 호출하면constructor()실행. - 이번에는
Singleton.instance가 이미 존재하므로, 조건문이false가 되어 새로운 할당 없이 기존의Singleton.instance반환. - 따라서,
const b는 기존의Singleton.instance(=a와 같은 인스턴스)를 참조.
3. 인스턴스 비교(a===b)
a와b모두 동일한Singleton.instance를 참조하므로,a===b는true를 출력.
4. Java의 싱글톤 패턴
class Singleton{
private static class singleInstanceHolder{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return singleInstanceHolder.INSTANCE;
}
}
public class HelloWorld{
public static void main(String[] args){
Singleton a = Singleton.getInstance();
Singleton b = Singleton.getInstance();
System.out.println(a.hashCode());
System.out.println(b.hashCode());
if(a==b){
System.out.println(true);
}
}
}
코드 분석
1. Singleton 클래스
SingleInstanceHolder클래스는Singleton클래스 내부에 정적(static)으로 선언된 클래스- 이 클래스는
INSTANCE라는 정적 상수 필드를 가지며, 이는Singleton클래스의 유일한 인스턴스를 생성. getInstance()메서드는SingleInstanceHolder.INSTANCE를 반환하는 정적 메서드로, 이를 통해Singleton인스턴스에 접근.
2. HelloWorld 클래스
Singleton인스턴스를 두 번(a와 b) 가져와 해시 코드를 출력하고, 동일 비교.
실행 과정
1. Singleton.getInstance() 호출
Singleton.getInstance()를 처음 호출하면,SingleInstanceHolder클래스가 로드되고 초기화.- 이때,
SingleInstanceHolder의 정적 필드인INSTANCE가 초기화 되면서Singleton의 인스턴스가 생성.
2. a와 b에 동일한 인스턴스 할당
a와b모두Singleton.getInstance()를 호출하여 동일한Singleton인스턴스를 받음.
3. 해시 코드 출력 및 인스턴스 비교 테스트
5. 싱글톤 패턴의 장단점
장점
- 메모리 효율성: 한 번의 인스턴스 생성으로 고정된 메모리 영역을 사용하므로, 메모리 낭비를 방지.
- 전역 접근성: 싱글톤 인스턴스는 전역적으로 접근 가능하여, 여러 클래스에서 데이터를 공유하기 용이.
- 리소스 관리 용이성: 데이터베이스 연결 풀(DBCP)처럼 공통된 객체를 여러개 생성해야 하는 상황에서 유용.
단점
- 테스트 어려움: 단위 테스트는 테스트가 서로 독립적이고, 테스트를 어떤 순서로든 실행할 수 있어야 하는데 싱글톤은 전역 상태를 유지하므로, 독립성이 떨어져 테스트가 어려움.
- 멀티스레드 환경에서의 문제: 동기화 처리를 하지 않으면 멀티스레드 환경에서 인스턴스가 여러 개 생성될 수 있음.
- 높은 결합도: 싱글톤 인스턴스를 여러 *모듈이 공유하면 모듈 간 의존성이 높아져 유지보수가 어려움.
- 전역 상태로 인한 문제: 전역 상태를 가지므로, 프로그램의 상태를 추적하고 관리하기 어려움.
높은 결합도 해결 방법 => 의존성 주입(DI, Dependency Injection) 활용 => 모듈간의 결합을 느슨하게 만듬
*모듈: 하나의 기능을 담당하는 코드 단위(클래스, 패키지, 라이브러리, 프레임워크의 일부 등)
6. 의존성 주입의 장점
장점
- 모듈들을 쉽게 교체할 수 있는 구조가 되어 테스트하기 쉽고, 마이그레이션하기도 수월.
- 구현할 때 추상화 레이어(인터페이스 or 추상 클래스)를 넣고 이를 기반으로 구현체를 넣어주기 때문에 의존성 방향 일관, 쉽게 추론, 모듈간 관계 명확.
단점
- 모듈들이 더욱더 분리되므로 클래스 수가 늘어나 복잡성 증가.
- 약간의 런타임 페널티.
7. 의존성 주입 원칙
- 상위 모듈은 하위 모듈에서 어떠한 것도 가져오지 않아야 함.
- 둘 다 추상화에 의존.
- 추상화는 세부 사항에 의존하지 않아야 함.
8. 싱글톤 패턴을 써야 하는 이유
- 인스턴스의 유일성 보장
- 프로그램에서 특정 클래스의 인스턴스를 단 하나만 유지해야 하는 경우가 많음 !
- ex) 데이터베이스 연결 객체, 설정 관리 객체, 로그 기록 객체 등은 단 하나의 인스턴스만 있어야함 !
- 메모리 효율성
- 여러개의 동일한 객체를 생성하는 것은 불필요한 메모리 낭비를 초래..
- 싱글톤 패턴을 사용하면 한번만 인스턴스를 생성하고, 이후에는 기존 인스턴스를 재사용해서 메모리 사용량을 절약할 수 있음 !
- 전역 데이터 공유 및 관리 용이
- 프로그램 전반에서 하나의 객체를 공유하면, 여러 클래스가 동일한 데이터를 공유하고 활용하기 쉽다 !
- ex) 애플리케이션의 설정값(Configuration)을 저장하는 객체를 싱글톤으로 만들면, 여러 클래스가 이를 편리하게 접근할 수 있음 !
- 리소스 관리 용이성
- 데이터베이스 연결 풀(DBCP)이나 캐시 시스템 같은 리소스 관리 객체는 여러개의 인스턴스를 만들면 비효율적 일수도 있음
- 싱글톤 패턴을 사용하면 공통된 리소스를 효율적으로 관리할 수 있다 !
- 의존성 주입(DI)과의 조합으로 높은 결합도 문제를 해결
- 싱글톤 패턴의 문제점 중 하나는 높은 결합도로 인해 모듈 간 의존성이 커질 수 있다는 점이다.
- 하지만 의존성 주입을 활용하면, 싱글톤 객체를 직접 생성하지 않고 주입받는 방식으로 결합도를 낮출 수 있다 !
- ex) 싱글톤 객체를 직접 참조하는 것이 아니라, 인터페이스를 사용하여 DI 컨테이너를 통해 객체를 주입 받으면 유지보수 쉬워짐 !
9. 싱글톤 패턴을 적용해야 하는 대표적인 경우
- 애플리케이션 설정 관리
- 데이터베이스 연결 객체
- 로깅 시스템
- 캐싱 시스템
- 스레드 풀 관리
10. 결론
싱글톤 패턴은 프로그램에서 단 하나의 인스턴스를 유지해야 할 때 필수적인 디자인 패턴이다.
메모리 절약, 데이터 공유, 리소스 관리의 용이성 등의 장점이 있어서 데이터베이스 연결 객체, 설정 관리, 로깅 시스템 등에서 널리 사용된다.
하지만 멀티스레드 환경에서의 동기화 문제, 높은 결합도 문제, 테스트의 어려움 같은 단점도 존재한다.
이러한 단점은 의존성 주입(DI)을 활용하여 싱글톤 패턴을 보다 유연하게 설계함으로써 해결할 수 있다.
'Computer Science > Design Pattern' 카테고리의 다른 글
| 이터레이터 패턴(Iterator Pattern) (0) | 2025.03.21 |
|---|---|
| 프록시 패턴(Proxy Pattern) (0) | 2025.03.19 |
| 옵저버 패턴(Observer Pattern) (1) | 2025.03.19 |
| 전략 패턴(Strategy Pattern) (1) | 2025.03.18 |
| 팩토리 패턴(Factory Pattern) (0) | 2025.03.17 |
