๐ŸŽiOS/๊ธฐํƒ€๊ฐœ๋ฐœ๊ณต๋ถ€

[iOS] ARC๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

BMOChop 2023. 1. 25. 20:38

์•ˆ๋…•ํ•˜์„ธ์š”^^

๋น„๋ชจ์ž…๋‹ˆ๋‹ค.๐Ÿค–

 

์˜ค๋Š˜ ์–˜๊ธฐํ•ด๋ณผ ์ฃผ์ œ๋Š” ๋ฐ”๋กœ ARC์ž…๋‹ˆ๋‹ค.

์š”์ฆ˜ GIF ๊ด€๋ จ ๋ฉ”๋ชจ๋ฆฌ ์ด์Šˆ๋„ ์žˆ๊ณ  ๋˜ ๊ด€๋ จ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋งŒ๋“ค๋‹ค๋ณด๋‹ˆ

๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ์— ์ค‘์š”์„ฑ์„ ๋А๋ผ๊ณ  ์žˆ๋Š”๋ฐ์š”.

์ด์™€ ๊ด€๋ จ๋œ ์ง€์‹๋“ค์„ ํ™•์‹คํ•˜๊ฒŒ ์งš๊ณ  ๋„˜์–ด๊ฐ€์•ผ๋  ๊ฒƒ ๊ฐ™์•„์„œ ์ •๋ฆฌํ•ด๋ด…๋‹ˆ๋‹ค.

 

 

ARC

์ž๋™์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ๋ฐฉ์‹.

์ธ์Šคํ„ด์Šค๊ฐ€ ์ ์ ˆํ•œ ์‹œ์ ์— ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜์ง€ ์•Š์œผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์ž์›์„ ๋‚ญ๋น„ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋•Œ๋ฌธ์— ARC๋Š” ํ•„์š”ํ•˜์ง€ ์•Š๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ž๋™์œผ๋กœ ํ•ด์ œ์‹œ์ผœ์ค๋‹ˆ๋‹ค.

 

 

ARC์˜ ์ž‘๋™ ๋ฐฉ์‹

ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋งˆ๋‹ค ARC๋Š” ๊ทธ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

๊ทธ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์—๋Š” ์ธ์Šคํ„ด์Šค ํƒ€์ž… ์ •๋ณด ๋ฐ ๊ด€๋ จ ์ €์žฅ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’๋“ค์ด ์ €์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ ํ›„ ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๊ฐ€ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์„ ๋•Œ ARC๊ฐ€ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ž๋™์œผ๋กœ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

 

 

ARC์˜ ์žฅ๋‹จ์ 

์žฅ์ 

  • ์ปดํŒŒ์ผ ๋‹น์‹œ ์ด๋ฏธ ์ธ์Šคํ„ด์Šค์˜ ํ•ด์ œ ์‹œ์ ์ด ์ •ํ•ด์ ธ ์žˆ์–ด์„œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์–ธ์ œ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋ ์ง€ ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ์‹œ์Šคํ…œ ์ž์›์„ ์ถ”๊ฐ€ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋‹จ์ 

  • ARC์˜ ์ž‘๋™ ๊ทœ์น™์„ ๋ชจ๋ฅด๊ณ  ์‚ฌ์šฉ์‹œ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

ARC ์‚ฌ์šฉ ๊ทœ์น™

  • ์•„์ง ๋” ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ์‹œํ‚ค๋ฉด ์ธ์Šคํ„ด์Šค์™€ ๊ด€๋ จ๋œ ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ์ธ์Šคํ„ด์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • ์ธ์Šคํ„ด์Šค์— ๊ฐ•์ œ๋กœ ์ ‘๊ทผํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์ž˜๋ชป๋œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์œผ๋กœ ์ธํ•ด ํ”„๋กœ๊ทธ๋žจ์ด ๊ฐ•์ œ ์ข…๋ฃŒ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์—์„œ ARC๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜์ง€ ์•Š๋„๋ก ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ์—ฌ๋ถ€๋ฅผ ๊ณ„์† ์ถ”์ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค์˜ ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ณ€์ˆ˜, ์ƒ์ˆ˜๋“ฑ ์–ด๋А ํ•œ๊ณณ์—์„œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•œ๋‹ค๋ฉด ARC๊ฐ€ ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๋ฅผ ํ•ด์ œํ•˜์ง€ ์•Š๊ณ  ์œ ์ง€ํ•ด์•ผ ํ•˜๋Š” ๋ช…๋ถ„์ด ๋ฉ๋‹ˆ๋‹ค.
  • ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์œ ์ง€์‹œํ‚ค๋ ค๋ฉด ์ด๋Ÿฐ ๋ช…๋ถ„์„ ARC์—๊ฒŒ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

