์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

[Design Patterns] ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด(Delegate Pattern)

๐ŸŽ iOS/Patterns & Arch

by AHN.Jihyeon 2024. 7. 8. 02:20

๋ณธ๋ฌธ


๐Ÿ’ฌ  Introduction

 

ํ…์ŠคํŠธํ•„๋“œ : ์œ ์ €๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ์„ ๋ฐ›๋Š”๋‹ค. 

 

์ž…๋ ฅ๋œ ๋™์ž‘๋“ค์„ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์— ์ „๋‹ฌํ•œ๋‹ค.

์ด๋•Œ, ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ(๋Œ€๋ฆฌ์ž) ํŒจํ„ด์ด ํ•„์š”ํ•˜๋‹ค. 

์ฆ‰, ํ…์ŠคํŠธ ํ•„๋“œ์˜ ๋Œ€๋ฆฌ์ž๋Š” ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋œ๋‹ค. 

 

ํ…์ŠคํŠธํ•„๋“œ๋ผ๋Š” ๊ฐ์ฒด์™€ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋ผ๋Š” ๊ฐ์ฒด๊ฐ€ ์žˆ์„ ๋•Œ

ํ…์ŠคํŠธํ•„๋“œ์™€ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์˜ ์˜์‚ฌ์†Œํ†ต์„ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด

์ด ์˜์‚ฌ์†Œํ†ต์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ค‘๊ฐ„์˜ ๋Œ€๋ฆฌ์ž(๋ธ๋ฆฌ๊ฒŒ์ดํŠธ)๋Š” ํ”„๋กœํ† ์ฝœ ํƒ€์ž…์œผ๋กœ ์„ค์ •ํ•˜๊ณ 

ํ”„๋กœํ† ์ฝœ ํƒ€์ž…์œผ๋กœ ๋™์ž‘์ด ์ „๋‹ฌ๋œ๋‹ค.

 

๊ฐ์ฒด ๋‚ด์—์„œ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ์„ค์ •ํ•œ๋‹ค๋ฉด self๋ผ๊ณ  ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 

์—†๋‹ค๋ฉด ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ์ง์ ‘์ ์œผ๋กœ ์„ค์ •

 

๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋Š” ํ…์ŠคํŠธ ํ•„๋“œ์˜ ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•ด์•ผ ํ•œ๋‹ค. 

์ด ํ”„๋กœํ† ์ฝœ์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์„ ํƒ์ ์ธ ์š”๊ตฌ์‚ฌํ•ญ๋“ค(๋ฉ”์„œ๋“œ)์„ ๊ตฌํ˜„ํ•˜๋ฉด

ํ…์ŠคํŠธํ•„๋“œ์—์„œ ๋ฐœ์ƒํ•œ ๋‚ด์šฉ๋“ค์„ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

 

 

 

๐Ÿ”Ž  1 . ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด


Delegate : ๋Œ€๋ฆฌ์ž, ๋Œ€์‹  ์ˆ˜ํ–‰ํ•˜๋Š” ์‚ฌ๋žŒ, ์œ„์ž„์ž

 

protocol์— ๋Œ€์‹  ์ฒ˜๋ฆฌํ•ด์ฃผ๊ธธ ๋ฐ”๋ผ๋Š” ๋‚ด์šฉ์„ ์ž‘์„ฑํ•ด์„œ ์œ„์ž„ํ•œ๋‹ค. 

๊ทธ ์ผ์„ ์œ„์ž„ ๋ฐ›์€ ๊ฐ์ฒด๋Š” ๊ทธ ์ผ์„ ๊ตฌ์ฒด์ ์œผ๋กœ ๋Œ€์‹  ์ฒ˜๋ฆฌํ•œ๋‹ค. 

 

 

๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์˜ ๊ตฌ์„ฑ 

1. ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํ”„๋กœํ† ์ฝœ ์ •์˜

๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๊ฐ์ฒด๊ฐ€ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋Š” ํ”„๋กœํ† ์ฝœ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

protocol MyDelegate: AnyObject {
    func didPerformAction()
}

 

 

2. ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํ”„๋กœํผํ‹ฐ ์ •์˜

๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•  ํ”„๋กœํผํ‹ฐ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๋ณดํ†ต weak๋กœ ์„ ์–ธํ•˜์—ฌ ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜(๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜)์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

class MyClass {
    weak var delegate: MyDelegate?
    
    func performAction() {
        // ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ ํ›„ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ
        delegate?.didPerformAction()
    }
}

 

 

weak ํ‚ค์›Œ๋“œ์˜ ์—ญํ• ๊ณผ ์‚ฌ์šฉ ์ด์œ 

