๐Ÿ“’ Study/๐Ÿšฉ Swift

[ Swift ] ARC ( Automatic Reference Counting ) ๋ชจ๋ธ / Swift์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ

EarthSea 2024. 4. 11. 23:07

 

 

 

 

์˜ค๋Š˜์€ ARC ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•ด ๋ณผ๊นŒ ํ•ฉ๋‹ˆ๋‹ค!

๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด ๋ณผ๊นŒ์š”?! โœจ

 

 

์Šค์œ„ํ”„ํŠธ๋Š” ARC ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ํž™ ์˜์—ญ์—์„œ์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์Œ.. ๊ทธ๋ ‡๋‹ค๋ฉด ํž™ ์˜์—ญ์ด ๋Œ€์ฒด ๋ญ๊ธธ๋ž˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌ๋ฅผ ํ•ด์ฃผ์–ด์•ผ ํ• ๊นŒ์š”?!

 

๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์ค‘ Heap ์˜์—ญ

Heap ์˜์—ญ์€ ๋Ÿฐํƒ€์ž„ ์ค‘ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ๋™์ ์œผ๋กœ ํ• ๋‹น๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ๋™์  ํ• ๋‹น์ด ๋ญ”๋ฐ์š”?! ๋™์  ํ• ๋‹น์ด๋ž€ ์Šคํƒ ์˜์—ญ์ฒ˜๋Ÿผ ์ •ํ•ด์ง„ ๊ณณ์— ๋ฐ์ดํ„ฐ ๋”ฑ๋”ฑ ๋“ค์–ด๊ฐ€๊ณ  ๋‚˜์˜ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ฉ”๋ชจ๋ฆฌ์˜ ๋น„์›Œ์ ธ ์žˆ๋Š” ๊ณต๊ฐ„์„ ์ฐพ์•„์„œ ํฌ๊ธฐ๋‚˜ ์ƒ์กด๊ธฐ๊ฐ„์„ ์ •ํ•˜์—ฌ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. Heap ์˜์—ญ์—๋Š” ์ฐธ์กฐ ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋งŒ ์ €์žฅ์ด ๋ฉ๋‹ˆ๋‹ค.

 

  • ๋Ÿฐํƒ€์ž„ ์ค‘ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ Heap ์˜์—ญ์— ์ €์žฅ
  • ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋™์ ์œผ๋กœ ํ• ๋‹น
  • ์ฐธ์กฐ ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ

 

์ด Heap ์˜์—ญ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ์ด ๋˜๋ฉด ๋” ์ด์ƒ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š” ์—†์„ ๋•Œ๋Š” ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•ด์ œ๋ฅผ ํ•ด์ฃผ์–ด์•ผ ํ•˜์ž–์•„์š”?!

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ด Heap ์˜์—ญ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๋ฅผ ํ•ด์ฃผ์–ด์•ผ๋งŒ ํ•ฉ๋‹ˆ๋‹ค.

 

 

 

ARC ( Automatic Reference Counting )

์Šค์œ„ํ”„ํŠธ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ ARC๋ผ๋Š” ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ARC๋Š” ' Automatic Reference Counting '์ด๋ผ๋Š” ์˜์–ด์˜ ์ค„์ž„๋ง์ธ๋ฐ์š”! Reference Counting์„ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌํ•ด ์ฃผ๋Š” ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.

 

 

Reference Counting

์—ฌ๊ธฐ์„œ Referece Counting์ด๋ž€ ์ž๊ธฐ ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” ( ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ) ๊ฒƒ์˜ ๊ฐœ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ค„์—ฌ์„œ RC๋ผ๊ณ ๋„ ํ•ด์š”.

 

 

ARC๋Š” ๋‹ค๋ฅธ ๋ชจ๋ธ๋“ค๊ณผ ๋‹ฌ๋ฆฌ RC๋ฅผ 1 ์ฆ๊ฐ€์‹œ์ผœ ์ฃผ๋Š” retain() ํ•จ์ˆ˜์™€ RC๋ฅผ 1 ๊ฐ์†Œ์‹œ์ผœ์ฃผ๋Š” release() ํ•จ์ˆ˜๋ฅผ ์ž๋™์œผ๋กœ ์‹คํ–‰์‹œ์ผœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•ด ์ค๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด, ๊ฐœ๋ฐœ์ž๋“ค์ด ์–ธ์ œ, ์–ด๋–ป๊ฒŒ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ํ•ด์ฃผ์–ด์•ผ ํ• ๊นŒ์š”?!

 

 

 

