# 싱글톤(Singleton)이란?
[정의]
- 싱글톤 클래스는 하나의 인스턴스를 사용하며 인스턴스화할 필요없이 객체에 접근하는 방법이다.
[특징]
- 프로세스당 클래스의 인스턴스는 하나만 있을 수 있다.
- 싱글톤의 객체는 해당 클래스 접근이 전역으로 제공된다. (static)
- 인스턴스에 대한 액세스는 클래스 메서드를 통해 전달되므로 개체를 만들 필요가 없습니다.
- 우리의 Singleton 클래스는 우리가 일반 Cocoa 클래스로 만든 SingletonObject라고 하며 NSObject의 하위 클래스입니다.
- 싱글톤 인스턴스를 반환하는 팩토리 메서드의 이름은 규칙에 따라 sharedClassType 형식을 갖습니다.
[사용목적]
- 싱글톤은 복잡한 소프트웨어 문제를 해결하기 위한 디자인패턴이다?
[장점]
- 초기화를 한번만 하기대문에 더 나은 메모리를 사용한다.
- 자원이 하나로 공유되어 개체당 최대인스턴스 수를 보장한다.
- 인스턴스에 대한 참조를 전역으로 제공하므로 별도의 참조를 전달할 필요가 없다.
- 고유한 자원을 캡슐화 하여 앱의 전체에서 쉽게 사용할 수 있도록한다.
[단점]
- 다중스레드의 위험이존재하기때문에 어느지점에서 접근하여 값이 바뀌는지를 모두 파악하기가 어렵다.
- 유닛 테스트가 어렵다(개체와 관련된 메서드가 밀접하게 결합되어 있는 경우 테스트 가능한 코드를 작성하는데 문제를 일으킬 수 있다.)
- 결합도가 높아져 확장성이 떨어진다.
- 객체의 참조가 완전히 투명하지 않기 때문에 사용자 추적이 어려워진다.
- 정적인 메모리를 할당한다
- 코드의 숨겨진 종속성이 존재할 수 있다.
[Cocoa touch프레임워크에서 싱글턴이 활용된 사례는 무엇이 있을까?]
- URLSession.shared
- UserDefaults.standard
- NotificationCenter.default
- DispatchQueue.main
[결론]
싱글턴패턴을 사용하기 이전에 프로젝트의 해당클래스가 싱글톤객체인지를 먼저 파악해보는 것이 좋을 것 같다. 왜냐하면 싱글톤은 편의성을 위해 투명성을 희생하는 패턴이 될 수 있기때문이다. 일각에서는 단점이 장점보다 많다라는 얘기가있고 그 얘기안에는 사용자 추적이 어렵다는 단점과 결합도가 높아져 확장성이 떨어지고 다중 스레드에 대한 위험이 존재한다고 얘기한다. 그리고 프로젝트에 사용됨으로서 정말 적합해서 해결되기 보단 편의성으로 사용되지 않도록 조심해야한다라는 것같다. 이 패턴이 적절한지를 파악해하는 것이 중요한것같다.
야곰)디자인 패턴이란것이 그리고 어떻게 사용해야하는에 따라서 다른것이라서 좋다 나쁘다 를 판별하기는 어렵다. 정말 필요한 상황에는 싱글톤이 좋은 패턴으로 적용되기도하고 그렇지않기도함. 한번 사용해보는걸 권장함 짬밥은 괜히있는게 아니다.
[궁금한점해결]
- 싱글톤을 공부하도록 하는 야곰에 의도는 sington으로 설계되어있는 프레임워크가 존재하기때문에 알아둬라라는 의도로 학습을 시킨것
- 싱글톤을 사용하게되면 결합도가 높아지다보니 객체지향프로그래밍과 멀어지는 프로그래밍이 될 수 있지 않나요 ?
야곰답변) 실제로 싱글톤을 지양하는 분위기인것맡으나 상황에따라 정말 잘사용될 수도있음
싱글톤을 사용할때의 단점인 투명성을 해결하려면 ??
[학습활동때 알게된 점]
- 싱글톤은 class의 static인스턴스를 사용할때 초기화가된다. Like lazy
- 싱글톤은 init()을 private으로 지정해야한다. 왜냐하면 그렇게해야 init을 함부러 생성하지않고 동일한 한 인스턴스만 전달할 수 있기때문이다.
- 반드시 shared를 사용하지는 않아도된다. UIApplication.shared/ Filemanager.default/NotificationCenter.default
[야곰숙제]
# static의미 (https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#:~:text=the required modifier.-,static,because you can’t write class or final on those declarations.,-unowned)
- 인스턴스멤버가아니라 타입의 멤버임을 나타낸다.
- 클래스 내에서 static을 사용하게되면 final 클래스를 작성하는 것과 동일한 효과를 가진다. (상속을 이해한 후 static과 class를 공부한다.)
- 그러나 클래스의 상수 유형 프로퍼티는 예외이다. 이유는 static은 해당선언에 대해 class또는 final을 작성할 수 없기 때문에 정상적인 비클래스 의미를 갖는다.
# 싱글톤에서 class가아닌 static을 사용하는 이유는 상속에 대한 개념을 익힌 후에 살펴보는것이 좋을것같다고 말씀해주심 from 리뷰어(개굴)
# struct로 singleton으로 만들면 안되는 이유 (https://stackoverflow.com/questions/47906064/use-self-in-singleton-struct)
- 하나의 객체를 공유할 수 있으려면 class의 참조가 필요하기때문이다. struct는 값타입이기때문에 값을 복사하는 특성이 있다. 그래서 하나의 고유한 값을 참조할 수 있는 싱글톤과는 거리가 있다. 그래서 만약 struct로 생성된 shared의 프로퍼티를 공유해서 사용하게되면 고유한 원본이아닌 별도의 복사본을 생성하는 것이기때문에 적합하지 않다…!
# 학습활동에세 얘기한 RC와 Deinit
Class Person {
var name: String
init(name: String) {
self.name = name
}
}
# RC
[정의]
- RC란 class의 타입을 참조하고 있는 인스턴스의 수를 말함.
[특징]
- 함수 매개변수에 Person타입을 참조하고 함수를 사용하면 함수가 끝날때까지 RC가 1이 증가하고 함수가끝날때 RC가 차감된다.
- struct인 stack구조는 스코프를 벗어나면 메모리에서 사라진다. 예시로 함수는 stack구조인데 매개변수로 class타입을 받아 내부 프로퍼티의 값을 변경해준다고하면
함수 실행될때는 RC가 하나증가하고 함수가 종료될때 RC가 다시 차감됨
Deinit
[정의]
- RC가 사라지는 과정(인스턴스가 메모리에서 해제되는경우)이 Deinit임
[특징]
- Deinit을 신경써줘야하는 이유가 언제 몇날 몇시에 인스턴스가 메모리에 해제될지를 생각하고 프로그래밍을 할 수 가없기때문에 미리 class내부에서 deinit을 정의해주는것이다.
- Deinit을 사용할때는 마무리되었다는걸 알려주어야하는 상황에 사용하면 되기때문에 필수사항이 아니다.
# struct와 class 를 선택하는 기준 중 하나
- 야곰)어떠한 함수를 통해서 값을 전달할때 주소값을 줘야하면 클래스, 그냥 값을 전달해주어야하면 구조체를 선택해야하는 기준도 있음, 이게 뭐가 중요하길래 struct와 class를 나누어놨을까 ? 가 우리가 알아가야할 숙제임