Published on

๐ŸŽ Swift - ARC(strong, weak, unowned)

Authors
  • avatar
    Name
    ์ด์ฐฝ์ค€
    Twitter

Swift ๋ฌธ์„œ์—๋Š” ์˜ค๋žœ๋งŒ์ด๋„ค์š”. ์ตœ๊ทผ ํŒŒ์ด์ฌ๋งŒ ๋‹ค๋ฃจ๋‹ค๋ณด๋‹ˆ Swift ์ชฝ ๋ฐ€๋ฆฐ ๊ณต๋ถ€๊ฐ€ ์‚ฐ๋”๋ฏธ์—์š”.

์˜ค๋Š˜์€ ARC์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊ฒ๋‹ˆ๋‹ค. ์ด์•ผ๊ธฐ๋Š” ๊ณ„์† ๋“ค์–ด์™”๊ณ  ์ฐธ๊ณ ํ•˜๋Š” ์ฝ”๋“œ๋“ค์—์„œ๋„ ๋งค์šฐ ์ž์ฃผ ๋ณด์˜€๋Š”๋ฐ ์ด๋ฒˆ์— ์ œ๋Œ€๋กœ ์•Œ์•„๋ณด๊ณ  ๊ฐ€๋ด์•ผ๊ฒ ์Šต๋‹ˆ๋‹ค.

ARC (Automatic Reference Counting)

์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ARC๋Š” ์ฐธ์กฐ์™€ ๊ด€๋ จ๋œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ณด๊ธฐ๋งŒํ•ด๋„ ๊ธฐ๋ถ„์ด ์ข‹์•„์ง€๋Š” Automaticํ•œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

ํ•œ ๋งˆ๋””๋กœ ์‰ฝ๊ฒŒ ๋„˜๊ธฐ๋ฉด ARC๋Š”

์ž๋™์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ์•„์ฃผ ๊ฐ„ํŽธํ•œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์กฐ๊ธˆ ๋” ๋“ค์–ด๊ฐ€๋ฉด ARC๋Š”,

์ปดํŒŒ์ผ ํƒ€์ž„์— ์ž๋™์œผ๋กœ retain, release ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. retainํ•œ ํšŸ์ˆ˜๋ฅผ ์ถ”์ ํ•˜๋ฉฐ ๋” ์ด์ƒ ์ฐธ์กฐ๋˜์ง€ ์•Š๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ releaseํ•ด์ฃผ๋Š” ๊ฒƒ ์ด๋ผ๊ณ  ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ธฐ๊ธฐ์˜ ๋ฉ”๋ชจ๋ฆฌ(Heap) ์˜์—ญ์€ ์œ ํ•œ๋œ ์ž์›์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์–ธ์ œ๋‚˜ ์ตœ์ ํ™”๊ฐ€ ํ•„์š”ํ•˜๊ณ , ๊ฐ€๋ณ๊ฒŒ ์œ ์ง€ํ•  ํ•„์š”๊ฐ€ ์žˆ์ฃ !

Swift๊ฐ€ ๊ณต๊ฐœ๋˜๊ธฐ ์ด์ „ Obj-C ์–ธ์–ด๋กœ iOS ์•ฑ์„ ๊ฐœ๋ฐœํ–ˆ๋˜ ์‹œ์ ˆ์—๋Š” ์ด ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ์ˆ˜๋™์œผ๋กœ ํ•ด์ฃผ์–ด์•ผ ํ–ˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๋ฐฉ์‹์„ MRC(Manual Reference Counting)์ด๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

  • retain: reference count๋ฅผ ์ฆ๊ฐ€์‹œ์ผœ ๊ฐ์ฒด๊ฐ€ ์œ ์ง€๋˜๋„๋ก ๋ณด์žฅ
  • release: reference count๋ฅผ ๊ฐ์†Œ์‹œ์ผœ ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฐ์ฒด๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ์œ ์ง€๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€

