learnings/Swift

[iOS/Swift] ์†Œ๋ฉธ์ž๋ฅผ ์‚ฌ์šฉํ•œ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ

Une. 2024. 3. 26. 19:10

0. ๋ฐœ๋‹จ

ํ™˜ํ˜• ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œํ–ˆ๋Š”๋ฐ, ํ•ด๋‹น ๋ฆฌ์ŠคํŠธ ๋‚ด์˜ ๋…ธ๋“œ๋“ค์ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜์ง€ ์•Š๋Š” ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค.

var myCLL: CircularLinkedList<Int>? = CircularLinkedList<Int>()
for i in 0..<2{
    myCLL!.insertAtLast(DoublyNode(data: i))
}
myCLL = nil

dealloc์ด ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค...
๋˜‘๋˜‘....๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ์ผ์–ด๋‚˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค๋งŒ..?


1. ์ƒํ™ฉ ๋ฐ ์›์ธ ํŒŒ์•…

๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ ์ „, ๋ฆฌ์ŠคํŠธ์— ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ์˜ค๋กœ์ง€ ๋ฉ”์†Œ๋“œ insertAtLast๋งŒ์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค.
๋”ฐ๋ผ์„œ ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋…ธ๋“œ์˜ ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•  ๋•Œ, ๋ฆฌ์ŠคํŠธ์˜ ํŠน์„ฑ์ƒ head์™€ tail ํ”„๋กœํผํ‹ฐ ๋ฐ ์ž…๋ ฅ๋˜๋Š” ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ๋นˆ๋ฒˆํ•˜๋ฏ€๋กœ ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๋“ค์— ๋Œ€ํ•œ ๋งˆ๊ตฌ์žก์ด์‹ ์ ‘๊ทผ์œผ๋กœ RC๊ฐ€ ๋งˆ๊ตฌ์žก์ด๋กœ ์Œ“์ด๋Š” ๊ฒƒ์ด ์›์ธ์ด๋ผ ์ง์ž‘ํ•˜์˜€๋‹ค.

๋ฆฌ์ŠคํŠธ์˜ ๊ตฌํ˜„๋ถ€ ๋ฐ ๋ฆฌ์ŠคํŠธ์— ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ์‚ฌ์šฉํ–ˆ๋˜ insertAtLast ํ•จ์ˆ˜์˜ ๊ตฌํ˜„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

class DoublyNode<T>{
    weak var prevNode: DoublyNode<T>?
    var nextNode: DoublyNode<T>?
    var data: T?
}
class CircularLinkedList<T>{
    var head: DoublyNode<T>?
    weak var tail: DoublyNode<T>?
    
    ....
    
    func insertAtLast(_ newNode: DoublyNode<T>){
        if self.head == nil {
            self.head = newNode
            self.tail = newNode
            head?.prevNode = newNode
            tail?.nextNode = newNode
            return
        }
        self.head?.prevNode = newNode
        self.tail?.nextNode = newNode
        newNode.prevNode = self.tail
        newNode.nextNode = self.head
        self.tail = newNode
    }

 

2. ๋ฌธ์ œ์  ์ฐพ๊ธฐ

๋…ธ๋“œ๋ฅผ 1๊ฐœ๋งŒ ์ถ”๊ฐ€ํ•˜์˜€์„ ๊ฒฝ์šฐ์—๋„ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ๊ฐ€ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค.
์ฆ‰, head == nil ์ผ ๋•Œ์—๋„ ๋ฌธ์ œ๊ฐ€ ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
ํ•ด๋‹น ๋ธ”๋ก์„ ํ•˜๋‚˜์”ฉ ๋œฏ์–ด๋ณด๋ฉด ์ด๋ ‡๋‹ค.

