싱글톤 패턴
싱글톤은 단 한번, 단 하나의 instance를 생성하여 여러 곳에서 공유되는 객체다.
고정된 메모리 영역을 얻고, 새로운 instance를 계속해서 만들지 않기 때문에 메모리 낭비를 방지할 수 있다.
하지만 한 번 생성되면 deinit이 불가능하기 때문에 남용하게 되면 문제가 발생하게 된다.
또한, 멀티쓰레드 환경에서 동기화처리를 하지 않으면 문제가 발생할 수 있다. 그럼에도 편리한 면이 많기 때문에 자주 사용하게 된다. 나또한 자주 싱글톤 패턴을 자주 쓰곤 했는데, 문득 구조체로 구현한 객체도 클래스와 별반 다르지 않게(거의 문제가 없었다) 작동하곤 했다. 단순히 구조체가 클래스보다 메모리 관리에 용이하단 이유로 웬만해선 구조체를 애용하던 편이었어서 왜 싱글톤 패턴에서 대부분 클래스를 사용하는지 의문이 생겼다. 그에 대한 해답은 다음과 같다.
class MyClassSingleton {
static let sharedInstance = MyClassSingleton()
private init(){}
var state = 5
func helloClass() { print("hello from class Singleton: \(state)") }
}
struct MyStructSingleton {
static let sharedInstance = MyStructSingleton()
private init() {}
var state = 5
func helloStruct() { print("hello from struct Singleton: \(state)") }
}
이렇게 똑같이 클래스와 구조체로 구현한 싱글톤 객체가 있다고 가정해보자. 이제 여기서 이렇게 해보자
let csi = MyClassSingleton.sharedInstance
csi.state = 42
MyClassSingleton.sharedInstance.helloClass() // 42
var ssi = MyStructSingleton.sharedInstance
ssi.state = 42
MyStructSingleton.sharedInstance.helloStruct() // 5
여기서 확연한 차이를 드러낸다.
이는 클래스와 구조체의 차이와 똑같다.
클래스는 참조 즉 메모리를 가르키지만 구조체는 그저 복사할 뿐이다.
이런 경우는 구조체로 구현된 싱글톤 객체는 사실상 싱글톤 객체라 볼 수 없다.
따라서 정말 드문 경우지만 싱글톤 객체가 그저 함수만 모아놓은 경우처럼 immuatable 해도 되거나 혹은 그래야만 하는 경우가 아니라면 클래스를 써야한다는 결론이다.