weak ํ‚ค์›Œ๋“œ์˜ ์—ญํ• 

weak ํ‚ค์›Œ๋“œ๋Š” ์ฐธ์กฐ ์ˆœํ™˜(reference cycle)์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ฐธ์กฐ ์ˆœํ™˜์€ ๋‘ ๊ฐ์ฒด๊ฐ€ ์„œ๋กœ๋ฅผ ๊ฐ•ํ•˜๊ฒŒ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์–ด, ๋‘˜ ๋‹ค ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜์ง€ ์•Š๋Š” ์ƒํ™ฉ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. weak ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ•ํ•œ ์ฐธ์กฐ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

์‚ฌ์šฉ ์ด์œ 

์ฐธ์กฐ ์ˆœํ™˜ ๋ฐฉ์ง€: weak ์ฐธ์กฐ๋Š” ๊ฐ์ฒด๊ฐ€ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๊ฐ•ํ•˜๊ฒŒ ์ฐธ์กฐํ•˜์ง€ ์•Š๋„๋ก ํ•˜์—ฌ ์ฐธ์กฐ ์ˆœํ™˜์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

์ž๋™ ํ•ด์ œ: weak ์ฐธ์กฐ๋Š” ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๊ฐ์ฒด๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋  ๋•Œ, ์ž๋™์œผ๋กœ nil๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

 

 

์˜ˆ์‹œ

๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์—์„œ weak ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ์ฃผ๋กœ ์ฐธ์กฐ ์ˆœํ™˜์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์—์„œ ๊ฐ์ฒด A๊ฐ€ ๊ฐ์ฒด B๋ฅผ ์ฐธ์กฐํ•˜๊ณ , ๊ฐ์ฒด B๊ฐ€ ๊ฐ์ฒด A๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํ”„๋กœํผํ‹ฐ๋ฅผ weak๋กœ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

 

protocol MyDelegate: AnyObject {
    func didPerformAction()
}

class MyClass {
    weak var delegate: MyDelegate?
    
    func performAction() {
        delegate?.didPerformAction()
    }
}

class MyDelegateClass: MyDelegate {
    func didPerformAction() {
        print("Action was performed")
    }
}

let myObject = MyClass()
let delegateObject = MyDelegateClass()

myObject.delegate = delegateObject
myObject.performAction()

์—ฌ๊ธฐ์„œ MyClass์˜ delegate ํ”„๋กœํผํ‹ฐ๋ฅผ weak๋กœ ์„ ์–ธํ•จ์œผ๋กœ์จ delegateObject๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋  ๋•Œ delegate ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ž๋™์œผ๋กœ nil๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

3. ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๊ฐ์ฒด ๊ตฌํ˜„

๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๊ณ  ํ”„๋กœํ† ์ฝœ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

class MyDelegateClass: MyDelegate {
    func didPerformAction() {
        print("Action was performed")
    }
}

 

 

 

4. ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ์„ค์ • ๋ฐ ์‚ฌ์šฉ

๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํ”„๋กœํผํ‹ฐ์— ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

let myObject = MyClass()
let delegateObject = MyDelegateClass()

myObject.delegate = delegateObject
myObject.performAction()  // "Action was performed" ์ถœ๋ ฅ

 

 

 

 

๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์˜ ์žฅ๋‹จ์ 

์žฅ์ 

๊ฐ์ฒด ๊ฐ„์˜ ์ฑ…์ž„ ๋ถ„๋ฆฌ: ๊ฐ์ฒด ๊ฐ„์˜ ์—ญํ• ๊ณผ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค.

์œ ์—ฐ์„ฑ ์ฆ๊ฐ€: ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด ๋™์ผํ•œ ์ž‘์—…์„ ์—ฌ๋Ÿฌ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ์œ ์—ฐ์„ฑ์ด ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ•ํ•œ ๊ฒฐํ•ฉ๋„ ๊ฐ์†Œ: ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์€ ๊ฐ์ฒด ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”์–ด ์ฝ”๋“œ์˜ ์œ ์—ฐ์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ๋†’์ž…๋‹ˆ๋‹ค.

 

๋‹จ์ 

๋ณต์žก์„ฑ ์ฆ๊ฐ€: ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์„ ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ๋ณต์žก์„ฑ์ด ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”์  ์–ด๋ ค์›€: ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๋ฉ”์„œ๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ํ˜ธ์ถœ๋  ๊ฒฝ์šฐ, ์ฝ”๋“œ์˜ ํ๋ฆ„์„ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

 

