Singleton 패턴이란?


Apple 공식문서에 의하면 “Provide access to a shared resource using a single, shared class instance.” 라고 적혀있습니다.

즉, 전역으로 접근가능한 공유 클래스 인스턴스 만들기 위한 패턴입니다.

프로그램 내에서 하나의 인스턴스로만 관리할 클래스에 대해 사용합니다. 싱글톤 패턴으로 구현된 클래스는 여러번 호출이 되어도 실제로 생성된 객체는 오직 한개이므로 한개의 객체로 재활용하는 패턴이라고 표현 할 수 있습니다.

현재 구현 및 사용이 어렵지 않아 가장 사용하기 쉬운 패턴이라고 저는 생각합니다.

하지만 최초 한번만 메모리를 할당하여 메모리 낭비를 방지 할수 있으면서도 호출 후 해제할 방법이 없어 남용한다면 메모리 낭비가 생길 수 있습니다.

적당히가 제일 어려운것 같습니다…


class User {

    // let으로 thread-safe하게 만들며 타입프로퍼티를 사용하여 모든 인스턴스에서 하나의 값을 공용으로 사용하게 만든다

    static let sharedInstance = User()

    var name = "ian"

    var gender = "male"

    var threadTest = [0]

    // 생성자 구문을 private으로 접근제한을 두어 외부에서 클래스에대한 접근을 막아주었습니다.

    private init() {

        print("init ###")
    }

    // 클래스를 구현할때에는 항상 deinit안에 로그를 찍어 해제 시점을 파악하는 습관은 retain cycle을 파악하는데 도움이됩니다.

    deinit {

        print("deinit ###")
    }
}


생성자 구문에 접근제한자를 두어 sharedInstance로만 접근이 가능하게 된것을 확인하실 수 있습니다.



로그를 보시면 2번 호출 되었지만 처음 호출될때만 메모리에 할당되는것을 볼 수 있으며 name의 값을 변경해보면서 하나의 인스턴스로만 값이 관리가 되는것을 확인하실 수 있습니다.


let instance = User.sharedInstance

print(instance.name)  // ian

instance.name = "iron man"


let instance2 = User.sharedInstance

print(instance2.name) // iron man


이로써 Singleton 패턴에 대해 알아보았습니다.

마지막으로 제가 싱글톤 패턴에 대해서 알지 못하였을때 앱 내에서 유저 정보를 다음과 같은 식으로 관리하였었습니다.

아래또한 하나의 구조체로 전역으로 공유 및 관리가 가능합니다.


struct User2 {

    static var name = "ian"

    static var gender = "male"

}


print(User2.name) // ian

User2.name = "thor"

print(User2.name) // thor


그렇다면 과연 두 방식은 무슨 차이를 가지는 것인지 궁금해졌습니다.

첫째로, 싱글톤 패턴을 활용하면 thread-safe 합니다. 즉, 동시적으로 여러곳에서 인스턴스에 접근을 할때 안정성을 보장해주는 것 입니다.

둘째로, 메모리가 로드되는 시점의 차이가 있습니다. 전자의 방법은 호출시에 메모리에 로드되지만 후자의 방법은 실제로 사용하지 않아도 앱 시작시에 메모리에 로드되게 됩니다.


정리 끝.