λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ₯– Bread Basics/Swift

Swift 곡식 λ¬Έμ„œ 정리 - μ΄ˆκΈ°ν™” ν•΄μ œ (Deinitialization)

by BreadDev 2025. 4. 11.
728x90

μ•ˆλ…•ν•˜μ„Έμš”. 이전 ν¬μŠ€νŒ…μ—μ„œ Swift의 μ΄ˆκΈ°ν™”(Initialization)에 λŒ€ν•΄ μ•Œμ•„λ³΄μ•˜λŠ”λ°μš”, μ˜€λŠ˜μ€ κ·Έ λ°˜λŒ€νŽΈμ— μžˆλŠ” 'μ΄ˆκΈ°ν™” ν•΄μ œ(Deinitialization)'에 λŒ€ν•΄ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€. 객체의 생λͺ…μ£ΌκΈ° λμ—μ„œ μ€‘μš”ν•œ 역할을 ν•˜λŠ” 이 κ°œλ…μ„ μ΄ν•΄ν•˜λ©΄ Swift의 λ©”λͺ¨λ¦¬ 관리λ₯Ό 더 효과적으둜 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ“Œ μ΄ˆκΈ°ν™” ν•΄μ œλž€? (What is Deinitialization?)

μ΄ˆκΈ°ν™” ν•΄μ œλŠ” 클래슀 μΈμŠ€ν„΄μŠ€κ°€ λ©”λͺ¨λ¦¬μ—μ„œ ν•΄μ œλ˜κΈ° 직전에 μˆ˜ν–‰λ˜λŠ” 정리 μž‘μ—…μž…λ‹ˆλ‹€. Swiftμ—μ„œλŠ” deinit ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 이 νŠΉλ³„ν•œ λ©”μ„œλ“œλ₯Ό μ •μ˜ν•©λ‹ˆλ‹€.

deinit {
    // 정리 μž‘μ—… μˆ˜ν–‰
}

μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문(Deinitializer): μΈμŠ€ν„΄μŠ€κ°€ λ©”λͺ¨λ¦¬μ—μ„œ ν•΄μ œλ˜κΈ° 직전에 μžλ™μœΌλ‘œ ν˜ΈμΆœλ˜λŠ” νŠΉλ³„ν•œ λ©”μ„œλ“œλ‘œ, λ¦¬μ†ŒμŠ€ 정리 μž‘μ—…μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

πŸ“Œ μ΄ˆκΈ°ν™” ν•΄μ œλŠ” μ–΄λ–»κ²Œ λ™μž‘ν•˜λ‚˜μš”?

SwiftλŠ” ARC(Automatic Reference Counting)λ₯Ό 톡해 λ©”λͺ¨λ¦¬λ₯Ό μžλ™μœΌλ‘œ κ΄€λ¦¬ν•©λ‹ˆλ‹€. 더 이상 μΈμŠ€ν„΄μŠ€λ₯Ό μ°Έμ‘°ν•˜λŠ” 곳이 μ—†μœΌλ©΄ ν•΄λ‹Ή μΈμŠ€ν„΄μŠ€λŠ” λ©”λͺ¨λ¦¬μ—μ„œ μžλ™μœΌλ‘œ ν•΄μ œλ©λ‹ˆλ‹€.

μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문의 μ£Όμš” νŠΉμ§•μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  1. 클래슀만 μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문을 κ°€μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€ (κ΅¬μ‘°μ²΄λ‚˜ μ—΄κ±°ν˜•μ€ λΆˆκ°€)
  2. ν΄λž˜μŠ€λ‹Ή ν•˜λ‚˜μ˜ μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문만 μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€
  3. νŒŒλΌλ―Έν„°λ₯Ό κ°€μ§€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€
  4. 직접 ν˜ΈμΆœν•  수 μ—†κ³ , μ‹œμŠ€ν…œμ— μ˜ν•΄ μžλ™μœΌλ‘œ ν˜ΈμΆœλ©λ‹ˆλ‹€
  5. μΈμŠ€ν„΄μŠ€κ°€ λ©”λͺ¨λ¦¬μ—μ„œ ν•΄μ œλ˜κΈ° 직전에 ν˜ΈμΆœλ©λ‹ˆλ‹€