๐Ÿ”Ž 2. ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์—์„œ ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ?

 

1. ์œ ์—ฐ์„ฑ๊ณผ ํ™•์žฅ์„ฑ

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

 

2. ๋ช…ํ™•ํ•œ ๊ณ„์•ฝ

ํ”„๋กœํ† ์ฝœ์€ ๊ฐ์ฒด๊ฐ€ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋Š” ์ผ์ข…์˜ ๊ณ„์•ฝ(Contract)์ž…๋‹ˆ๋‹ค. ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์—์„œ ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๊ฐ์ฒด๊ฐ€ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๋ฉ”์„œ๋“œ๊ฐ€ ๋ช…ํ™•ํžˆ ์ •์˜๋˜์–ด, ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋“ค์ด ๋น ์ง์—†์ด ๊ตฌํ˜„๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

3. ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ

ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ํด๋ž˜์Šค์—์„œ ๋™์ผํ•œ ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜์—ฌ, ์ค‘๋ณต๋œ ์ฝ”๋“œ๋ฅผ ์ค„์ด๊ณ  ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ๋™์ž‘์„ ๋‹ค์–‘ํ•œ ํด๋ž˜์Šค์— ๊ฑธ์ณ ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

4. ๊ฐ์ฒด ๊ฐ„ ์˜์กด์„ฑ ๊ฐ์†Œ

ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด ๊ฐ„์˜ ๊ฐ•ํ•œ ์˜์กด์„ฑ์„ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์ฒด๋Š” ํŠน์ • ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•œ ๋‹ค๋ฅธ ๊ฐ์ฒด์™€๋งŒ ์ƒํ˜ธ์ž‘์šฉํ•˜๋ฏ€๋กœ, ๊ฐ์ฒด ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์•„์ง‘๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ”๋“œ์˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ด๊ณ , ๊ฐ์ฒด ๊ต์ฒด๋‚˜ ๋ณ€๊ฒฝ์ด ์šฉ์ดํ•ด์ง‘๋‹ˆ๋‹ค.

 

5. ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ถ„๋ฆฌ

ํ”„๋กœํ† ์ฝœ์„ ํ†ตํ•ด ํŠน์ • ์—ญํ• ์— ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋งŒ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋‹จ์ผ ์ฑ…์ž„ ์›์น™(Single Responsibility Principle)์„ ์ง€ํ‚ค๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ๊ฐ์ฒด๋Š” ์—ฌ๋Ÿฌ ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜์—ฌ ๊ฐ๊ฐ์˜ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ถˆํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ํฌํ•จํ•˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

 

 

๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ

class SpecificDelegateClass {
    func didPerformAction() {
        print("Action performed")
    }
}

class MyClass {
    var delegate: SpecificDelegateClass?
    
    func performAction() {
        delegate?.didPerformAction()
    }
}

๋งŒ์•ฝ ํ”„๋กœํ† ์ฝœ ์—†์ด ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด, ํŠน์ • ํด๋ž˜์Šค ํƒ€์ž…์„ ์ง์ ‘ ์ฐธ์กฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ์ฒด ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋†’์ด๊ณ , ์ฝ”๋“œ์˜ ์œ ์—ฐ์„ฑ๊ณผ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋–จ์–ด๋œจ๋ฆฝ๋‹ˆ๋‹ค.

 

์ด ๊ฒฝ์šฐ, MyClass๋Š” SpecificDelegateClass์— ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋‹ค๋ฅธ ํด๋ž˜์Šค๊ฐ€ ์ด ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค๋ฉด MyClass๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

 

 

ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•œ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด

protocol MyDelegate: AnyObject {
    func didPerformAction()
}

class MyClass {
    weak var delegate: MyDelegate?
    
    func performAction() {
        delegate?.didPerformAction()
    }
}

class DelegateClassA: MyDelegate {
    func didPerformAction() {
        print("Action performed by DelegateClassA")
    }
}

class DelegateClassB: MyDelegate {
    func didPerformAction() {
        print("Action performed by DelegateClassB")
    }
}

let myObject = MyClass()
let delegateA = DelegateClassA()
let delegateB = DelegateClassB()

myObject.delegate = delegateA
myObject.performAction() // "Action performed by DelegateClassA"

myObject.delegate = delegateB
myObject.performAction() // "Action performed by DelegateClassB"

ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋ฉด, ์–ด๋–ค ํด๋ž˜์Šค๊ฐ€ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ• ์ง€์— ๋Œ€ํ•ด ์œ ์—ฐํ•˜๊ฒŒ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