์ด ๋‘ ๊ธฐ๋Šฅ์„ ๊ณ„์†ํ•ด์„œ ๋ฐ˜๋ณตํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•ด์ฃผ์–ด์•ผ ํ–ˆ๋˜ ๊ฒƒ์ด์ฃ . ์ •๋ง์ด์ง€ ๋„ˆ๋ฌด ๋ฒˆ๊ฑฐ๋กญ์ง€ ์•Š๋‚˜์š”..? ๊ทธ๋ž˜์„œ ์• ํ”Œ์€ ๊ฐœ๋ฐœ์ž๋“ค์˜ ํŽธ์˜์„ฑ์„ ์œ„ํ•ด ARC๋ฅผ ๋“ฑ์žฅ์‹œํ‚ค๊ฒŒ ๋œ ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

ARC๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ˆ˜ํ–‰๋˜๋Š” ๋ฐฉ์‹์ด ๊ฐ๊ฐ์˜ ์ฝ”๋“œ ์ค‘๊ฐ„์ค‘๊ฐ„์— ์ž๋™์œผ๋กœ retain ์ฝ”๋“œ์™€ release ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…์‹œํ‚ค๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

Retain & Release

์ปดํŒŒ์ผ ํƒ€์ž„์—๋Š” ๋‹จ์ˆœํžˆ ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…๋งŒ ํ•ด์ฃผ๊ณ , ๋Ÿฐํƒ€์ž„๋™์•ˆ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋ฉฐ reference count๋ฅผ ์ฆ๊ฐ์‹œํ‚ต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค๊ฐ€ count ๊ฐ’์ด 0์ด ๋˜๋ฉด deinit์„ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ์‹œํ‚ค๋Š” ๊ฒƒ์ด์ฃ !

์ž ๊ทธ๋Ÿฐ๋ฐ, ์ž๋™์œผ๋กœ ๊ด€๋ฆฌ๋ฅผ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์•„๋ฌด๋ฆฌ ํŽธํ•˜๋”๋ผ๋„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์–ด๋Š์ •๋„ ๋ฉ”๋ชจ๋ฆฌ์— ๊ด€์—ฌ๋ฅผ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ์žˆ๊ฒ ์ฃ ? ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ๋ฅผ ์œ„ํ•ด์„œ strong, weak, unowned๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

strong (๊ฐ•ํ•œ ์ฐธ์กฐ)

  • ์„ ์–ธํ•  ๋•Œ ์•„๋ฌด ํ‚ค์›Œ๋“œ๋„ ์ ์–ด์ฃผ์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’(default)์œผ๋กœ ์„ค์ •
  • ํ•ด๋‹น ์ธ์Šคํ„ด์Šค์˜ ์†Œ์œ ๊ถŒ์„ ๊ฐ€์ง
  • ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค์˜ reference count ์ฆ๊ฐ€
  • strong reference count๊ฐ€ 0์ด ๋˜๋ฉด ๊ฐ์ฒด๋Š” deinit
  • ๊ฐ’ ์ง€์ • ์‹œ์ ์— retain, ์ฐธ์กฐ ์ข…๋ฃŒ ์‹œ์ ์— release
var david: Person? = Person(name: "David")
// reference count ++

david = nil // reference count --

๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฃผ์˜ํ•  ์ ์ด ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜(Strong Reference Cycle) ์ž…๋‹ˆ๋‹ค.

class Strong {
  var strong: Strong? = nil
}

var strong1: Strong? = Strong()
var strong2: Strong? = Strong()

strong1?.strong = strong2
strong2?.strong = strong1

strong1 = nil
strong2 = nil

