728x90

싱글턴(Singleton)이라는 것은 디자인 패턴의 가장 기초적인 패턴이다.

하지만 이 패턴이라는 것은 사실상 딱 부러지는 코드를 제공하는 것은 아니고 코드라는게 항상 그렇지만 100% 정답은 없다.


그 중에서 싱글턴은 아래의 조건만 맞춰 진다면 개인적으로 "어떠한" 방법을 쓰든 싱글턴이라고 부르는게 맞다고 생각한다.

1. Process내에서 단 한 개만 생성되는 것을 보장하며, 그것을 표현할 수 있을 것.

2. 사용하는 시점이 생성되는 시점일 것.


싱글턴과 전역 변수가 비슷하지만 차이 점을 하나씩 비교해보자. 

싱글턴은 Process내에서 단 한개만 생성이 된다는 것을 보장함과 동시에 표현이 가능하다는 점에 있어서 전역 변수로는 표현하기 힘든 부분이라는 것에 싱글턴의 존재성을 깨닫게 된다.


아래 예제를 보자.


그림 - 싱글턴인듯 아닌듯 한 기본 예제


위의 코드는 처음 싱글턴을 공부할 때 항상 만들어보는 예제 일 것이다. 하지만 이것만으로는 이것이 단 한개 만을 가지는지는 보장이 되지 않는다. 왜냐하면 생성자와 소멸자가 private이나 protected로 보호되지 않고 public으로 선언되어 있기 때문이다.

한마디로 굳이 CreateInstance()를 사용하지 않고 직접 new나 delete로 생성 및 삭제가 외부에서 가능해지기 때문이다. 



그림 - 싱글턴 기본 예제 1


이렇게 생성자와 소멸자를 private으로 외부에서 접근하지 못하도록 보호를 한다면, 


CSingleton* pTest = new CSingleton();

delete pTest;


위의 코드는 컴파일 단계에서 에러가 날 것이다. private이기 때문에 생성도 할 수 없고, 삭제도 할 수 없기 때문이다.

하지만, 위 처럼 싱글턴을 생성하면 static 객체는 생성의 시점이 명확하게 정의되지 않기 때문에, 다른 전역 객체에서 이를 참조하고자 할 때 생성 순서 때문에 문제가 발생할 수 있다. 그래서 new를 이용하여 생성하는 것이 더 안전해 보인다.


자 이번엔 new를 이용해서 싱글턴을 만들어보자.



위의 방법은 처음에 말했던 조건에 모두 부합한다. 사용하기 위해 CreateInstance()를 하는 순간 생성되고, 원하는 시점에 삭제가 가능하다. 


만약 CreateInstance()가 동시에 여러 곳에서 호출될까봐 무서운 사람은 Singleton 전용 Mutex를 하나 만들어서 사용하는 것도 괜찮은 방법일 것이다.


여기서, 조금 생각 해볼 것은 new로 생성한 인스턴스를 굳이 삭제해야 하는 것이다. 프로그램이 종료되는 시점에는 어차피 new로 생성한 메모리까지 전부 해제가 된다. 따라서, 어차피 생성한 목적이 프로그램 종료시까지 단 하나의 객체가 동작하는 것이라면 그 크기가 어마어마한 것이 아니라면 명시적으로 메모리 해제를 수행할 필요는 없다는 것이다. 하지만, 만약의 상황을 대비해 해제 함수를 하나 만들어 두는게 더 나아 보이긴 하다.... (어려운 작업이 아니니....)



이 싱글턴은 멀티 쓰레드에서는 안전하지 않다... 

728x90

+ Recent posts