Bibi's DevLog π€π
[iOS] Singleton μ±κΈν€ ν¨ν΄μ΄λ 무μμ΄κ³ , λ¨μ κ³Ό λμμ 무μμΈκ°? λ³Έλ¬Έ
[iOS] Singleton μ±κΈν€ ν¨ν΄μ΄λ 무μμ΄κ³ , λ¨μ κ³Ό λμμ 무μμΈκ°?
λΉλΉ bibi 2023. 2. 14. 23:04What Is a Singleton and How To Create One In Swift
μ΄ κΈμ μμ λ λ¬Έμμ κΈ°λ°νμ¬ μ§μ μ 리ν κΈμ λλ€.π·
μ±κΈν€ ν¨ν΄μ μννΈμ¨μ΄ κ°λ°μ λ§€μ° λ리 μ¬μ©λλ λμμΈ ν¨ν΄μ΄μ§λ§, μν°ν¨ν΄μΌλ‘ κ³ λ €λμ΄μ§λ€. κ·Έ μ΄μ λ₯Ό μ΄ν΄λ³΄μ.
μ±κΈν€ ν¨ν΄μ΄λ 무μμΈκ°
μ±κΈν€ ν¨ν΄μ ν΄λμ€μ μΈμ€ν΄μ€κ° λ¨ νλλ§ μμ±λλλ‘ νλ ν¨ν΄μ΄λ€.
νλ‘κ·Έλ¨μμ μ΄λ€ μμ μμλ κ·Έ ν΄λμ€μ μΈμ€ν΄μ€λ λ± νλλ§ μ‘΄μ¬νλλ‘ λ³΄μ₯νλ κ²μ΄ μ±κΈν€ ν¨ν΄μ λͺ©μ μ΄λ€.
μλ₯Ό λ€λ©΄, μ νμ νλ μμν¬μμλ μλμ κ°μ κ°μ²΄λ€μ΄ μ±κΈν€μΌλ‘ μ¬μ©λλ€.
// Shared URL Session
let sharedURLSession = URLSession.shared
// Default File Manager
let defaultFileManager = FileManager.default
// Standard User Defaults
let standardUserDefaults = UserDefaults.standard
// Default Payment Queue
let defaultPaymentQueue = SKPaymentQueue.default()
μ μ μ κ·Ό
μ±κΈν€ ν¨ν΄μ μ μ μ κ·Ό(global access)μ΄ κ°λ₯νλ€λ νΉμ§μ΄ μμΌλ©°, μ΄κ²μ μ±κΈν€ ν¨ν΄μ λΆμμ©μ΄κΈ°λ νλ€.
μ μ μ κ·Όμ βνλ‘μ νΈμ λͺ¨λ κ°μ²΄κ° μ΄ κ°μ²΄μ μ κ·Όν μ μμβμ μλ―Ένλ€. μ΄κ²μ νΈλ¦¬νμ§λ§ κ·Έλ§νΌμ λΆμμ©μ΄ λ°λ₯Έλ€.
μ±κΈν€ ν¨ν΄μ μ΄λ»κ² λ§λλκ°
static
ν€μλλ₯Ό μ¬μ©ν΄ λ§λ€ μ μλ€.
μ±κΈν€ λ§λ€κΈ° - (1) static νλ‘νΌν°μ private μμ±μ
class NetworkManager {
// MARK: - Properties
static let shared = NetworkManager(baseURL: API.baseURL)
// MARK: -
let baseURL: URL
// Initialization
private init(baseURL: URL) {
self.baseURL = baseURL
}
}
- μμ±μκ° privateμ΄λ€.
- μ€μ§ ν΄λμ€ μκΈ° μμ λ§μ΄ μμ μ μΈμ€ν΄μ€λ₯Ό μμ±ν μ μλ€.
shared
λΌλ μ΄λ¦μ static μμ νλ‘νΌν°λ‘ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό μμ±νλ€.- μ΄ νλ‘νΌν°λ₯Ό ν΅ν΄ λ€λ₯Έ κ°μ²΄λ€μ΄ μ±κΈν€ κ°μ²΄μ μ κ·Όν μ μλ€.
- static νλ‘νΌν°λ μ΄λ―Έ lazyλ‘ λμνλ―λ‘,
lazy
ν€μλκ° νμμλ€.
μ¬μ©νκΈ° (1)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
print(NetworkManager.shared)
return true
}
μ±κΈν€κ°μ²΄.shared
μ κ°μ΄ μ¬μ©νλ©΄ λλ€.
μ±κΈν€ λ§λ€κΈ° - (2) private static ν΄λ‘μ μ class λ©μλ
class NetworkManager {
// MARK: - Properties
private static var sharedNetworkManager: NetworkManager = {
let networkManager = NetworkManager(baseURL: API.baseURL)
// Configuration
// ...
return networkManager
}()
// MARK: -
let baseURL: URL
// Initialization
private init(baseURL: URL) {
self.baseURL = baseURL
}
// MARK: - Accessors
class func shared() -> NetworkManager {
return sharedNetworkManager
}
}
μμ λ°©λ²λ³΄λ€ μ½κ° λ 볡μ‘ν λ°©μμ΄λ€.
- private static propertyλ₯Ό ν΄λ‘μ λ‘ μμ±
- μ±κΈν€ κ°μ²΄μ μ΄κΈ°νλ₯Ό ν΄λ‘μ λ΄μμ μ§ννλ€. μ΄λ₯Ό ν΅ν΄ μ±κΈν€ κ°μ²΄μ λν λ 볡μ‘ν μ΄κΈ°νμ ꡬμ±μ ν μ μλ€.
shared()
ν΄λμ€ λ©μλλ₯Ό ν΅ν΄ μ±κΈν€ κ°μ²΄μ μ κ·Όν μ μλ€.
μ¬μ©νκΈ° (2)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
print(NetworkManager.shared())
return true
}
μ±κΈν€κ°μ²΄.shared()
μ κ°μ΄ μ¬μ©νλ©΄ λλ€.
μ±κΈν€ ν¨ν΄μ λ¨μ - νΈμμ± λλ¬Έμ ν¬λͺ μ±μ ν¬μνλ€
μ±κΈν€μ μ¬μ©νλ©΄ λ°λμ νΈμμ± λλ¬Έμ ν¬λͺ μ±μ ν¬μνκ² λλ€.
μννΈμ¨μ΄μμ βνΈμμ±βμ μ°μ μμ μμμ μ‘΄μ¬νμ§ μλλ€. μ¦ νΈμμ±λ³΄λ€ ν¬λͺ μ±μ΄ λ μ€μνλ€.
μλ₯Ό λ€μ΄ νλ‘μ νΈ λ΄μμ μ¬μ©μ κ΄λ¦¬λ₯Ό ν΄μΌ νλ€κ³ μκ°ν΄ 보μ.
μ¦ μ¬μ©μ κ°μ²΄κ° μμ±λκ³ κ΄λ¦¬λμ΄μΌ νλ€.
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ μ±κΈν€ ν¨ν΄μ μ¬μ©νλ€λ©΄ - ν λ²μ μ€μ§ ν λͺ μ μ¬μ©μλ§μ΄ λ‘κ·ΈμΈν μ μλ€.
μ±κΈν€ ν¨ν΄μ μ¬μ©νλ κ²μ΄ λ λμ λλ μμ§λ§, λ¨μ μ΄ μ₯μ λ³΄λ€ ν¨μ¬ λ§λ€. μ²μμλ λ¨μ μ΄ λ§€μ° λ―Έλ¬νκΈ° λλ¬Έμ, λ§μ κ°λ°μλ€μ΄ μ±κΈν€ ν¨ν΄μ μλͺ» μ¬μ©νκ² λλ€.
μ±κΈν€ ν¨ν΄μ κ°μ₯ μ€μν λ¨μ μ νΈμμ± λλ¬Έμ ν¬λͺ μ±μ ν¬μνλ€λ κ²μ΄λ€. μ§λ μμ μ κ°μ΄, μκ°μ΄ μ§λ μλ‘ μ±κΈν€ κ°μ²΄μ μ κ·Όνλ κ°μ²΄λ₯Ό μΆμ ν μ μκ² λλ€. κ·Έλ¦¬κ³ , λ μ€μν κ²μ, μ±κΈν€ κ°μ²΄μ νλ‘νΌν°λ₯Ό μμ νλ κ°μ²΄λ€λ μΆμ ν μ μκ² λλ€.
νλ‘μ νΈμμ μ±κΈν€ κ°μ²΄λ₯Ό μ¬μ©νλ©΄μ λΉμ μ κΈ°μ λΆμ±(technical debt)λ₯Ό λ§λ€κΈ° μμνκ² λλ€. μ±κΈν€μ μ κ·ΌνκΈ° λ무 μ½κΈ° λλ¬Έμ λ°μ΄λ¬μ€μ²λΌ νΌμ Έλκ°λ κ²½ν₯μ΄ μλ€. μ±κΈν€ κ°μ²΄κ° μ΄λμμ μ°μ΄κ³ μλμ§ μΆμ νλ κ²μ μ΄λ €μ°λ©°, ν¬κ³ 볡μ‘ν νλ‘μ νΈμμ μ±κΈν€μ μ κ±°νλ κ²μ 리ν©ν λ§ μ§μ₯μ΄ λ μ μλ€. μ±κΈν€ ν¨ν΄μ΄ ν λ² νλ‘μ νΈμ μ¬μ©λκΈ° μμνλ©΄, λ λ§μ μ±κΈν€ μμ΄ νλ‘μ νΈλ₯Ό λμκ°κ² νλ κ²μ΄ μ΄λ €μμ§λ€.
μ±κΈν€μ λ λ€λ₯Έ λ¨μ μ ν μ€νΈμ΄λ€. μ±κΈν€ κ°μ²΄μ μμ‘΄νλ κ°μ²΄λ κ°ν κ²°ν©μΌλ‘ μΈν΄ λ¨μ ν μ€νΈκ° μ΄λ €μμ§λ€.
μ±κΈν€ ν¨ν΄μ μ‘°κΈ λ ν¬λͺ νκ² μ¬μ©νλ λ²
μ±κΈν€ κ°μ²΄λ₯Ό νμλ‘ νλ κ°μ²΄μκ² μμ‘΄μ± μ£Όμ λ°©μμΌλ‘ μ±κΈν€ κ°μ²΄λ₯Ό μ λ¬νλ©΄ μ’λ ν¬λͺ νκ² μ¬μ©ν μ μλ€.
ν΄λμ€μ μΈν°νμ΄μ€κ° μμ μ μμ‘΄μ±μ μ€λͺ νκ² λκΈ° λλ¬Έμ΄λ€. μ¦, ν΄λμ€κ° μμ μ μμ±νκΈ° μν΄ μ΄λ€ κ°μ²΄λ€μ νμλ‘ νλμ§ λͺ ννκ² λ³΄μ¬μ€λ€. νλ‘μ νΈ κ΅¬μ‘°λ μ μ°νκ³ λμ¨νκ² κ²°ν©λ κ²μ²λΌ λ³΄μΌ μ μμ§λ§, μ€μ λ‘λ μ ν κ·Έλ μ§ μλ€.
μ±κΈν€ ν¨ν΄μ λμ - μμ‘΄μ± μ£Όμ (dependency injection)
μ±κΈν€μ λ체ν μ μλ κ²μ μμ‘΄μ± μ£Όμ μ΄λ€.
μμ‘΄μ± μ£Όμ μ κ°μ₯ μ€μν μ₯μ μ ν¬λͺ μ±(transparency) μ΄λ€. μ΄λ μ±κΈν€μ μ₯μ μΈ νΈμμ±λ³΄λ€ λ λμ μ₯μ μ΄λ€.
μλ₯Ό λ€μ΄, μ΄λ€ κ°μ²΄κ° μν μ μννλ λ°μ userκ°μ²΄λ₯Ό νμλ‘ νλ€λ©΄, κ·Έ userκ°μ²΄λ μμ‘΄μ±μΌλ‘μ μ£Όμ λμ΄μΌ νλ€. μ½λλ‘ μμ±νμλ©΄ μλμ κ°λ€.
class User {
var firstName = ""
var lastName = ""
}
class NetworkController {
let user: User
init(user: User) {
self.user = user
}
}
μμ‘΄μ± μ£Όμ
λ°©μμ μ€λν«μ ν΅ν΄, λͺ¨λ κ°λ°μλ€μ΄ NetworkController
λ₯Ό μ¬μ©ν λ μ ν¨ν User
μΈμ€ν΄μ€μ μμ‘΄ν κ²μμ μ μ μλ€.
μ΄λ μ°Έμ‘°λ‘ κ°μ²΄λ₯Ό μ λ¬νλ λ°©λ²(passing an object by reference)μΌλ‘λ μλ €μ Έ μλ€.
μμ‘΄μ± μ£Όμ μ λΉμ₯μ λ νΈλ¦¬ν μ§ λͺ°λΌλ, μ₯κΈ°μ μΌλ‘ ν° μ΄μ΅μ΄ λλ€. μ½λ κΈ°λ°μ λͺ νμ±μ λν΄μ£ΌκΈ° λλ¬Έμ μ΄λ€ κ°μ²΄κ° μ΄λ€ κ°μ²΄μ μμ‘΄νκ³ μλμ§λ₯Ό μ ννκ² λ³΄μ¬μ€λ€.
λν μμ‘΄μ± μ£Όμ
μ΄ λ νΈλ¦¬νλ€λ μ μ΄ μ΄μ μ΄ λκΈ°λ νλ€. λΉμ μ΄ λ μ μ€νκ² κ²°μ νλλ‘ λ§λ€κΈ° λλ¬Έμ΄λ€. NetworkController
κ°μ²΄κ° User
κ°μ²΄μ λν΄ μ§μ μ κ·Όνλ λμ , μ΄λ¦κ³Ό λΉλ°λ²νΈλ§ μ λ¬νλ κ±Έλ‘ μΆ©λΆν μλ μμ§ μμκ°? μ΄μ²λΌ μμ‘΄μ± μ£Όμ
μ νμ
μ μꡬμ¬νμ μ μνκΈ° μν λ§€μ° μ μ©ν λκ΅¬κ° λλ€.
κ²°λ‘
μ±κΈν€ ν¨ν΄ μ체μ λ³Έμ§μ μΈ λ¬Έμ κ° μλ κ²μ μλλ€. μ±κΈν€μ μ λλ‘ μ¬μ©λλ€λ©΄ λ³Έμ§μ μΌλ‘ λμμ§ μλ€.
νμ§λ§ λλΆλΆμ κ°λ°μλ€μ΄ βνΈλ¦¬ν¨βμ΄λΌλ μλͺ»λ μ΄μ λλ¬Έμ μ±κΈν€ ν¨ν΄μ μ¬μ©νλ κ²μ΄ λ¬Έμ μΈ κ²μ΄λ€. μ±κΈν€ κ°μ²΄λ μ무λ°μλ λ§μλλ‘ μ κ·ΌνλΌκ³ λ§λ κ°μ²΄κ° μλλ€.
μ±κΈν€ ν¨ν΄μ λͺ©μ μ νΈλ¦¬ν¨μ΄ μλλΌ, μ΄λ€ μμ μλ ν΄λμ€μ μΈμ€ν΄μ€κ° λ¨ νκ°λ§ μ‘΄μ¬νλλ‘ λ³΄μ₯νλ κ²μ΄λ€. μ±κΈν€μ μ¬μ©ν λλ μ΄ λͺ©μ μ λ°λμ μΌλμ λμ΄μΌ νλ€.
μ 리νμλ©΄, μ±κΈν€ ν¨ν΄μ λ§€μ° λ§€μ° μ νμ μΌλ‘ μ¬μ©λμ΄μΌ νλ€.
λ§μ½ λΉμ μ΄ μ±κΈν€ κ°μ²΄λ₯Ό λ§λλ €κ³ νλ€λ©΄, μ μ λ©μΆ°μ λ€λ₯Έ μ νμ§κ° μλμ§ μκ°ν΄λ΄μΌ νλ€. μ±κΈν€μ λ§λλ μ΄μ κ° νΈλ¦¬ν¨ λλ¬Έμ΄λΌλ©΄, μ±κΈν€μ λ§λ€μ΄μλ μλλ€.