์œ„ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด strong1๊ณผ strong2๋Š” ์„œ๋กœ์˜ strong์„ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ, strong์€ ๊ฐ•ํ•œ ์ฐธ์กฐ ๊ฐ์ฒด๋ผ์„œ nil์„ ์ฃผ๊ธฐ ์ „๊นŒ์ง„ ํ•ด์ œ๋˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋งˆ์ง€๋ง‰ strong1๊ณผ strong2์— nil ๊ฐ’์„ ์ฃผ๋ ค ํ•  ๋•Œ, ์„œ๋กœ๊ฐ€ ์„œ๋กœ๋ฅผ ๊ฐ•ํ•˜๊ฒŒ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์–ด ๊ฐ๊ฐ์˜ ๊ฐ์ฒด ๋ณ€์ˆ˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ๊ฐ€ ๋˜์—ˆ์ง€๋งŒ, ๊ฐ์ฒด ์ž์ฒด๋Š” ์—ฌ์ „ํžˆ ์„œ๋กœ๋ฅผ ์ฐธ์กฐํ•˜๋ฉฐ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ๊ฐ€ ๋˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๊ฐ์ฒด ๋ณ€์ˆ˜๋Š” ์ด๋ฏธ ํ•ด์ œ๊ฐ€ ๋˜์–ด ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ๋ฐฉ๋ฒ•๋„ ์—†๊ณ , ๊ฐ์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œํ•  ๋ฐฉ๋ฒ•๋„ ์—†์–ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์˜์›ํžˆ ๋ฉ”๋ชจ๋ฆฌ์— ๋จธ๋ฌผ๋Ÿฌ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด์ฃ .

์ด๋Ÿฐ ํ˜„์ƒ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด weak (์•ฝํ•œ ์ฐธ์กฐ)๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

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

  • ํ•ด๋‹น ์ธ์Šคํ„ด์Šค์˜ ์†Œ์œ ๊ถŒ์„ ๊ฐ€์ง€์ง€ ์•Š์Œ
  • ์ฃผ์†Œ๊ฐ’๋งŒ ๊ฐ€์ง์œผ๋กœ์„œ ํฌ์ธํ„ฐ์ฒ˜๋Ÿผ ์‚ฌ์šฉ
  • reference count๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค์ง€ ์•Š์Œ
  • weak reference count๊ฐ€ 0์ด ๋˜๋ฉด dead
  • ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ๋  ๋•Œ ์ž๋™์œผ๋กœ nil๋กœ ์ดˆ๊ธฐํ™”
  • ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๊ฐ€ nil ์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ optional์ด์–ด์•ผ ํ•จ
weak var david: Person? = Person(named: "David")
// ๋ฐ”๋กœ ๊ฐ์ฒด ํ•ด์ œ, nil

๊ทธ๋ ‡๋‹ค๋ฉด weak๋Š” ์–ด๋–ป๊ฒŒ ์ฐธ์กฐ ์ˆœํ™˜์„ ํ•ด๊ฒฐํ• ๊นŒ์š”?

class Strong {
  weak var strong: Strong? = nil
}

var strong1: Strong? = Strong()
var strong2: Strong? = Strong()

strong1?.strong = strong2
strong2?.strong = strong1

strong1 = nil
strong2 = nil

์œ„์™€ ๊ฐ™์€ ์˜ˆ์‹œ์ด์ง€๋งŒ ๊ฐ๊ฐ์˜ ๊ฐ์ฒด ๋ณ€์ˆ˜๊ฐ€ weak(์•ฝํ•œ ์ฐธ์กฐ)์ด๊ธฐ ๋•Œ๋ฌธ์— ARC๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋  ๋•Œ ์ž๋™์œผ๋กœ ๊ฐ์ฒด๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ์‹œ์ผœ ์ค๋‹ˆ๋‹ค.

์ฐธ์กฐ ์ˆœํ™˜ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ๋„ค์š”!

unowned (๋ฏธ์†Œ์œ  ์ฐธ์กฐ)

  • ํ•ด๋‹น ์ธ์Šคํ„ด์Šค์˜ ์†Œ์œ ๊ถŒ์„ ๊ฐ€์ง€์ง€ ์•Š์Œ
  • unowned reference count๊ฐ€ 0์ด ๋˜๋ฉด free
  • ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๋ฅผ nil๋กœ ์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š์Œ