๐Ÿ’ช๐Ÿผ๊ฐ•ํ•œ์ฐธ์กฐ (Strong Reference)

  • ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ๊ณ„์† ๋‚จ์•„์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ช…๋ถ„์€ ๋ฐ”๋กœ ๊ฐ•ํ•œ ์ฐธ์กฐ(Strong Reference)์ž…๋‹ˆ๋‹ค.
  • ์ฝ”๋“œ๋“ค๋กœ ํ™•์ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
class Robot {
	let name: String
    
    init(name: String) {
    	self.name = name
        print("\(name) is being initialized")
    }
    
    deinit {
    	print("\(name) is being deinitialized")
    }
}

var reference1: Robot?
var reference2: Robot?
var reference3: Robot?

reference1 = Person(name: "BMO")
// BMO is being initialized
// ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ํšŸ์ˆ˜ : 1

reference2 = reference1 // ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ํšŸ์ˆ˜ : 2
reference3 = reference1 // ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ํšŸ์ˆ˜ : 3
  • ์ธ์Šคํ„ด์Šค๋Š” ์ฐธ์กฐ ํšŸ์ˆ˜๊ฐ€ 0์ด ๋˜๋Š” ์ˆœ๊ฐ„ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ธ์Šคํ„ด์Šค(reference1)๋ฅผ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค(reference2, reference3)์˜ ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ณ€์ˆ˜, ์ƒ์ˆ˜ ๋“ฑ์— ํ• ๋‹นํ•  ๋•Œ ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฐธ์กฐ ํšŸ์ˆ˜๊ฐ€ 1 ์ฆ๊ฐ€ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

//๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ ์ถœ๋ ฅ
print(Unmanaged.passUnretained(reference1!).toOpaque()) ///0x0000600002a77c00์ถœ๋ ฅ 
print(Unmanaged.passUnretained(reference2!).toOpaque()) ///0x0000600002a77c00์ถœ๋ ฅ 
print(Unmanaged.passUnretained(reference3!).toOpaque()) ///0x0000600002a77c00์ถœ๋ ฅ
  • ๊ทธ ๋‹ค์Œ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ํ•œ๋ฒˆ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
  • reference1, 2, 3 ๋ชจ๋‘ ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

reference1 = nil // ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ํšŸ์ˆ˜ : 2
reference2 = nil // ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ํšŸ์ˆ˜ : 1
reference3 = nil // ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ํšŸ์ˆ˜ : 0
// BMO is being deinitialized
  • ์œ„์ฒ˜๋Ÿผ reference1์ด ์ฐธ์กฐ ํ•ด์ œ๋˜์–ด๋„ Robot ์ธ์Šคํ„ด์Šค ์•„์ง reference2, reference3์— ๋Œ€ํ•œ ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ deallocated๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๋ฅผ deinit์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„ , ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๊ฐ€ ๊ฐ€์ง„ ๋ชจ๋“  ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ํ•ด์ œํ•ด์•ผ deinit ๋˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

๐Ÿ’ช๐Ÿผ๊ฐ•ํ•œ ์ˆœํ™˜ ์ฐธ์กฐ (Strong Reference Cycle)

๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ• ๋•Œ๋„ ์ฃผ์˜ํ•ด์•ผ ๋  ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. 