  1. head == nil ์ผ ๋•Œ ๋…ธ๋“œ ์ถ”๊ฐ€ ์‹œ
    1. self.head = newNode // newNode์— ๋Œ€ํ•œ RC 1์ฆ๊ฐ€, total:1
    2. self.tail = newNode 
    3. head?.prevNode = newNode 
    4. tail?.nextNode = newNode // newNode์— ๋Œ€ํ•œ RC 1 ์ฆ๊ฐ€, total:2
  2. ์ด๋•Œ myCLL = nil ์„ ์ˆ˜ํ–‰ ์‹œ
    1. ํ™˜ํ˜• ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜๋ฉฐ ์ œ๊ฑฐ๋จ
    2. ์ธ์Šคํ„ด์Šค ์ œ๊ฑฐ๋กœ ์ธํ•œ ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ๋“ค์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ์ธ์Šคํ„ด์Šค์˜ RC๊ฐ€ 1์”ฉ ๊ฐ์†Œ
    3. ์ด๋•Œ, head๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋…ธ๋“œ์˜ RC๊ฐ€ 1 ๊ฐ์†Œ // newNode์— ๋Œ€ํ•œ RC total:1
    4. ์ƒํ™ฉ ์ข…๋ฃŒ // newNode์— ๋Œ€ํ•œ RC total:1, ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐœ์ƒ

1-4๋กœ ์ธํ•˜์—ฌ ์Šค์Šค๋กœ์— ๋Œ€ํ•œ RC๊ฐ€ ์ฆ๊ฐ€ํ•˜์˜€์œผ๋ฏ€๋กœ, ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์‚ญ์ œํ•œ ํ›„ head์™€ tail ํ”„๋กœํผํ‹ฐ๋ฅผ fileprivat ์ฒ˜๋ฆฌํ•˜์˜€๋‹ค.

์ƒ๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, ์Šค์Šค๋กœ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœํผํ‹ฐ๋Š” weak๋กœ ํ•˜์—ฌ ์Šค์Šค๋กœ์— ๋Œ€ํ•œ RC๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค๋Š”๊ฒƒ์„ ์•Œ์•˜๋‹ค.
๋™์‹œ์—, ๋ฆฌ์ŠคํŠธ ๋‚ด์˜ ๋…ธ๋“œ๋“ค์€ ์ด์ „ ๋…ธ๋“œ์˜ next ํ”„๋กœํผํ‹ฐ๋งŒ์ด ์œ ์ผํ•œ ์ฐธ์กฐ ๊ฒฝ๋กœ์ธ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์œผ๋ฏ€๋กœ next ํ”„๋กœํผํ‹ฐ๋Š” weak๋กœ ์„ค์ •ํ•  ๊ฒฝ์šฐ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์  ๋˜ํ•œ ์—ฐ๊ด€์ง€์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.
๋”ฐ๋ผ์„œ insertAtLastํ•จ์ˆ˜์˜ ๋™์ž‘์— ๋”ฐ๋ผ ์ฆ๊ฐํ•˜๋Š” RC๋ฅผ ์ถ”์ ํ•˜๋ฉฐ ์ˆ˜์ •ํ•œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