ARC(Automatic Reference Counting): Swiftμ—μ„œ λ©”λͺ¨λ¦¬λ₯Ό κ΄€λ¦¬ν•˜λŠ” λ°©μ‹μœΌλ‘œ, μΈμŠ€ν„΄μŠ€μ— λŒ€ν•œ μ°Έμ‘°λ₯Ό μΆ”μ ν•˜μ—¬ 더 이상 μ°Έμ‘°λ˜μ§€ μ•ŠμœΌλ©΄ μžλ™μœΌλ‘œ λ©”λͺ¨λ¦¬λ₯Ό ν•΄μ œν•©λ‹ˆλ‹€.

πŸ“Œ 상속과 μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문

μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문은 상속 κ΄€κ³„μ—μ„œ νŠΉμ • μˆœμ„œλ‘œ ν˜ΈμΆœλ©λ‹ˆλ‹€:

  1. ν•˜μœ„ 클래슀의 μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문이 λ¨Όμ € ν˜ΈμΆœλ©λ‹ˆλ‹€
  2. κ·Έ λ‹€μŒ μƒμœ„ 클래슀의 μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문이 ν˜ΈμΆœλ©λ‹ˆλ‹€
  3. 이 과정은 μ΅œμƒμœ„ ν΄λž˜μŠ€κΉŒμ§€ κ³„μ†λ©λ‹ˆλ‹€

μ΄λŠ” μ΄ˆκΈ°ν™”(initialization)μ™€λŠ” λ°˜λŒ€ μˆœμ„œμž…λ‹ˆλ‹€. μ΄ˆκΈ°ν™”λŠ” μƒμœ„ ν΄λž˜μŠ€λΆ€ν„° ν•˜μœ„ 클래슀 순으둜 μ§„ν–‰λ˜μ§€λ§Œ, μ΄ˆκΈ°ν™” ν•΄μ œλŠ” ν•˜μœ„ ν΄λž˜μŠ€λΆ€ν„° μƒμœ„ 클래슀 순으둜 μ§„ν–‰λ©λ‹ˆλ‹€.

μ€‘μš”: ν•˜μœ„ ν΄λž˜μŠ€κ°€ μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문을 κ΅¬ν˜„ν•˜μ§€ μ•Šμ•„λ„ μƒμœ„ 클래슀의 μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문은 μžλ™μœΌλ‘œ ν˜ΈμΆœλ©λ‹ˆλ‹€.

πŸ“Œ μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문의 ν™œμš©

μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문은 주둜 λ‹€μŒκ³Ό 같은 μƒν™©μ—μ„œ μ‚¬μš©λ©λ‹ˆλ‹€:

  • 파일, λ„€νŠΈμ›Œν¬ μ—°κ²° λ“± μ™ΈλΆ€ λ¦¬μ†ŒμŠ€ λ‹«κΈ°
  • μž„μ‹œ λ””λ ‰ν† λ¦¬λ‚˜ 파일 μ‚­μ œ
  • μ‹œμŠ€ν…œ μ•Œλ¦Ό ꡬ독 ν•΄μ œ
  • 타이머 쀑지
  • λ‹€λ₯Έ κ°μ²΄μ—κ²Œ μžμ‹ μ˜ μ†Œλ©Έμ„ μ•Œλ¦¬κΈ°

μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문 λ‚΄μ—μ„œλŠ” ν•΄λ‹Ή μΈμŠ€ν„΄μŠ€μ˜ λͺ¨λ“  ν”„λ‘œνΌν‹°μ— μ ‘κ·Όν•  수 있으며, 이 ν”„λ‘œνΌν‹°λ“€μ„ 기반으둜 정리 μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ“Œ μ‹€μ œ 예제: κ²Œμž„ λ‚΄ 코인 관리 μ‹œμŠ€ν…œ