๋ฐ”๋กœ "๊ฐ•ํ•œ ์ˆœํ™˜ ์ฐธ์กฐ" ์ž…๋‹ˆ๋‹ค.

 

๊ฐ•ํ•œ ์ˆœํ™˜ ์ฐธ์กฐ๋Š” ์—ฌ๋Ÿฌ ์ธ์Šคํ„ด์Šค๊ฐ€ ์„œ๋กœ ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ํ•˜๋Š” ์‚ฌ์ดํด์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ํ•œ๋ฒˆ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

class Robot {
    let name: String
    
    init(name: String) {
        self.name = name
    }
    
    var battery: Battery?
    
    deinit {
        print("\(name) is being deinitialized!")
    }
}
 
class Battery {
    let energy: String
    
    init(energy: String) {
        self.energy = energy
    }
    
    var master: Robot?
    
    deinit {
        print("Battery \(number) is being deinitialized!")
    }
}
  • ๊ฐ๊ฐ Robot ํด๋ž˜์Šค์™€ Battery ํด๋ž˜์Šค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Battery ์—๋Š” nil๋กœ ์ดˆ๊ธฐํ™” ๋œ Robot ํƒ€์ž…์˜ master ํ”„๋กœํผํ‹ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Robot ์—๋Š” nil๋กœ ์ดˆ๊ธฐํ™” ๋œ Battery ํƒ€์ž…์˜ battery ํ”„๋กœํผํ‹ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

var bmo: Robot? = Robot(name: "bmo") // Robot ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 1
var energizer: Battery? = Battery(number: "50") // bmo ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 1

 

  • ๊ฐ๊ฐ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค.

 

bmo?.battery = energizer // Battery ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 2
energizer?.master = bmo // Robot ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 2
  • robot์— battery ๋ฅผ, battery ์—๋Š” robot ์„ ํ• ๋‹นํ•˜๊ฒŒ ๋˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • Robot ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ Battery ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•ด ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , Battery ์˜ ์ธ์Šคํ„ด์Šค๋Š” Robot ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•ด ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋˜์–ด ๋‘ ์ธ์Šคํ„ด์Šค ์‚ฌ์ด์—๋Š” ๊ฐ•ํ•œ ์ฐธ์กฐ ์‚ฌ์ดํด์ด ์ƒ์„ฑ ๋ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ฐ•ํ•œ ์ˆœํ™˜ ์ฐธ์กฐ๋Š” ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋ƒ๋ฉด, ARC๊ฐ€ ์ฐธ์กฐ ํšŸ์ˆ˜๊ฐ€ 0 ์ด ๋˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ž๋™์œผ๋กœ ํ• ๋‹น ํ•ด์ œ๋ฅผ ํ•ด์ค˜์•ผํ•˜๋Š”๋ฐ

๊ฐ•ํ•œ ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ์ƒ๊ธฐ๊ฒŒ ๋˜๋ฉด Reference Count ๊ฐ€ 0์ด ๋˜์ง€ ์•Š์•„ ์ธ์Šคํ„ด์Šค ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณ„์† ์ฐจ์ง€  (๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ํ˜„์ƒ์ด ๋ฐœ์ƒ) ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

bmo = nil // Robot ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ํšŸ์ˆ˜ : 1
energizer = nil // Battery ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ํšŸ์ˆ˜ : 1

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•ด์•ผ ํ• ๊นŒ์š”? ๐Ÿคท๐Ÿป‍โ™‚๏ธ

 

๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์•ž์„œ ์ฐธ์กฐ์˜ ์ข…๋ฅ˜์— ๋Œ€ํ•ด์„œ ๋จผ์ € ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

References

Swift ์—์„  ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๋ฐฉ์‹์ด ์œ„์—์„œ ์„ค๋ช… ๋“œ๋ฆฐ ๊ฐ•ํ•œ ์ฐธ์กฐ ์™ธ์—๋„ 2๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

strong reference

  • ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค์˜ Reference Count ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค.
  • ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๋Š” defaultํ•œ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