    ///๋ฆฌ์ŠคํŠธ์˜ ๋งˆ์ง€๋ง‰์— ๋…ธ๋“œ ์ถ”๊ฐ€
    func insertAtLast(_ newNode: DoublyNode<T>){
        if self.head == nil {
            self.head = newNode
            self.tail = newNode
            return
        }
        newNode.prevNode = self.tail //prevNode๋Š” weak๋ผ rf ์ฆ๊ฐ€ ์•ˆํ•œ๋‹ค
        newNode.nextNode = self.tail?.nextNode //rf 1 ์ฆ๊ฐ€, newNode.nextNode = self.head์‹œ head์— ๋Œ€ํ•œ rf๊ฐ€ ์ฆ๊ฐ€ํ•จ
        self.tail!.nextNode = newNode //์ƒˆ ๋…ธ๋“œ์˜ rf 1 ์ฆ๊ฐ€
        self.tail = newNode //tail์€ weak๋ผ rf ์ฆ๊ฐ€ ์•ˆํ•œ๋‹ค
    }

๊ทธ๋Ÿฌ๋‚˜... ๊ฐ€์žฅ ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ œ๋Š”...

DoublyNode๋Š” ์ด์ „์— ์ด์ค‘ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•˜์—ฌ ์‚ฌ์šฉํ–ˆ๋˜ ํด๋ž˜์Šค์ด๋‹ค.
์ด ํด๋ž˜์Šค๋Š”, ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ์˜ next ํ”„๋กœํผํ‹ฐ๋Š” ํ•ญ์ƒ nil์ด์—ฌ์„œ ์ฒซ ๋…ธ๋“œ์˜ RC๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค์ง€ ์•Š์•˜๋Š”๋ฐ
ํ™˜ํ˜• ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ๋Š” ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๊ฐ€ ์ฒซ ๋…ธ๋“œ์˜ RC๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๊ณ , ์ด๋กœ ์ธํ•˜์—ฌ ์–ด๋А ์ธ์Šคํ„ด์Šค๋„ ํ•ด์ œ๋˜์ง€ ์•Š์•„ RC๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๊ฐ์†Œํ•˜์ง€ ์•Š๊ณ , ์ด๋กœ ์ธํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜๋‹ค.
๋˜ํ•œ, ํ™˜ํ˜• ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ ํด๋ž˜์Šค๋Š” ๋…ธ๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ 3๊ฐœ ์กด์žฌํ•˜์˜€๊ณ , ๊ฐ ํ•จ์ˆ˜์— ๋Œ€ํ•ด ์ถ”๊ฐ€๋˜๋Š” ๋กœ์ง์— ๋”ฐ๋ฅธ RC๋ฅผ ์ถ”์ ํ•˜๋ฉฐ ์ตœ๋Œ€ํ•œ ๋ฆฌ์ŠคํŠธ๊ฐ€ dealloc ๋์„ ๋•Œ ๊ทธ ์•ˆ์˜ ๋…ธ๋“œ ๋ชจ๋‘ dealloc ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ •๋ง ๋งŽ์€ ์‹œ๊ฐ„์„ ํˆฌ์žํ•˜์˜€์œผ๋‚˜ ์‹คํŒจํ•˜์˜€๋‹ค.

๋‚˜์˜ Strong Refence ๋ฒ ์ด๋น„๋“ค...

 

 

3. ๋ฌธ์ œ ํ•ด๊ฒฐ

ํ•œ์ฐธ์„ ์‹ธ๋ฉ”๋‹ค deinit ๋ฉ”์†Œ๋“œ์—์„œ ๋…ธ๋“œ๋“ค์„ dealloc ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๊ณ , ๊ตฌํ˜„์„ ์œ„ํ•ด ํƒ€์ดํ•‘ ํ•˜๋˜ ์ค‘...

์˜ค๋ธŒ์ ํŠธ๊ฐ€ dealloc ๋˜๊ธฐ ์ „, ์ •๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋น„๋กœ์†Œ ์ด์ œ์„œ์•ผ ์†Œ๋ฉธ์ž์˜ ์—ญํ• ์„ ๊นจ๋‹ฌ์•˜๋‹ค.
ํˆดํŒ์„ ๋ณด๋Š” ์ˆœ๊ฐ„ ๋„์„œ๊ด€์—์„œ ํƒ„์„ฑ์„ ๋‚ด์ง€๋ฅผ ๋ป” ํ–ˆ๋‹ค. ์†Œ๋ฉธ์ž์˜ ์กด์žฌ ์ด์œ ๋ฅผ ๊นจ๋‹ฌ์€ ์ˆœ๊ฐ„์ด์—ˆ๋‹ค.
์ปดํ“จํ„ฐ ๊ณตํ•™๊ณผ๋ฅผ ์กธ์—…ํ•œ ํ›„์—์•ผ ์†Œ๋ฉธ์ž์˜ ์“ฐ์ž„์„ ๊นจ๋‹ซ๋‹ค๋‹ˆ....! ์ฐธ์œผ๋กœ ๋ถ€๋„๋Ÿฌ์šด ์ผ์ด๋‹ค.

class CircularLinkedList<T>{
    fileprivate var head: DoublyNode<T>?
    fileprivate weak var tail: DoublyNode<T>?
    deinit {
        var currentNode = self.head
        while(currentNode != nil){
            currentNode?.nextNode = nil
            currentNode = currentNode?.prevNode
        }
    }
    ...
}

์˜ˆ์ƒํ•œ ๋Œ€๋กœ, ๋…ธ๋“œ๋“ค์ด ์ •์ƒ์ ์œผ๋กœ dealloc ๋˜์—ˆ๋‹ค.

 

4. ํ›„๊ธฐ

myCLL = nil ์ผ ๋•Œ, ์†Œ๋ฉธ์ž๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ์„œ๋„ ๋ชจ๋“  ๋…ธ๋“œ๋“ค์ด ๋‹จ๋ฒˆ์— dealloc ๋˜๋„๋ก ํ•˜์ง€ ๋ชปํ•œ๊ฒƒ์— ํฐ ์•„์‰ฌ์›€์ด ๋‚จ๋Š”๋‹ค.
๋งŒ์•ฝ, ์ด ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„๋œ ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ 1์ฒœ๋งŒ๋ช…์˜ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ๊ด€๋ฆฌํ•˜๋Š” ์ฝ”๋“œ์˜€๋‹ค๋ฉด..? ์„œ๋ฒ„์ปดํ“จํ„ฐ๋ฅผ ์ •๋ง ๋งŽ์ด ์žฌ๋ถ€ํŒ…ํ–ˆ์–ด์•ผ๊ฒ ์ง€...

์ทจ์—…์„ ์ค€๋น„ํ•˜๋ฉฐ, Swift๋ฅผ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ๋‹ค์‹œ ๋‹ค์ง€๋Š” ๊ณผ์ •์—์„œ ๊ทธ๋™์•ˆ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•˜๋˜ ๋ถ€๋ถ„๋“ค๋„ ์Šต๋“ํ•˜๋ ค ํž˜์“ฐ๊ณ  ์žˆ๋‹ค.
๊ทธ๋™์•ˆ ์ง€๋‚˜์ณค๋˜ ๊ฒƒ๋“ค์— ๋Œ€ํ•œ ์ค‘์š”์„ฑ์„ ๊นŠ์ด ๊นจ๋‹ซ๋Š”๋‹ค. ์—ญ์‹œ ๊ธฐ์ดˆ๋Š” ์‰ฌ์šด๊ฒŒ ์•„๋‹ˆ๋ผ ์ค‘์š”ํ•œ ๊ฒƒ์ด๋‹ค.
์•ž์œผ๋กœ ๊ณต๋ถ€ํ•  ๊ฒƒ๊ณผ ๊ฒฝํ—˜ํ•  ๊ฒƒ๋“ค์— ๊ธฐ๋Œ€๊ฐ์ด ์ƒ๊ธด๋‹ค!