λ‹€μŒμ€ κ²Œμž„ μ‹œλ‚˜λ¦¬μ˜€λ₯Ό 톡해 μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문의 ν™œμš©μ„ λ³΄μ—¬μ£ΌλŠ” μ˜ˆμ œμž…λ‹ˆλ‹€:

class Bank {
    static var coinsInBank = 10_000
    
    static func distribute(coins numberOfCoinsRequested: Int) -> Int {
        let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)
        coinsInBank -= numberOfCoinsToVend
        return numberOfCoinsToVend
    }
    
    static func receive(coins: Int) {
        coinsInBank += coins
    }
}

이 Bank ν΄λž˜μŠ€λŠ” κ²Œμž„ λ‚΄ 은행을 λ‚˜νƒ€λ‚΄λ©°, μ½”μΈμ˜ 뢄배와 μˆ˜μ§‘μ„ κ΄€λ¦¬ν•©λ‹ˆλ‹€.

class Player {
    var coinsInPurse: Int
    
    init(coins: Int) {
        coinsInPurse = Bank.distribute(coins: coins)
    }
    
    func win(coins: Int) {
        coinsInPurse += Bank.distribute(coins: coins)
    }
    
    deinit {
        Bank.receive(coins: coinsInPurse)
    }
}

Player ν΄λž˜μŠ€λŠ” κ²Œμž„ ν”Œλ ˆμ΄μ–΄λ₯Ό λ‚˜νƒ€λ‚΄λ©°:

  • μ΄ˆκΈ°ν™” μ‹œ μ€ν–‰μ—μ„œ 코인을 λ°›μ•„μ˜΅λ‹ˆλ‹€
  • κ²Œμž„μ—μ„œ 이길 λ•Œ μΆ”κ°€ 코인을 받을 수 μžˆμŠ΅λ‹ˆλ‹€
  • μ΄ˆκΈ°ν™” ν•΄μ œ μ‹œ ν”Œλ ˆμ΄μ–΄κ°€ κ°€μ§„ λͺ¨λ“  코인을 은행에 λ°˜ν™˜ν•©λ‹ˆλ‹€

이 μ˜ˆμ œλŠ” μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문이 λ¦¬μ†ŒμŠ€ 관리에 μ–΄λ–»κ²Œ ν™œμš©λ˜λŠ”μ§€ λ³΄μ—¬μ€λ‹ˆλ‹€. ν”Œλ ˆμ΄μ–΄κ°€ κ²Œμž„μ„ λ– λ‚  λ•Œ 그듀이 κ°€μ§„ 코인은 μžλ™μœΌλ‘œ μ€ν–‰μœΌλ‘œ λ°˜ν™˜λ©λ‹ˆλ‹€.

μ‹€ν–‰ μ˜ˆμ‹œ

var playerOne: Player? = Player(coins: 100)
print("μƒˆλ‘œμš΄ ν”Œλ ˆμ΄μ–΄κ°€ \(playerOne!.coinsInPurse)개의 μ½”μΈμœΌλ‘œ κ²Œμž„μ— μ°Έκ°€ν–ˆμŠ΅λ‹ˆλ‹€")
// 좜λ ₯: "μƒˆλ‘œμš΄ ν”Œλ ˆμ΄μ–΄κ°€ 100개의 μ½”μΈμœΌλ‘œ κ²Œμž„μ— μ°Έκ°€ν–ˆμŠ΅λ‹ˆλ‹€"
print("μ€ν–‰μ—λŠ” ν˜„μž¬ \(Bank.coinsInBank)개의 코인이 λ‚¨μ•„μžˆμŠ΅λ‹ˆλ‹€")
// 좜λ ₯: "μ€ν–‰μ—λŠ” ν˜„μž¬ 9900개의 코인이 λ‚¨μ•„μžˆμŠ΅λ‹ˆλ‹€"