๊ฐ•ํ•œ ์ฐธ์กฐ ์‚ฌ์ดํด

์„œ๋กœ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๊ฐ€ ์„œ๋กœ๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ๋•Œ๋ฅผ Strong Reference Cycle ์ด๋ผ๊ณ  ํ•˜๋ฉฐ, ์ด๋ฅผ ๊ฐ•ํ•œ ์ฐธ์กฐ ์‚ฌ์ดํด์ด๋ผ๊ณ  ํ•˜๋Š”๋ฐ์š”. ์ด๋•Œ, ๊ฐ๊ฐ์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ nil์ด ๋˜์–ด๋„ ์„œ๋กœ๊ฐ€ ์„œ๋กœ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— RC๊ฐ€ 0์ด ๋˜์ง€ ๋ชปํ•ด์„œ ๋ฉ”๋ชจ๋ฆฌ์— ๊ณ„์† ๋‚จ์•„์žˆ๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. ์“ฐ์ด์ง€ ์•Š๋Š”๋ฐ, ๋ฉ”๋ชจ๋ฆฌ์— ๊ณ„์† ๋‚จ์•„์žˆ๊ฒŒ ๋˜๋ฉด ์ด๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„๊ฐ€ ๋˜๊ฒ ์ฃ ? ์ด๋ฅผ "๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜"๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

์กฐ๊ธˆ ๋” ์ž์„ธํžˆ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ด…์‹œ๋‹ค!

class Person {
    let name: String
    var apartment: Apartment?

    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

class Apartment {
    let unit: String
    var tenant: Person?

    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) is being initialized")
    }

    deinit {
        print("Apartment \(unit) is being deinitialized")
    }
}

var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil
unit4A = nil

 

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๊ฐ„๋‹จํžˆ ๊ทธ๋ฆผ์œผ๋กœ ๋‚˜ํƒ€๋‚ด๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Person๊ณผ Apartment๋ผ๋Š” ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ๊ฐ๊ฐ john๊ณผ unit4A์ด๊ณ  ์ธ์Šคํ„ด์Šค์˜ ์ €์žฅ ์†์„ฑ์ธ apartment์™€ tenant๊ฐ€ ๊ฐ๊ฐ์˜ ํด๋ž˜์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋•Œ, john์ด๋ผ๋Š” Person์˜ ์ธ์Šคํ„ด์Šค๋Š” john์ด๋ผ๋Š” ๋ณ€์ˆ˜์—๊ฒŒ์„œ ์ฐธ์กฐ๋ฅผ ๋‹นํ•˜๊ณ , unit4A์˜ ์ €์žฅ ์†์„ฑ์ธ tenant์—๊ฒŒ ์ฐธ์กฐ๋‹นํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— RC๊ฐ€ 2๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. unit4A๋ผ๋Š” Apartment์˜ ์ธ์Šคํ„ด์Šค๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ RC๊ฐ€ 2์ด๊ฒ ์ฃ ?!

 

 

์ด ๊ฒฝ์šฐ์— john๊ณผ unit4A์˜ ๊ฐ’์„ nil๋กœ ํ• ๋‹นํ•˜๊ฒŒ ๋˜๋ฉด, john๊ณผ unit4A๊ฐ€ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ํด๋ž˜์Šค๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ๊ฐ๊ฐ์˜ RC๊ฐ€ 1๋กœ ์ค„์–ด๋“ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

 

์ด๋•Œ, ์„œ๋กœ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” ์ฐธ์กฐ๊ฐ€ ๋‚จ์•„์žˆ์–ด RC๊ฐ€ 1์ธ ์ƒํƒœ๋กœ ์œ ์ง€๋˜๊ธฐ ๋•Œ๋ฌธ์— Heap ์˜์—ญ์—์„œ John๊ณผ unit4A์˜ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ œ๊ฑฐ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๊ณ , ์ด๋Ÿฐ ์ƒํ™ฉ์„ ๊ฐ•ํ•œ ์ฐธ์กฐ ์‚ฌ์ดํด์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?!?!