weak reference

  • ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค์˜ Reference Count๋ฅผ ์ฆ๊ฐ€ ์‹œํ‚ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ• ๋‹น ํ•ด์ œ๋  ๊ฒฝ์šฐ nil ์ด ํ• ๋‹น ๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, weak reference๊ฐ€ ๊ฐ•ํ•œ ์ˆœํ™˜ ์ฐธ์กฐ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ํ•˜๋‚˜์˜ ๋ฐฉ๋ฒ•์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐ŸŽˆ์ฃผ์˜
nil
์ด ํ• ๋‹น ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜ต์…”๋„ ํƒ€์ž…์œผ๋กœ ์„ ์–ธ
ARC๊ฐ€ weak ๋ณ€์ˆ˜๋ฅผ nil ๋กœ ๋งŒ๋“ค๋•Œ๋Š” ํ”„๋กœํผํ‹ฐ ์˜ต์ €๋ฒ„ (Property observer)๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

unowned reference

  • ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค์˜ Reference Count๊ฐ€ ์ฆ๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ• ๋‹น ํ•ด์ œ๋  ๊ฒฝ์šฐ ๋ณ„๋‹ค๋ฅธ ์กฐ์น˜๋ฅผ ์ทจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

unowned์€ weak์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ฐ•ํ•œ ์ˆœํ™˜์ฐธ์กฐ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋‚˜ weak ์™€ ๋‹ค๋ฅด๊ฒŒ ์˜ต์…”๋„ ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ ์ด์œ ๋Š” unowned ์ฐธ์กฐ๋ฅผ ํ•˜๋ฉด ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ• ๋‹น ํ•ด์ œ๋˜์–ด๋„ ์—ฌ์ „ํžˆ Heap ์˜์—ญ์— ์ธ์Šคํ„ด์Šค๊ฐ€ ์žˆ๋˜ ๊ณณ์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰ ํ—ˆ์ƒ ํฌ์ธํ„ฐ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

ํ—ˆ์ƒ ํฌ์ธํ„ฐ(Dangling Pointer)๋ž€..?
์œ ํšจํ•˜์ง€ ์•Š์€ ์ฃผ์†Œ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ํฌ์ธํ„ฐ๋ฅผ ๋งํ•˜๋ฉฐ ์ฃผ๋กœ ๊ฐ์ฒด ํŒŒ๊ดด์‹œ ๋ฐœ์ƒ

๊ทธ๋ ‡๊ธฐ ๋–„๋ฌธ์—, ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ๋จผ์ € ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์—†๋Š” ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

weak vs unowned

๊ตฌ๋ถ„ weak unowned
์–ธ์ œ? ์ฐธ์กฐํ•œ ๊ฐ์ฒด๊ฐ€ ์‹ค์ œ ์‚ฌ์šฉํ• ๋•Œ ํ•ด์ œ๋ ์ง€๋„ ๋ชจ๋ฅผ ๋•Œ ์‚ฌ์šฉ. ๋ณดํ†ต ์งง์€์ฃผ๊ธฐ๋กœ ์ฐธ์กฐํ•  ๋•Œ ์‚ฌ์šฉ ์ฐธ์กฐํ•œ ๊ฐ์ฒด์™€ ์ƒ๋ช…์ฃผ๊ธฐ๊ฐ€ ๊ฐ™๊ฑฐ๋‚˜ ์ฐธ์กฐํ•œ ๊ฐ์ฒด๊ฐ€ ๋” ๊ธธ๋•Œ ์‚ฌ์šฉ
์ˆœํ™˜ ์ฐธ์กฐ ๋ฌธ์ œ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ
์ฐธ์กฐํ•œ ๊ฐ์ฒด๊ฐ€ ํ•ด์ œ ๋˜์—ˆ์„๋•Œ nil๋กœ ๊ฐ’์ด ๋ณ€๊ฒฝ dangling pointer๊ฐ€ ๋จ

 

 