playerOne!.win(coins: 2_000)
print("ν”Œλ ˆμ΄μ–΄1이 2000개의 코인을 νšλ“ν•˜μ—¬ ν˜„μž¬ \(playerOne!.coinsInPurse)개의 코인을 보유 μ€‘μž…λ‹ˆλ‹€")
// 좜λ ₯: "ν”Œλ ˆμ΄μ–΄1이 2000개의 코인을 νšλ“ν•˜μ—¬ ν˜„μž¬ 2100개의 코인을 보유 μ€‘μž…λ‹ˆλ‹€"
print("μ€ν–‰μ—λŠ” 이제 \(Bank.coinsInBank)개의 μ½”μΈλ§Œ λ‚¨μ•„μžˆμŠ΅λ‹ˆλ‹€")
// 좜λ ₯: "μ€ν–‰μ—λŠ” 이제 7900개의 μ½”μΈλ§Œ λ‚¨μ•„μžˆμŠ΅λ‹ˆλ‹€"

// ν”Œλ ˆμ΄μ–΄κ°€ κ²Œμž„μ„ λ– λ‚©λ‹ˆλ‹€ - μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문이 ν˜ΈμΆœλ©λ‹ˆλ‹€
playerOne = nil
print("ν”Œλ ˆμ΄μ–΄1이 κ²Œμž„μ„ λ– λ‚¬μŠ΅λ‹ˆλ‹€")
// 좜λ ₯: "ν”Œλ ˆμ΄μ–΄1이 κ²Œμž„μ„ λ– λ‚¬μŠ΅λ‹ˆλ‹€"
print("μ€ν–‰μ—λŠ” 이제 \(Bank.coinsInBank)개의 코인이 μžˆμŠ΅λ‹ˆλ‹€")
// 좜λ ₯: "μ€ν–‰μ—λŠ” 이제 10000개의 코인이 μžˆμŠ΅λ‹ˆλ‹€"

이 예제λ₯Ό 보면:

  1. ν”Œλ ˆμ΄μ–΄κ°€ 100개의 μ½”μΈμœΌλ‘œ κ²Œμž„μ„ μ‹œμž‘ν•©λ‹ˆλ‹€
  2. ν”Œλ ˆμ΄μ–΄κ°€ 2,000개의 코인을 더 μ–»μŠ΅λ‹ˆλ‹€
  3. ν”Œλ ˆμ΄μ–΄κ°€ κ²Œμž„μ„ λ– λ‚  λ•Œ(playerOne = nil), μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문이 ν˜ΈμΆœλ˜μ–΄ λͺ¨λ“  코인이 μ€ν–‰μœΌλ‘œ λ°˜ν™˜λ©λ‹ˆλ‹€
  4. 결과적으둜 은행은 μ›λž˜ μƒνƒœμΈ 10,000개의 코인을 λ‹€μ‹œ λ³΄μœ ν•˜κ²Œ λ©λ‹ˆλ‹€

