λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
  • Dev Blog
CS/λ””μžμΈ νŒ¨ν„΄

[GoF λ””μžμΈ νŒ¨ν„΄] - 싱글톀 νŒ¨ν„΄

by μœ μ§„μ˜ 2024. 6. 4.

 

λͺ¨λ“  μ½”λ“œλŠ” Swift둜 μž‘μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

 

문제 상황

데이터λ₯Ό 읽고 μ“°λŠ” 역할을 ν•˜λŠ” 객체가 있고 μ½”λ“œμ˜ μ—¬λŸ¬ κ³³μ—μ„œ 이 객체λ₯Ό μ‚¬μš©ν•œλ‹€κ³  κ°€μ •ν•΄ 보자. 각각의 μ½”λ“œ μ˜μ—­μ—μ„œ 이 객체의 μΈμŠ€ν„΄μŠ€λ₯Ό 일일이 μƒμ„±ν•œλ‹€λ©΄ 두 가지 문제점이 λ°œμƒν•  수 μžˆλ‹€.

 

첫째, λͺ¨λ“  μ½”λ“œ μ˜μ—­μ—μ„œ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό 계속 μƒμ„±ν•˜κΈ° λ•Œλ¬Έμ— λ©”λͺ¨λ¦¬κ°€ 많이 μ‚¬μš©λœλ‹€.

λ‘˜μ§Έ, ν•˜λ‚˜μ˜ μ½”λ“œ μ˜μ—­μ—μ„œμ˜ μž‘μ—… κ²°κ³Όκ°€ λ‹€λ₯Έ μ½”λ“œ μ˜μ—­μ— κ³΅μœ λ˜μ§€ λͺ»ν•  수 μžˆλ‹€. 즉, A μ½”λ“œ μ˜μ—­μ—μ„œ 데이터λ₯Ό μ €μž₯μ‹œμΌœ λ†¨μ§€λ§Œ, B μ½”λ“œ μ˜μ—­μ—μ„œλŠ” μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν–ˆκΈ° λ•Œλ¬Έμ— A μ˜μ—­μ—μ„œ μ €μž₯μ‹œμΌ°λ˜ 데이터에 μ ‘κ·Όν•  수 없을 것이닀.

 

싱글톀 νŒ¨ν„΄

싱글톀 νŒ¨ν„΄μ€ μ‘μš© ν”„λ‘œκ·Έλž¨ 전체에 걸쳐 μœ μΌν•œ 객체λ₯Ό λ§Œλ“€μ–΄ μ „μ—­μ μœΌλ‘œ 데이터 곡유λ₯Ό ν•  수 있게 ν•΄μ£ΌλŠ” λ””μžμΈ νŒ¨ν„΄μ΄λ‹€.

 

μ½”λ“œ μ˜ˆμ‹œ

class DataStorage { // 싱글톀 객체
    static let shared = DataStorage() // 유일 객체에 μ ‘κ·Όν•  수 μžˆλŠ” static ν”„λ‘œνΌν‹°
    private var someData = 0

    private init() {} // μ΄ˆκΈ°ν™”λ¬Έμ„ private으둜 μ„€μ •ν•¨μœΌλ‘œμ¨ 유일 객체 보μž₯

    func setData(data: Int) {
        someData = data
    }

    func getData() -> Int {
        return someData
    }
}

class A {
    func setData(data: Int) {
        DataStorage.shared.setData(data: data) 
    }
}

class B {
    func getData() {
        let data = DataStorage.shared.getData()
        print(data)
    }
}

let a = A()
let b = B()

a.setData(data: 2)
b.getData() // 2

 

 

μž₯점

 

λ‹€μ–‘ν•œ κ°μ²΄λ“€μ—κ²Œ μžμ‹ μ˜ μƒνƒœλ₯Ό κ³΅μœ ν•  수 μžˆλ‹€. λ˜ν•œ, ν•˜λ‚˜μ˜ μΈμŠ€ν„΄μŠ€λ§Œ 생성해 μž¬μ‚¬μš©ν•˜λ―€λ‘œ λ©”λͺ¨λ¦¬ λ‚­λΉ„λ₯Ό 방지할 수 μžˆλ‹€.

 

 

단점

 