๊ฐ•ํ•œ ์ฐธ์กฐ ์‚ฌ์ดํด๋กœ ์ธํ•œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜์˜ ํ•ด๊ฒฐ๋ฐฉ์•ˆ์€ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

์•ฝํ•œ ์ฐธ์กฐ ( weak Reference )

์ฒซ ๋ฒˆ์งธ๋กœ๋Š” ์•ฝํ•œ ์ฐธ์กฐ์ž…๋‹ˆ๋‹ค. ์ฐธ์กฐ๋ฅผ ๋‹นํ•˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ nil์ด ๋˜๋ฉด ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค๋„ nil๋กœ ํ• ๋‹น์ด ๋˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • weak ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ

 

class Person {
    var name: String
    weak var friend: Person? // ์•ฝํ•œ ์ฐธ์กฐ
    
    init(name: String) {
        self.name = name
    }
}

var john: Person? = Person(name: "John")
var doe: Person? = Person(name: "Doe")

john?.friend = doe
doe?.friend = john

john = nil
doe = nil

์œ„์˜ ์˜ˆ์‹œ๋กœ ์„ค๋ช…ํ•˜์ž๋ฉด, john์˜ ๊ฐ’์ด nil์ด ๋œ๋‹ค๋ฉด ์ด john์„ ๊ฐ€๋ฆฌํ‚ค๋Š” unit4A์˜ ์ €์žฅ์†์„ฑ์ธ tenant์˜ ๊ฐ’๋„ nil์ด ๋˜์–ด RC๊ฐ€ 0์œผ๋กœ ์ค„์–ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค!

 

 

 

๋น„์†Œ์œ  ์ฐธ์กฐ ( unowned Reference )

weak๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ, ๋‹ค๋ฅธ ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ๋น„์†Œ์œ  ์ฐธ์กฐ์ž…๋‹ˆ๋‹ค. weak๊ณผ ๋‹ค๋ฅธ ์ ์€ ์˜ต์…”๋„ ํƒ€์ž…์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฐธ์กฐ๋‹นํ•˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ nil์ด ๋˜๋ฉด ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ํ˜ธ์ถœํ•˜์˜€์„ ๋•Œ, ์˜ค๋ฅ˜๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ’์ด ์žˆ์„ ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์ด ๋ช…ํ™•ํ•ด์งˆ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋น„์†Œ์œ  ์ฐธ์กฐ์ž…๋‹ˆ๋‹ค.

  • unowned ํ‚ค์›Œ๋“œ

 

class Customer {
    let name: String
    var card: CreditCard?
    
    init(name: String) {
        self.name = name
    }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer //๋น„์†Œ์œ  ์ฐธ์กฐ
    
    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
}

var john: Customer? = Customer(name: "John Doe")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

john = nil // ์—ฌ๊ธฐ์„œ Customer ์ธ์Šคํ„ด์Šค์™€ ์—ฐ๊ด€๋œ CreditCard ์ธ์Šคํ„ด์Šค๋„ ํ•จ๊ป˜ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.

 

์œ„์˜ ๊ฒฝ์šฐ์—” CreditCard์˜ ์ธ์Šคํ„ด์Šค๋Š” customer(john)์ด nil๋กœ ํ• ๋‹น๋˜์ง€ ์•Š์„ ๋•Œ๋งŒ ์œ ํšจํ•˜๊ณ ,  Customer ์ธ์Šคํ„ด์Šค๊ฐ€ nil์ด ๋œ ํ›„์— CreditCard๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

 

 

weak VS unowned

  • ๋ณดํ†ต weak์„ ๋” ๋งŽ์ด ์‚ฌ์šฉ
  • weak ๋ณด๋‹ค unowned๊ฐ€ ๋” ๋น ๋ฆ„.

 

[ let, var, optional, non-optional ์‚ฌ์šฉ ๊ฐ€๋Šฅ ]

  let var optional non-optional
strong O O O O
weak X O O X
unowned O O O O

 

์ด๋•Œ, strong์€ ๊ธฐ๋ณธ ๋ณ€์ˆ˜ ์„ ์–ธ ์‹œ์— ์ž๋™์œผ๋กœ ์„ ์–ธ๋˜๋Š” ํ‚ค์›Œ๋“œ์ž…๋‹ˆ๋‹ค.