πŸ“Œ μ΄ˆκΈ°ν™” ν•΄μ œ μ‚¬μš© μ‹œ μ£Όμ˜μ‚¬ν•­

  1. μ‚¬μš© λ²”μœ„ μ œν•œ: μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문은 κΌ­ ν•„μš”ν•œ κ²½μš°μ—λ§Œ μ‚¬μš©ν•˜μ„Έμš”. λŒ€λΆ€λΆ„μ˜ 경우 Swift의 ARCκ°€ λ©”λͺ¨λ¦¬ 관리λ₯Ό μ•Œμ•„μ„œ 잘 ν•΄μ€λ‹ˆλ‹€.
  2. μˆœν™˜ μ°Έμ‘° 주의: μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문이 ν˜ΈμΆœλ˜μ§€ μ•ŠλŠ”λ‹€λ©΄, μˆœν™˜ μ°Έμ‘°(circular reference) λ¬Έμ œκ°€ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” ARCκ°€ λ©”λͺ¨λ¦¬λ₯Ό ν•΄μ œν•˜μ§€ λͺ»ν•˜κ²Œ ν•˜λŠ” 원인이 λ©λ‹ˆλ‹€.
  3. 비동기 μž‘μ—… 주의: μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문 λ‚΄μ—μ„œ 비동기 μž‘μ—…μ„ μ‹œμž‘ν•˜λ©΄ μ•ˆ λ©λ‹ˆλ‹€. μΈμŠ€ν„΄μŠ€κ°€ 이미 ν•΄μ œ 쀑이기 λ•Œλ¬Έμ— 예기치 μ•Šμ€ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  4. μ‹œμŠ€ν…œ λ¦¬μ†ŒμŠ€ ν•΄μ œ: 파일 ν•Έλ“€, λ„€νŠΈμ›Œν¬ μ—°κ²° λ“± μ‹œμŠ€ν…œ λ¦¬μ†ŒμŠ€λ₯Ό μ‚¬μš©ν•œ κ²½μš°μ—λŠ” λ°˜λ“œμ‹œ μ΄ˆκΈ°ν™” ν•΄μ œ κ΅¬λ¬Έμ—μ„œ 이λ₯Ό 정리해주어야 ν•©λ‹ˆλ‹€.

팁: 디버깅 쀑에 μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문이 ν˜ΈμΆœλ˜λŠ”μ§€ ν™•μΈν•˜λ €λ©΄, 내뢀에 print 문을 μΆ”κ°€ν•˜μ—¬ 둜그λ₯Ό 남겨볼 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ“Œ 정리

μ΄ˆκΈ°ν™” ν•΄μ œλŠ” Swiftμ—μ„œ 클래슀 μΈμŠ€ν„΄μŠ€μ˜ 생λͺ…μ£ΌκΈ° λ§ˆμ§€λ§‰μ— μ€‘μš”ν•œ 역할을 ν•©λ‹ˆλ‹€. 특히 μ™ΈλΆ€ λ¦¬μ†ŒμŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” ν΄λž˜μŠ€μ—μ„œλŠ” 이λ₯Ό 적절히 ν™œμš©ν•˜λŠ” 것이 λ©”λͺ¨λ¦¬ λˆ„μˆ˜λ‚˜ λ¦¬μ†ŒμŠ€ λˆ„μˆ˜λ₯Ό λ°©μ§€ν•˜λŠ” 데 μ€‘μš”ν•©λ‹ˆλ‹€.

μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문의 μ£Όμš” 포인트:

  • 클래슀만 κ°€μ§ˆ 수 있음
  • ν΄λž˜μŠ€λ‹Ή ν•˜λ‚˜λ§Œ μ •μ˜ κ°€λŠ₯
  • νŒŒλΌλ―Έν„° μ—†μŒ
  • μžλ™μœΌλ‘œ 호좜됨
  • 상속 μ‹œ ν•˜μœ„ ν΄λž˜μŠ€λΆ€ν„° μƒμœ„ 클래슀 순으둜 호좜됨

Swift의 ARC 덕뢄에 λŒ€λΆ€λΆ„μ˜ 경우 λͺ…μ‹œμ μΈ λ©”λͺ¨λ¦¬ 관리가 ν•„μš”ν•˜μ§€ μ•Šμ§€λ§Œ, μ™ΈλΆ€ λ¦¬μ†ŒμŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” 경우 μ΄ˆκΈ°ν™” ν•΄μ œ ꡬ문을 톡해 이λ₯Ό 적절히 μ •λ¦¬ν•˜λŠ” 것이 쒋은 ν”„λ‘œκ·Έλž˜λ° μŠ΅κ΄€μž…λ‹ˆλ‹€.