싱글턴 패턴(Singleton Pattern)은 클래스의 인스턴스가 오직 하나만 존재하도록 보장하고, 그 인스턴스에 대한 전역 접근점을 제공하는 디자인 패턴입니다. 이 패턴은 주로 전역 상태를 관리해야 할 때 사용됩니다.

싱글턴 패턴의 주요 특징
1. 단일 인스턴스: 클래스의 인스턴스가 하나만 생성됩니다.
2. 전역 접근: 인스턴스에 대한 전역 접근점을 제공합니다.
3. 지연 초기화: 필요할 때 인스턴스를 생성할 수 있습니다.
C++ 예시 코드
아래는 C++로 구현한 싱글턴 패턴의 예시입니다.
#include <iostream>
class Singleton {
private:
static Singleton* instance; // 유일한 인스턴스를 가리키는 포인터
// 생성자를 private로 설정하여 외부에서 인스턴스를 생성하지 못하도록 함
Singleton() {}
public:
// 인스턴스를 가져오는 정적 메서드
static Singleton* getInstance() {
if (instance == nullptr) { // 인스턴스가 없으면 생성
instance = new Singleton();
}
return instance;
}
// 예시 메서드
void showMessage() {
std::cout << "Hello from Singleton!" << std::endl;
}
};
// 정적 멤버 초기화
Singleton* Singleton::instance = nullptr;
int main() {
// 싱글턴 인스턴스에 접근
Singleton* singleton = Singleton::getInstance();
singleton->showMessage();
return 0;
}
코드 설명
1. private 생성자: 외부에서 인스턴스를 생성할 수 없도록 생성자를 private으로 설정합니다.
2. 정적 메서드: getInstance() 메서드는 인스턴스를 반환합니다. 인스턴스가 없으면 새로 생성합니다.
3. 정적 멤버: instance는 클래스 내부에서 인스턴스를 저장하는 정적 포인터입니다.
이 구조를 통해 프로그램 내에서 단 하나의 Singleton 인스턴스만 존재하게 됩니다. 필요할 때마다 getInstance()를 호출하여 같은 인스턴스를 사용할 수 있습니다.
위 C++ 코드를 실행하면 다음과 같은 결과가 출력됩니다:
Hello from Singleton!
코드 실행 순서는 다음과 같습니다:
1. main() 함수가 실행됩니다.
2. Singleton::getInstance() 메서드가 호출되어 Singleton 클래스의 유일한 인스턴스를 가져옵니다.
- 이때 instance 정적 멤버 변수가 nullptr이므로, 새로운 Singleton 인스턴스가 생성됩니다.
3. 생성된 Singleton 인스턴스의 showMessage() 메서드가 호출되어 "Hello from Singleton!"이 출력됩니다.
이와 같이 싱글턴 패턴을 통해 프로그램 전체에서 단 하나의 Singleton 인스턴스가 사용되는 것을 확인할 수 있습니다.
장점
1. 클래스가 하나의 인스턴트만 갖는다는 것을 확신할 수 있습니다.
2. 이 인스턴스에 대한 전역 접근 지점을 얻습니다.
3. 싱글턴 객체는 처음 요청될 때만 초기화됩니다.
단점
1. 단일 책임 원칙을 위반합니다. 이 패턴은 한 번에 두 가지의 문제를 동시에 해결합니다.
2. 또 싱글턴 패턴은 잘못된 디자인(예를 들어 프로그램의 컴포넌트들이 서로에 대해 너무 많이 알고 있는 경우)을 가릴 수 있습니다.
3. 그리고 이 패턴은 다중 스레드 환경에서 여러 스레드가 싱글턴 객체를 여러 번 생성하지 않도록 특별한 처리가 필요합니다.
4. 싱글턴의 클라이언트 코드를 유닛 테스트하기 어려울 수 있습니다. 그 이유는 많은 테스트 프레임워크들이 모의 객체들을 생성할 때 상속에 의존하기 때문입니다. 싱글턴 클래스의 생성자는 비공개이고 대부분 언어에서 정적 메서드를 오버라이딩하는 것이 불가능하므로 싱글턴의 한계를 극복할 수 있는 창의적인 방법을 생각해야 합니다. 아니면 그냥 테스트를 작성하지 말거나 싱글턴 패턴을 사용하지 않으면 됩니다.
다른 패턴들과의 관계
1. 대부분의 경우 하나의 퍼사드 객체만 있어도 충분하므로 퍼사드 패턴의 클래스는 종종 싱글턴으로 변환될 수 있습니다.
2. 만약 객체들의 공유된 상태들을 단 하나의 플라이웨이트 객체로 줄일 수 있다면 플라이웨이트는 싱글턴과 유사해질 수 있습니다. 그러나 이 패턴들에는 두 가지 근본적인 차이점이 있습니다:
- 싱글턴은 인스턴스가 하나만 있어야 합니다. 반면에 플라이웨이트 클래스는 여러 고유한 상태를 가진 여러 인스턴스를 포함할 수 있습니다.
- 싱글턴 객체는 변할 수 있습니다 (mutable). 플라이웨이트 객체들은 변할 수 없습니다 (immutable).
3. 추상 팩토리들, 빌더들 및 프로토타입들은 모두 싱글턴으로 구현할 수 있습니다.