싱글톤 패턴

  • 싱글톤은 단 한번, 단 하나의 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 해도 되거나 혹은 그래야만 하는 경우가 아니라면 클래스를 써야한다는 결론이다.

참고