안녕하세요 Ruel입니다.
이번 시간에는 Design Pattern 중 하나인
Singleton에 대하여 간단하게 알아봅시다.

레츠 꼬우
일단 애플 문서에 나와있는 Singleton을 봐볼까요?
Managing a Shared Resource Using a Singleton
- 단일 공유 클래스 인스턴스를 사용하여 공유 리소스에 대한 액세스를 제공함.
- 싱글톤을 만들어서 앱 전체에 공유되는 자원이나 서비스에 통합된 접근을 제공할 수 있음.
- ex) 사운드효과를 재생하는 오디오 채널이나 HTTP Requests를 네트워크 매니저로 싱글톤으로 만들 수 있음
싱글톤 만들기
- 간단한 싱글톤을 만들려면 static 타입 프로퍼티를 사용함
- 이는 여러 스레드에서 동시에 접근하더라도 한 번만 생성할 수 있도록 해줌
class Singltone {
static let shared = Singleton()
}
- 초기화 외 추가 설정이 필요한 경우, 클로처를 호출하여 전역 상수에 할당해 줄 수도 있음.
class Singleton {
static let shared: Singleton {
let instance = Singleton()
//추가 설정 코드
return instance
}
}
이렇게 여기까지 간단하게 애플 문서에 나와있네요.
이거 가지고는 부족하죠
더 알아봅시다.
1. Singleton pattern (싱글톤)이란?
싱글톤 패턴이랑,
객체를 하나만 생성하여, 언제 어디서든지 공용으로 사용하고 싶을 때 사용되는 디자인 패턴이에요.
Q) 싱글톤 패턴이 왜 필요해요??
A) 앱을 구현할 때, 유일하게 한 개만 존재하는 객체가 필요할 경우 사용해요.
즉, 한번 생성된 이후 앱이 종료될 때까지, 유일한 객체로 메모리에 상주해요(힙 영역에서~)
Singleton은 접근하는 순간 Lazy 하게 동작하여, 메모리에 올라가요
2. Singleton pattern 생성 방법
class Singleton {
static let shared = Singleton()
private init() {}
func doSomething() {
//싱글톤 객체에서 동작해야할 것들
}
}
static let 이름 = 객체 생성()
//데이터 영역에 유일한 객체의 주소가 담겨 있음
//자기 자신을 초기화하여, static let 변수에 할당
//앱이 실행되는 동안, (데이터 공유등) 유일하게 1개만 필요로 하는 객체일 때 사용
//한번 생성이 되면, 앱이 종료될 때 까지 1개의 객체로써 메모리에 상주
// 다만, 실제 static변수로 선언된 것은 접근시에만 지연(lazy)속성처럼 동작
// 외부에서, 또다른 새로운 객체를 생성하지 못하도록 private init 메서드로 선언
Singleton.shared.doSomething()
//이와 같이 사용 가능
- private를 활용하여 생성자를 구현하면 이후 새로 객체를 생성할 수 없음.
- private Init() {} 를 해주게 된다면 새로운 객체를 생성하는 것을 방지할 수 있음
3. Singleton pattern의 장단점
장점
- 어디서든지 동일한 인스턴스에 접근할 수 있어요.
다른 객체들이 싱글톤 객체에 접근하여 데이터를 공유하거나 동작을 할 수 있죠.
즉, 전역적으로 접근 가능해요 - 싱글톤 객체는 한 번 생성된 후 재사용되므로, 같은 인스턴스를 여러 번 생성하지 않아도 돼요.
따라서 리소스를 줄일 수 있어요
단점
- 싱글톤 객체는 전역적으로 접근 가능해서 의존성을 관리하기 힘들어요.
의존성 관리가 힘들기 때문에 테스트 및 유지보수가 어려워질 수 있어요 - 싱글톤은 전역적으로 공유되어 사용되기 때문에 상태관리가 힘들 수 있어요
따라서 생각지 못한 동작을 하게 만들 수 도 있죠 - 싱글톤은 여러 스레드에서 동시에 접근할 경우 동기화에 문제가 있을 수 있기 때문에 추가적으로 해당 사항에 대한 방어 코드가 필요해요
4. iOS 내부에서 기본적으로 제공되는 Singleton은 무엇이 있을까?
1. UserDefaults
- 사용자 설정 및 앱 데이터를 저장하는 데 사용되는 UserDefaults.
앱 전체에서 접근하고 수정할 수 있도록 단일 인스턴스를 제공해요
let defaults = UserDefaults.standard
defaults.set("Hello", forKey: "Greeting")
let greeting = defaults.string(forKey: "Greeting")
2. NotificationCenter
- 앱 내에서 이벤트를 전달하는 데 사용되는 NotificationCenter
다양한 객체 간의 통신을 가능하게 하고, 단일 인스턴스를 통해 전체 앱에서 이벤트를 관리해요
let notificationCenter = NotificationCenter.default
notificationCenter.post(name: Notification.Name("CustomNotification"), object: nil)
notificationCenter.addObserver(self, selector: #selector(handleNotification), name: Notification.Name("CustomNotification"), object: nil)
3. FileManager
- 파일 시스템과의 상호작용을 관리하는 FileManager.
파일 및 디렉터리의 생성, 삭제, 이동 등의 작업을 수행할 수 있는 단일 인스턴스를 제공해요.
let fileManager = FileManager.default
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
4. UIApplication
- 앱의 전체 수명주기를 관리하는 UIApplication.
앱의 상태 변화에 대응하고, 앱 수준의 설정 및 동작을 제어하는 단일 인스턴스를 제공해요.
let app = UIApplication.shared
app.isNetworkActivityIndicatorVisible = true
5. URLSession
- 네트워크 데이터 작업을 처리하는 URLSession
HTTP 요청을 보내고 응답을 받는 작업을 수행할 수 있는 단일 인스턴스를 제공해요.
let session = URLSession.shared
let url = URL(string: "https://api.example.com/data")!
let task = session.dataTask(with: url) { data, response, error in
// 데이터 처리 코드
}
task.resume()
이렇게 iOS 기본 프레임워크 내부에서도 다양한 싱글톤 패턴을 사용하고 있어요.
장점도 많고 단점도 있는 싱글톤 패턴 매우 유용하게 사용할 수 있지만, 남용하지 않도록 해야 해요.
필요한 경우에만 사용해야 하고, 그렇지 않다면 다른 방법을 고려하는 것도 하나의 방법이 될 수 있을 것 같아요.
이미 알고 사용하고 있는 Singleton에 대하여 알아보았는데요.
늘 그렇듯 알고 있어도 설명하려면 넘나 어려운 거....
그래도 장단점은 알고 사용해야겠다 싶어서 정리를 해보았어요.
잘못된 부분 혹은 추가적으로 알려주실 부분 있으시면 언제든지 댓글 남겨주세요.💬
감사합니다.🙇🏻♂️
'iOS > Swift' 카테고리의 다른 글
Swift] Property Observer (0) | 2024.08.10 |
---|---|
DI(Dependency Injection) - 의존성 주입 (0) | 2024.08.10 |