SOLID 원칙에 μœ„λ°°λ˜λŠ” 사둀가 λ§Žλ‹€. μš°μ„  싱글톀 μΈμŠ€ν„΄μŠ€ μžμ²΄κ°€ ν•˜λ‚˜λ§Œ μƒμ„±ν•˜κΈ° λ•Œλ¬Έμ— μ—¬λŸ¬ 가지 μ±…μž„μ„ μ§€λ‹ˆκ²Œ λ˜λŠ” κ²½μš°κ°€ λ§Žμ•„ 단일 μ±…μž„ 원칙(SRP)을 μœ„λ°˜ν•˜κΈ°λ„ ν•˜κ³ , 싱글톀 μΈμŠ€ν„΄μŠ€κ°€ 혼자 λ„ˆλ¬΄ λ§Žμ€ 일을 ν•˜κ±°λ‚˜, λ§Žμ€ 데이터λ₯Ό κ³΅μœ μ‹œν‚€λ©΄ λ‹€λ₯Έ ν΄λž˜μŠ€λ“€ κ°„μ˜ 결합도가 λ†’μ•„μ§€κ²Œ λ˜μ–΄ 개방-폐쇄 원칙(OCP)에도 μœ„λ°°λœλ‹€. λ˜ν•œ, ν΄λΌμ΄μ–ΈνŠΈ 객체가 μΈν„°νŽ˜μ΄μŠ€κ°™μ΄ μΆ”μƒν™”λœ 객체가 μ•„λ‹Œ ꡬ체 클래슀λ₯Ό μ˜μ‘΄ν•˜λ―€λ‘œ μ˜μ‘΄κ΄€κ³„ μ—­μ „ 원칙(DIP)에도 μœ„λ°°λœλ‹€.

λ˜ν•œ, μ–΄λ””μ—μ„œλ“  μ‚¬μš©ν•  수 μžˆλ‹€λΌλŠ” μž₯점이 단점이 λ˜κΈ°λ„ ν•˜λŠ”λ°, ν•΄λ‹Ή 싱글톀 객체와 κ΄€λ ¨λœ μž‘μ—…μ—μ„œ 였λ₯˜κ°€ λ‚œλ‹€λ©΄ 이에 λŒ€ν•œ νŠΈλŸ¬λΈ”μŠˆνŒ…μ΄ μ–΄λ €μ›Œμ§„λ‹€.

 

 

πŸ“Œ Swiftμ—μ„œμ˜ 싱글톀 νŒ¨ν„΄

 

UserDefaultsλ‚˜ NotificationCenter, URLSession μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ‹€ 보면 standard, default ν˜Ήμ€ shared ν”„λ‘œνΌν‹°λ₯Ό 확인해 λ³Ό 수 μžˆλ‹€. 이 ν”„λ‘œνΌν‹°λ“€μ€ Swiftμ—μ„œ μ œκ³΅ν•˜λŠ” 싱글톀 객체의 μΈμŠ€ν„΄μŠ€λ₯Ό μ˜λ―Έν•˜λŠ” static ν”„λ‘œνΌν‹°μ΄λ‹€.

싱글톀 νŒ¨ν„΄μ˜ λ¬Έμ œμ μ€ 싱글톀 객체의 데이터 변화와 μˆ˜μ •μ΄ μ˜μ‘΄ν•˜κ³  μžˆλŠ” μ—¬λŸ¬ κ°μ²΄λ“€μ—κ²Œ 영ν–₯을 λΌμΉœλ‹€λŠ” 것인데, μ–Έμ–΄ μžμ²΄μ—μ„œ μ œκ³΅ν•΄ μ£ΌλŠ” 싱글톀 객체의 경우 큰 λ¬Έμ œλŠ” λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. ν•˜μ§€λ§Œ, 싱글톀 객체λ₯Ό 직접 λ§Œλ“ λ‹€λ©΄ κΈ°λŠ₯의 변동사항에 따라 μˆ˜μ •μ΄ 자주 λ°œμƒν•˜μ§€ μ•Šμ„ 객체인지, ν•΄λ‹Ή 객체가 κ°€μ§ˆ λ°μ΄ν„°μ˜ λ³€ν™”κ°€ 영ν–₯λ ₯이 크진 μ•Šμ„μ§€ κ³ λ €ν•΄ λ³Ό ν•„μš”κ°€ μžˆλ‹€λŠ” 사싀을 κΈ°μ–΅ν•˜μž.

λŒ“κΈ€