๊ทธ๋ž˜์„œ ์…‹์˜ ์ฐจ์ด๋Š”?

  • strong
    • ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ
    • Reference Count 1 ์ฆ๊ฐ€
  • weak
    • ์ˆœํ™˜ ์ฐธ์กฐ์˜ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์„ ๊ฒฝ์šฐ ์‚ฌ์šฉ
    • ํ•ญ์ƒ var
    • Reference Count ๋ณ€๋™ X
  • unowned

์‚ฌ์ด๋“œ ํ…Œ์ด๋ธ” (Side Table Entry)

์„ค๋ช…์˜ ์ˆœ์„œ๋Š” ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜ ๋•Œ๋ฌธ์— strong โžก๏ธ weak โžก๏ธ unowned์˜ ์ˆœ์„œ๋กœ ํ–ˆ์ง€๋งŒ ๊ฐœ๋…์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๋ฉด strong โžก๏ธ unowned โžก๏ธ weak์˜ ์ˆœ์„œ๋กœ ๋ณด๋Š” ๊ฒƒ์ด ๋งž์Šต๋‹ˆ๋‹ค.

๊ฐ•ํ•œ ์ฐธ์กฐ ๋ณ€์ˆ˜์™€ ๋ฏธ์†Œ์œ  ์ฐธ์กฐ ๋ณ€์ˆ˜๋Š” ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ฐธ์กฐํ•˜์ง€๋งŒ, ์•ฝํ•œ ์ฐธ์กฐ ๋ณ€์ˆ˜๋Š” ๊ฐ์ฒด์˜ ์‚ฌ์ด๋“œ ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‚ด๋ถ€์ ์œผ๋กœ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด weak, unowned, strong์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ๋”ฐ๋กœ reference count๋ฅผ ์„ธ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ชจ๋“  ์ข…๋ฅ˜์˜ reference count๋ฅผ ์ „๋ถ€ ์…‰๋‹ˆ๋‹ค.

์ˆœ์ฐจ์ ์œผ๋กœ ์‚ดํŽด๋ณด๋ฉด, strong reference count๊ฐ€ 0์ด ๋˜๋ฉด ๊ฐ์ฒด๋Š” deinit ๋˜์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ์—๋Š” ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ดํ›„ unowned reference count๋ฅผ ์ฒดํฌํ•˜์—ฌ 0์ด ์•„๋‹ˆ๋ผ๋ฉด DEINITED ์ƒํƒœ๋กœ ๋ฉ”๋ชจ๋ฆฌ์— ์ญˆ์šฑ ๋‚จ์•„์žˆ๊ณ , 0์ด๋ผ๋ฉด free ๋ฉ๋‹ˆ๋‹ค.

๊ทธ ์ดํ›„์—๋Š” weak reference count๋ฅผ ์ฒดํฌํ•˜์—ฌ 0์ด ์•„๋‹ˆ๋ผ๋ฉด FREED ์ƒํƒœ๊ฐ€ ๋˜์–ด ์‚ฌ์ด๋“œ ํ…Œ์ด๋ธ”์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋‚จ์•„์žˆ๊ณ , 0์ด ๋˜์—ˆ์„๋•Œ์•ผ ๋ชจ๋“  reference count๊ฐ€ 0์ด ๋˜์–ด ์‚ฌ์ด๋“œ ํ…Œ์ด๋ธ”์ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜๋ฉฐ ๊ฐ์ฒด๊ฐ€ DEAD ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

ARC State Machine

์œ„ State Machine ๊ทธ๋ž˜ํ”„๋กœ ํ•œ๋ˆˆ์— ์•Œ์•„๋ณด๊ธฐ ์‰ฝ๊ฒŒ ์ •๋ฆฌํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.