DelegateClassA์™€ DelegateClassB๊ฐ€ ๋ชจ๋‘ MyDelegate ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, MyClass๋Š” ํŠน์ • ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํด๋ž˜์Šค์— ์ข…์†๋˜์ง€ ์•Š๊ณ  ์œ ์—ฐํ•˜๊ฒŒ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๊ฐ์ฒด๋ฅผ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

๐Ÿ”Ž  3. ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด๊ณผ ํด๋กœ์ €(Completion Handler) ๋น„๊ต


๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด๊ณผ ํด๋กœ์ €๋Š” ๊ฐ๊ฐ ํŠน์ • ์ž‘์—…์„ ๋‹ค๋ฅธ ๊ฐ์ฒด์— ์œ„์ž„ํ•˜๊ฑฐ๋‚˜ ์™„๋ฃŒ ์‹œ ํŠน์ • ๋™์ž‘์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋‘˜์˜ ์žฅ๋‹จ์ ์„ ๋น„๊ตํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด

protocol DataFetcherDelegate: AnyObject {
    func didFetchData(_ data: Data)
}

class DataFetcher {
    weak var delegate: DataFetcherDelegate?
    
    func fetchData() {
        // ๋ฐ์ดํ„ฐ ์š”์ฒญ ์ฝ”๋“œ
        let data = Data() // ์˜ˆ์ œ ๋ฐ์ดํ„ฐ
        delegate?.didFetchData(data)
    }
}

class ViewController: DataFetcherDelegate {
    func didFetchData(_ data: Data) {
        print("Data received")
    }
}

์žฅ์ :

์ฑ…์ž„ ๋ถ„๋ฆฌ: ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์€ ์—ญํ• ๊ณผ ์ฑ…์ž„์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์œ ์—ฐ์„ฑ: ํ•˜๋‚˜์˜ ๊ฐ์ฒด๊ฐ€ ์—ฌ๋Ÿฌ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์žฌ์‚ฌ์šฉ์„ฑ: ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํŒจํ„ด์„ ํ†ตํ•ด ๊ฐ์ฒด ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถฐ ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋‹จ์ :

๋ณต์žก์„ฑ ์ฆ๊ฐ€: ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ํ”„๋กœํ† ์ฝœ์„ ์ •์˜ํ•˜๊ณ , ๊ฐ์ฒด ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ณผ์ •์—์„œ ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”์  ์–ด๋ ค์›€: ์—ฌ๋Ÿฌ ๊ฐ์ฒด๊ฐ€ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ, ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

ํด๋กœ์ €(Completion Handler)

class DataFetcher {
    func fetchData(completion: @escaping (Data) -> Void) {
        // ๋ฐ์ดํ„ฐ ์š”์ฒญ ์ฝ”๋“œ
        let data = Data() // ์˜ˆ์ œ ๋ฐ์ดํ„ฐ
        completion(data)
    }
}

class ViewController {
    func loadData() {
        let dataFetcher = DataFetcher()
        dataFetcher.fetchData { data in
            print("Data received")
        }
    }
}

์žฅ์ :

๊ฐ„๊ฒฐํ•จ: ํด๋กœ์ €๋Š” ์ฝ”๋“œ ๋ธ”๋ก ์ž์ฒด๋กœ ๋ฐ”๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด, ๊ฐ„๋‹จํ•œ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ๊ฐ€๋…์„ฑ: ์ฝ”๋“œ์˜ ํ๋ฆ„์„ ๋”ฐ๋ผ๊ฐ€๊ธฐ๊ฐ€ ์‰ฌ์›Œ, ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ€๋…์„ฑ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค.

์ผํšŒ์„ฑ ์ž‘์—…์— ์ ํ•ฉ: ํŠน์ • ์ž‘์—… ์™„๋ฃŒ ํ›„ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๋Š” ๋กœ์ง์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

 

๋‹จ์ :

ํ™•์žฅ์„ฑ ์ œํ•œ: ํด๋กœ์ €๋Š” ์ผํšŒ์„ฑ ์ž‘์—…์— ์ ํ•ฉํ•˜์ง€๋งŒ, ๋ณต์žกํ•œ ๋กœ์ง์ด๋‚˜ ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฒฝ์šฐ ํ™•์žฅ์„ฑ์ด ๋–จ์–ด์ง‘๋‹ˆ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ: ํด๋กœ์ €์—์„œ self๋ฅผ ์บก์ฒ˜ํ•  ๋•Œ ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด, ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด [weak self]๋‚˜ [unowned self]๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

๐Ÿ”— Reference 


 

 

 

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