๊ฐ•ํ•œ ์ˆœํ™˜ ์ฐธ์กฐ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

์„œ๋กœ ๋‹ค๋ฅธ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๊ฐ„์— ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ์žˆ์„๋•Œ, ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ weak ๋˜๋Š” unowned ๋กœ ์„ ์–ธํ•ด์„œ ๊ฐ•ํ•œ ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ์ƒ๊ธฐ๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

weak๋กœ ํ•ด๊ฒฐํ•˜์˜€์„ ๋•Œ

class Robot {
    // ์ƒ๋žต: ์œ„์™€ ๋™์ผ
}
 
class Battery {
    let energy: String
    
    init(energy: String) {
        self.energy = energy
    }
    
    weak var master: Robot? // weak ๋ฅผ ๋„ฃ์–ด๋ณด์•˜๋‹ค.
    
    deinit {
        print("Battery \(number) is being deinitialized!")
    }
}
  • Battery ์— ์žˆ๋Š” master๋ฅผ weak๋กœ ๋ฐ”๊ฟ”๋ณด์•˜๋‹ค.

 

var bmo: Robot? = Robot(name: "bmo") // Robot ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 1
var energizer: Battery? = Battery(energy: "50") // bmo ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 1

bmo?.battery = energizer // Battery ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 2
energizer?.master = bmo // Robot ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 2

bmo = nil // Robot ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ํšŸ์ˆ˜ : 0
// bmo is being deinitialized!
energizer = nil // Battery ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ํšŸ์ˆ˜ : 0
// energizer is being deinitialized!
  • deinitialized ๊ฐ€ ๋ถˆ๋ฆฌ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค!

 

unowned๋กœ ํ•ด๊ฒฐํ•˜์˜€์„ ๋•Œ

class Robot {
    // ์ƒ๋žต: ์œ„์™€ ๋™์ผ
}
 
class Battery {
    let energy: String
    
    init(energy: String) {
        self.energy = energy
    }
    
    unowned var master: Robot? // weak ๋ฅผ ๋„ฃ์–ด๋ณด์•˜๋‹ค.
    
    deinit {
        print("Battery \(number) is being deinitialized!")
    }
}
  • ์ด๋ฒˆ์—” unowned ๋กœ ๋ฐ”๊ฟ” ๋ณด์•˜๋‹ค.

 

var bmo: Robot? = Robot(name: "bmo") // Robot ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 1
var energizer: Battery? = Battery(energy: "50") // bmo ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 1

bmo?.battery = energizer // Battery ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 2
energizer?.master = bmo // Robot ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ ํšŸ์ˆ˜ : 2

bmo = nil
// ์ฐธ์กฐ ํšŸ์ˆ˜ 0
// bmo is being deinitialized!
// energizer is being deinitialized!
  • Robot์— ๋Œ€ํ•œ ๊ฐ•ํ•œ ์ฐธ์กฐ๊ฐ€ ํ•ด์ œ๋˜๋ฉฐ Robot ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•ด ๊ฐ•ํ•œ ์ฐธ์กฐ๊ฐ€ ๋” ์ด์ƒ ์—†์œผ๋ฏ€๋กœ ํ• ๋‹น ํ•ด์ œ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ ์ดํ›„ Battery ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ๊ฐ•ํ•œ ์ฐธ์กฐ๋„ ์—†์–ด์ง€๋ฏ€๋กœ Battery ์ธ์Šคํ„ด์Šค๋„ ํ• ๋‹น ํ•ด์ œ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

 

์ด์ƒ ๋น„๋ชจ์˜€์Šต๋‹ˆ๋‹ค.๐Ÿค–

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

 

์ฐธ๊ณ ์ž๋ฃŒ

https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html

 

Automatic Reference Counting — The Swift Programming Language (Swift 5.7)

Automatic Reference Counting Swift uses Automatic Reference Counting (ARC) to track and manage your app’s memory usage. In most cases, this means that memory management “just works” in Swift, and you don’t need to think about memory management your

docs.swift.org