- ํ ํ๋ก์ ํธ(2์ธ)
- ํ๋ก์ ํธ ๊ธฐ๊ฐ: 2021.12.20 ~ 2021.12.31
Queue
LinkedList
Generic
Protocol
Delegate Pattern
SOLID : SRP
Wildcard Pattern
Strong Reference Cycle
Core Foundation
vsFoundation
CFAbsoluteTime
Date
GCD
DispatchQueue
Semaphore
DispatchGroup
async
sync
Serial
Concurrent
UI ๊ตฌ์ฑ (only Code)
Timer
RunLoop
Custom View
Auto Layout
์ํ ์ฐฝ๊ตฌ ์ ๋ฌด ์ค์ผ์ค์ ๊ด๋ฆฌํ๋ ๊ธฐ๋ฅ์ ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ์ ํ์ฉํ์ฌ ๊ตฌํํ ์ฑ์ด์์. ๐ฆ
์๋์ด ์ ์ฅํ ์์๋๋ก ๋๊ธฐํ๋ฅผ ๋๋ ์ฃผ๊ณ , ๋๊ฐ์ ์ฐฝ๊ตฌ์์ ๋งก์ ์ ๋ฌด๋ฅผ ๋์์ ์์๋๋ก ์ฒ๋ฆฌํด์ ! ๐ช๐ป
-
์ํฉ
append๋ฅผ ํ ๋ ์ฐ๊ฒฐ๋ ๋ฆฌ์คํธ๋ค์ ๊ฐ์ฅ ๋ง์ง๋ง ๋ถ๋ถ์ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ค์ผํ๋๋ฐ, ์์๋ฅผ ํ์ํ๊ธฐ ์ํด ๋ฐ๋ณต์ ์ผ๋ก ํฌ์ธํฐ๋ฅผ ์ถ์ ํ๋ ์์ ์ ํด์ผํ๋ ์ ์ ๊น๋ํ๊ฒ ํด๊ฒฐํด๋ณด๊ณ ์ถ์๋ค. -
์ด์
Queue๋ฅผ ์ํ LinkedList์ธ ์ ๋ ์๊ณ , ๋ ๊ฐ ์์๋ฅผ ํ์ํ๊ธฐ ์ํด ๋ฐ๋ณต์ ์ผ๋ก ํฌ์ธํฐ๋ฅผ ์ถ์ ํ๊ฒ ๋๋ค๋ฉด ์๊ฐ๋ณต์ก๋๊ฐ O(n)์ด๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ ์ ๊ทผ ๋ฐฉ์์ด ๋งค์ฐ ๋นํจ์จ์ ์ธ ์ ์ ํด๊ฒฐํ๊ณ ์ถ์๋ค. -
ํด๊ฒฐ
ํด๋์ค์ ์ฐธ์กฐ๋ฅผ ํ์ฉํ์ฌ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ฅผ ์ฐ๊ฒฐํ๋๋ก ๊ตฌํํ์๋ค.func append(_ value: Element) { let newNode = Node(value: value) if isEmpty { head = newNode tail = newNode } else { tail?.next = newNode tail = newNode } }
-
์ํฉ
๊ธฐ์กด์ ์์ผ๋์นด๋ ํจํด์ผ๋ก ์ธ์คํด์ค ์์ฑํ ํ์ ์ด Delegate๋ฅผ ์ฑํํ๊ณ ์๋ ํํ์๋ค. ์ดํ ์ํ์ฐธ์กฐ ๋ฌธ์ ๊ฐ ์ฐ๋ ค๋์ด ๊ฐ ํ์ ๋ค๋ง๋ค delegate ํ๋กํผํฐ์ weak ํค์๋๋ฅผ ๋ถ์ฌ์ฃผ์๋ค. -
์ด์
๊ทธ๋ฐ๋ฐ weak ํค์๋๋ฅผ ๋ถ์ฌ์ฃผ๋ ํด๋น ํ์ ์์ ์ถ๋ ฅํด์ฃผ์๋ ๋ฉ์๋๊ฐ ์คํ๋์ง ์์๋ค. init๊ณผ deinit์ ํตํด ๋๋ฒ๊น ์ ํด๋ณด๋ ์์ผ๋์นด๋ ํจํด์ผ๋ก ์์ฑํ ์ธ์คํด์ค๊ฐ ์์ฑ๊ณผ ๋์์ ํด์ ๋๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค.์์ผ๋์นด๋ ํจํด
์ ๊ฐ์ ํด์ฒดํ๊ฑฐ๋ ๋ฌด์ํ๋ ํจํด์ค ํ๋์ด๋ฏ๋กweak ํค์๋
๊ฐ ์ถ๊ฐ๋จ๊ณผ ๋์์ retain count๊ฐ ์ฌ๋ผ๊ฐ์ง ์๊ธฐ ๋๋ฌธ์ ์์ฑ๊ณผ ๋์์ ํด์ ๋๋ ๊ฒ์ด์๋ค. -
ํด๊ฒฐ
์ฌ์ฉํ์ง ์๋ viewController(์ํ์, ์ํ)๋ฅผ ์์์ ๋ด์ผ๋ฉด xcode์์ ๊ฒฝ๊ณ ๋ฉ์ธ์ง๊ฐ ๋ฐ์ํ๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ์์ผ๋ ์นด๋ ํจํด์ ์ฌ์ฉํด์ ์ํ์ฐธ์กฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๊ณ ํ๋จ๋์ด weak ํค์๋๋ฅผ ์ ๊ฑฐํ๊ณ ์์ผ๋์นด๋ ํจํด์ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.final class Bank { private let bankClerk: BankClerk private var customerQueue = Queue<Customer>() var delegate: BankDelegate? // weak ํค์๋ ์ ๊ฑฐ ... } func run() { let bankClerk = BankClerk() let bank = Bank(bankClerk: bankClerk) let bankManager = BankManager(bank: bank) let _ = BankClerkViewController(bankClerk: bankClerk) let _ = BankViewController(bank: bank) ... }
-
์ํฉ
- ํ์์ธ ํํฉ๊ณผ ๋๋ ์ฝ์์ฑ ๋ค์ ์คํ ์ ์์ ViewController๋ฅผ ์ถ๊ฐํ๋ ์์ ๊น์ง ์ถ์ธกํ์ฌ ๋ฏธ๋ฆฌ ์ฝ์์ฑ์ ๊ตฌํํ ๋๋ถํฐ Delegate ํจํด๊น์ง ๊ณ ๋ คํ์ฌ ์ค๊ณ๋ฅผ ํ์๋ค. (์ ์ฌ์ง์ ๋น์ ์์ฑํ๋ UML์ด๋ค.)
- ๋ฆฌ๋ทฐ์ด์๊ฒ ์ฝ๋๋ฆฌ๋ทฐ๋ฅผ ๋ฐ๊ณ ๋ค์ ์ดํด๋ณด๋ฉฐ ๊ณ ๋ฏผํด๋ณธ ๊ฒฐ๊ณผ, ์ฝ์์ฑ์์ ๋ถํ์ํ ์ญํ ๋ถ๋ฆฌ๊ฐ ์ผ์ด๋์ ์คํ๋ ค ์ฝ๋ ๊ฐ๋ ์ฑ์ด ๋งค์ฐ ๋จ์ด์ก๋ค.
-
์ด์
- ๋น์ฅ ๋ง๋ค์ด์ผํ ๊ธฐ๋ฅ์ด ์๋๋ผ ์ถํ ์ถ๊ฐ๋ ๊ธฐ๋ฅ๊น์ง ์ถ์ธกํ์ฌ ์ค๊ณํ ํ์ด ํฐ ๋ฌธ์ ์ ์ธ ๊ฒ ๊ฐ๋ค.
-
ํด๊ฒฐ
- ๋ฐ๋ผ์ ๋ค์ ๊ธฐ๋ฅ์ด ์ด๋ป๊ฒ ์ถ๊ฐ๋ ์ง ์ ์ ์๋ ์ํ์์๋ ์ต์ํ์ ๊ธฐ๋ฅ๋ง ๋น ๋ฅด๊ฒ ์์ ํด๋ฒ๋ฆํ๋ ์ต๊ด์ ๋ค์ฌ์ผ๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๊ณ , ๋์ค์ ๊ธฐ๋ฅ ์๊ตฌ์ฌํญ์ด ์ถ๊ฐ๋๋ค๋ฉด, ๊ฑฐ๊ธฐ์ ๋ง๊ฒ ๋ค์ ์ค๊ณ๋ฅผ ํด์ผ๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
- ์ถ์ธกํ์ฌ ์ค๊ณํ ๋ถ๋ถ์ ๋ค ์์ ํ์๋ค. ์ถํ ๊ธฐ๋ฅ ์๊ตฌ์ฌํญ์ด ๋์จ๋ค๋ฉด, ๊ทธ๋ ๋ค์ ์ค๊ณํด๋ณด๊ธฐ๋ก ํ์๋ค.
-
๋๋์
- ๋ค์ ์คํ ์ ์ง๋ ์ง์ํด์ ๊ฐ๋ฐํ์ง ๋ง์
- ๊ทธ๋ฅ ์๊ตฌ์ฌํญ์ ๋ง์ถฐ ์ต์ํ์ ๊ธฐ๋ฅ์ ๋นจ๋ฆฌ ๋ง๋ค์ด๋ณด์.
- ์๋ํ๊ณ ์คํจํ๊ณ ๋์๊ฐ๋ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ฉฐ ๊ฐ์ ํด๋๊ฐ๋ ๋ฐฉํฅ์ผ๋ก ์งํํ์.
์ํฉ
- ์ํ์์ ์๋งํผ DispatchQueue๋ฅผ ๋ง๋ค์ด์ฃผ๊ณ ์๊ณ , ๊ทธ ์์์ dequeue๋ฅผ ํ๊ธฐ ์ํด ๊ณ ๊ฐ์ ํ์ ์ ๊ทผํ๊ณ ์๋ค.
- ์ฌ๋ฌ ์ค๋ ๋์์ ๊ณ ๊ฐ์ ํ๋ฅผ ์ ๊ทผํ ์ ์๋ ๊ฐ๋ฅ์ฑ์ด ์๋ค.
- ๊ทธ๋ฌ๋ ํ์ฌ ์ฐ๋ฆฌ ์ฝ๋์์๋ race condition์์ด ์ ์๋ํ๋ค. ์ด์ ๊ฐ ๋ฌด์์ผ๊น?
- ์ํ์์ ์๋งํผ DispatchQueue๋ฅผ ๋ง๋ค์ด์ฃผ๊ณ ์๊ณ , ๊ทธ ์์์ dequeue๋ฅผ ํ๊ธฐ ์ํด ๊ณ ๊ฐ์ ํ์ ์ ๊ทผํ๊ณ ์๋ค.
์ด์
1. ์ผ๋จ ์ํ์์ ์(DispatchQueue)๊ฐ ์ ๋ค. 3๊ฐ๋ฟ์ด๋ค. ๋ฐ๋ผ์ ์ค๋ ๋๋ 3๊ฐ ์ด์ ์๊ธฐ์ง ์๋๋ค. 2. ๊ทธ๋ฆฌ๊ณ ๊ฐ ์ ๋ฌด๋ฅผ ํ ๋ ์ค๋ ๋๋ฅผ ์ ์ฌ์ด๋ค. ๋๋ ์ด๊ฐ ์๋ค. 3. ๊ณ ๊ฐ์ ์ซ์๋ ์ ์ํธ์ด๋ค.
- ๋ฐ๋ผ์ ๊ฒฐ๋ก ์ ํ์ฌ ์
ํ
(
์ํ์ ์
,๊ณ ๊ฐ ์
,๋๋ ์ด
) ๋๋ฌธ์ race condition์ด ๋ฐ์ํ์ง ์๋๋ค๋ ํ๋จ์ด ๋ค์๋ค. - ํ์ฌ๋ race condtion์ด ๋ฐ์ํ์ง ์๊ณ ์ ์์ ์ผ๋ก ์๋ํ์ง๋ง, ๊ฒฐ๊ตญ์
Queue
๋Thread-Safe
ํ์ง ์๊ธฐ ๋๋ฌธ์, race condition์ด ๋ฐ์ํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ๋ ์ฅ๋ดํ ์ ์๋ค๋ ๊ฒฐ๋ก ์ด๋ค.- ๋ฐ๋ผ์ DispatchSemaphore๋ฅผ ์ฌ์ฉํด์ ์ ๊ทผํ ์ ์๋ ์ค๋ ๋์ ์๋ฅผ ์ ํํด์ฃผ๋ ๊ฒ์ด ์์ ํ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
- ํ์ง๋ง ์ด ๋ฐฉ๋ฒ๋ ํ
์คํธ ๊ฒฐ๊ณผ
customers.dequeue
์์ ๋ค์ด for๋ฌธ์ผ๋ก ์ธํด ์์ ์ด ์์ฌ์๊ณ , ํ์ ์ ๊ทผ์ ์ธ๋งํฌ์ด๋ก ์ ํํ๊ณ ์์ผ๋, ์ ํํ๋ ๋์ ์์ธ ์์ ๋ค์ด ์ ํ์ด ํ๋ฆฌ๊ณ ์คํ๋๋ฉด ๋น์ด์๋ ํ์ ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์ fatalError๊ฐ ๋ฐ์ํ ์ ์๋ค.
- ๋ฐ๋ผ์ ๊ฒฐ๋ก ์ ํ์ฌ ์
ํ
(
ํด๊ฒฐ
- ํ์ฌ global()๋ก ๋์์ฑํ๋ฅผ ์ฌ์ฉํ๊ณ ์๋๋ฐ, ์ด ๋ถ๋ถ์ Serial Queue๋ก ๋ง๋ค์ด์ ์ง์๋ฅผ ์งํค๊ฒ ํด์ฃผ๋ฉด ๋งค์ฐ ์์ ํ ๊ฒ ๊ฐ๋ค. ๐
- ํ ์คํธ ๊ฒฐ๊ณผ, race condition ๋ฐ์ ํ์ง ์์๋ค!!!!!
- ํ์ฌ global()๋ก ๋์์ฑํ๋ฅผ ์ฌ์ฉํ๊ณ ์๋๋ฐ, ์ด ๋ถ๋ถ์ Serial Queue๋ก ๋ง๋ค์ด์ ์ง์๋ฅผ ์งํค๊ฒ ํด์ฃผ๋ฉด ๋งค์ฐ ์์ ํ ๊ฒ ๊ฐ๋ค. ๐
- ๊ฐ์ ๋ ์ฝ๋
- ๋ฉค๋ฒ๋ณ์๋ก Serial Queue๋ฅผ ์์ฑํด์ฃผ๊ณ DispatchQueue.global() ๋์ ์ง์ ์์ฑํด์ค bankerQueue๋ฅผ ์ฌ์ฉํ๋๋ก ๊ฐ์ ํ์๋ค.
- DispatchQueue๊ฐ ์ง์ญ๋ณ์๊ฐ ์๋๋ผ ๋ฉค๋ฒ๋ณ์์ฌ์ผํ๋ ์ด์ ๋ ๋ญ๊น?
- DispatchQueue์ ๋น๋๊ธฐ๋ก ํ๋ฅผ ๋ณด๋ด๊ณ ์๋ ๋ถ๋ถ์ด for๋ฌธ์ ์ํด 4๋ฒ ๋ถ๋ฆฐ๋ค๊ณ ํ์ ๋, ์ง์ญ๋ณ์๋ก DispatchQueue๊ฐ 4๊ฐ, ์ฆ ๊ฐ๊ฐ์ ์์ ๋ง๋ค ์์ฑ๋ ํ ๋ ์ค์ง์ ์ผ๋ก ๋์์ ์ ๊ทผํ๋ ๊ฒ์ ๋ง์์ฃผ์ง ๋ชปํ ๊ฒ์ด๋ค.
- ๋ฐ๋ผ์ for๋ฌธ ๋ด๋ถ์์ Queue๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ ๋ฐ๊นฅ์์ ์์ฑํด์, ๊ทธ ํด๋น ํ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก ํ์ฉํด์ผ ํ๋ค.
- Semaphore๋ฅผ ํ์ฉํ ๋์๋ ์์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฉค๋ฒ๋ณ์์ฌ์ผ ํ๋ค!!!!
- DispatchQueue๊ฐ ์ง์ญ๋ณ์๊ฐ ์๋๋ผ ๋ฉค๋ฒ๋ณ์์ฌ์ผํ๋ ์ด์ ๋ ๋ญ๊น?
- ๋ฉค๋ฒ๋ณ์๋ก Serial Queue๋ฅผ ์์ฑํด์ฃผ๊ณ DispatchQueue.global() ๋์ ์ง์ ์์ฑํด์ค bankerQueue๋ฅผ ์ฌ์ฉํ๋๋ก ๊ฐ์ ํ์๋ค.
์ํฉ
UIButton์ View์ ์์๋ฅผ ์ ๋ฐ์ดํธ ํ๋๋ก ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ณ ํ ์คํธ ํด๋ณด์์ผ๋, ๋ฒํผ์ด ํด๋ฆญ๋จ๊ฐ ๋์์ ํ๋ฉด์ด ๋ฉ์ถ๊ณ ์๋ฌ๊ฐ ๋๋ฉด์ ๋ทฐ๊ฐ ์ ๋ฐ์ดํธ ๋์ง ์๋ ์ํฉ์ ๋ง์ฃผํ๋ค.
์ด์
๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ๋ทฐ๋ฅผ ๊ทธ๋ฆฌ๋ ์์ ์ main thread์์ ์ฒ๋ฆฌํด์ฃผ์ด์ผ ํ๋๋ฐ, ๋ฐ๋ก ์ฒ๋ฆฌํด์ฃผ์ง ์์์ ํด๋น ์๋ฌ๊ฐ ๋ฐ์ํ๋ ๊ฒ ๊ฐ๋ค.ํด๊ฒฐ
๋ทฐ๋ฅผ ๊ทธ๋ฆฌ๋ ์์ ์ main thread์์ ์ฒ๋ฆฌํ๋๋ก DispatchQueue.main.async ํด๋ก์ ๊ตฌ๋ฌธ์์ ๋ฃ์ด์ฃผ์๋ค.
์ํฉ
๊ณ ๊ฐ ์ถ๊ฐ๋ฒํผ์ ์ฌ๋ฌ๋ฒ ํด๋ฆญํ๊ณ ์ด๊ธฐํ๋ฅผ ๋๋ฅด๊ฒ ๋๋ฉด ํ์ด๋จธ๊ฐ ๋ฉ์ถ์ง ์์๋ค.
์ด์
ํ์ด๋จธ๊ฐ ์ถ๊ฐ๋ฒํผ ํด๋ฆญ์ ๊ณ์ ์ถ๊ฐ๋๋ฉด์ ์ถ๊ฐ๋ ํ์ด๋จธ๊ฐ ๋๋์ง ์๊ณ ๊ณ์ ์คํ๋๋ ๋ฏ ํ๋ค.ํด๊ฒฐ
์ด๊ธฐํ ๋ฒํผ์ ํด๋ฆญํ ๋, ๋๊ธฐ์ค์ธ ๊ณ ๊ฐ์ด ์์ ๋ ํ์ด๋จธ๋ฅผ ๋ฉ์ถ๋ฉด์ ํ์ด๋จธ์ nil์ ๋์ ํด์ฃผ์๊ณ , ํ์ด๋จธ๊ฐ ์๋์ค์๋ ํ์ด๋จธ๋ฅผ ์ถ๊ฐํ์ง ์๋๋ก ํ๋ ๋ก์ง์ ์ถ๊ฐํด์ฃผ๋ ํด๊ฒฐ๋์๋ค.
๋์์ฑ ํ๋ก๊ทธ๋๋ฐ์ ์ ์ฉํด๋ณด๋ค๊ฐ, ๋์์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์ ๊ทผํ๋ ์ผ์ด ๋ฐ์ํ๊ณ ์๋์ง ๋๋ฒ๊น ํด๋ณด๊ณ ์ถ์ด์ ์์๋ณด๋ค๊ฐ ์๊ฒ๋์๋ค.
- Xcode์์ ..
Product > scheme > editScheme > Run > Diagnostics > Thread Sanitizer
Thread Sanitizer
์ด๊ฑธ ์ฒดํฌํ๋ฉด ๋น๋๋ฅผ ๋๋ฆฌ๊ณ ๋์ thread safe ํ์ง ์์ ์ํฉ์ด ๋ฐ์ํ ์ ์๋ ๊ฐ๋ฅ์ฑ์ ์์ค์ฝ๋์์ ์ฒดํฌํด์ค๋ค.- ํ์ง๋ง ์ฌ์ฉํด๋ณด๋ ์๋ฒฝํ๊ฒ ์ฒดํฌํด์ฃผ๋ ๊ฑด ์๋ ๊ฒ ๊ฐ๋ค. ๊ทธ๋ฅ ๋์์ฃผ๋ ๊ธฐ๋ฅ์ด๋ผ๊ณ ์๊ฐํ๊ณ ์ฌ์ฉํด์ผํ ๊ฒ ๊ฐ๋ค.
Thread Safeํ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ๋ ค๋ฉด?
- ๊ณต์ ์์์ ์ฝ๊ณ ์ฐ๋ ์์
์ Thread safeํ๊ฒ Shemaphore๋ฅผ ์ฌ์ฉํด์ ํ๋์ thread๋ง ์ ๊ทผ ํ ์ ์๋๋ก ํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
- ํ์ง๋ง ์ด ๋ฐฉ๋ฒ์ ์๋ฒฝํ๊ฒ ์ ์ดํ๊ธฐ๋ ๋ฌด๋ฆฌ๊ฐ ์๋ค. ์คํ๋ ค ๊ณต์ ์์์ lock์ผ๋ก ์ฒ๋ฆฌํ๋ค๊ฐ ๊ต์ฐฉ ์ํฉ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ๋๋ค๊ณ ํ๋ค.
- Serial Queue sync๋ก ๋ณด๋ด์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ๋ ์๋ค.
- ๊ทธ๋ฌ๋ฉด ๋ค์ด์จ task์ ์์๊ฐ ์๊ธฐ๊ธฐ ๋๋ฌธ์ ๋ค์์ ์ค๋ ๋์์ ๋์์ ๊ฐ์ ์ ๊ทผํ์ง ๋ชปํ๊ฒ ํ๋ ์ํฉ์ด ๋๋ค.
- sync๋ก ์ฌ์ฉํ๋ ์ด์ ๋ Serial queue๋ก ๋ณด๋ธ ์์ ์ ๊ธฐ๋ค๋ฆผ์ผ๋ก์จ ๊ณต์ ์์์ ์ ๋๋ก ๋ ๊ฐ์ ์ป๊ธฐ ์ํจ์ด๋ค.
CFAbsoluteTime ํ์ ๋์ ์ Date ํ์ ์ ํ์ฉํ์ฌ ์ฐ์ฐ์๊ฐ ์ธก์ ํ๋๋ก ์์ ํ์๋ค. Core Foundation ๋ด์ฅํจ์๋ณด๋ค Foundation์ ์๋ ๊ธฐ๋ฅ์ ํ์ฉํ๋ ๊ฒ์ด ๋ ์ณ๋ค๊ณ ํ๋จ๋์๋ค.
- ์ฝ์ด ํ์ด๋ฐ์ด์ ์ ์๋ ๊ธฐ๋ฅ์ Foundation์์ ๋ํํ์ฌ ๊ตฌํ๋์ด์ ธ์๋ค.
- ๋ณดํต ์ฑ๊ฐ๋ฐ์ ํ ๋์๋ Foundation์ ๊ธฐ๋ฅ ์์ด ๊ฐ๋ฐํ๊ธฐ์๋ ์ด๋ ค์์ด ์๊ธฐ ๋๋ฌธ์, Core Foundation์ ๋ด์ฅ๋์ด์๋ ๊ธฐ๋ฅ๋ณด๋ค๋ Foundation์ ๋ด์ฅ๋์ด์๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒ์ ์ ํธํ๋ ํธ์ด๋ค.
์ํฉ
ํ๋ก์ ํธ์์ ยBank ํ์
์ย๊ตฌ์กฐ์ฒด
์ด๊ณ ,numberOfCustomers ํ๋กํผํฐ
๋ฅผ ๊ฐ์ง๊ณ ์๋ค. ์ํ์์ด ์ผ์ ํ ๋, ์ฒ๋ฆฌํ ๊ณ ๊ฐ์ ์๋ฅผยDispatch.global().async
ย ํด๋ก์ ๋ด์์ ์นด์ดํธ(numberOfCustomers
) ํด์ฃผ๋๋ก ํ๋ ค๊ณ ํ์ผ๋ ์๋์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ์๋ค.์ด์
Escaping closure
์ ๊ฒฝ์ฐ ๊ตฌ์กฐ์ฒด์์๋ ์บก์ณ๊ฐ ๋ถ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์, ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ค๊ณ ํ๋ฉด ์๋์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
// ๊ฐ๋จํ ์ฝ๋ ์์
struct SomeStruct {
var num = 0
private mutating func test() {
let closure = { // Escaping closure captures mutating 'self' parameter
self.num += 1
}
closure()
}
}
-
Escaping closure
์ ๊ฒฝ์ฐ ๊ตฌ์กฐ์ฒด์์๋ ์บก์ณ๊ฐ ๋ถ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์, ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ค๊ณ ํ๋ฉด ์์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.class์ ๊ฐ์ ์ฐธ์กฐ ํ์ ์ด ์๋ Struct, enum๊ณผ ๊ฐ์ ๊ฐํ์ ์์๋ mutating reference์ ์บก์ณ๋ฅผ ํ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ self ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅ ํ๋ค.
-
ํด๊ฒฐ
Bank ํ์
์ํด๋์ค
๋ก ๋ฐ๊ฟ์ฃผ์๋ค.
- cancel ๋ฉ์๋๋ฅผ ํธ์ถํ๋๋ผ๋ ์์ ์ด ์์ ์ค์ด๋ผ๋ฉด ์ค์ง์ํฌ ์ ์๋ค.
- ์ฐํํ๋ ๋ฐฉ๋ฒ์ด ์กด์ฌํ์ง๋ง GCD๊ฐ ์์ ์ ์ทจ์ํ๊ฑฐ๋ ํ๋ ๊ฒ์ ํ ์๋ ์๋ค.
- Operation Queue๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ์ค์ธ ์์ ์ ์ค์ง ํ ์ ์๋ค. [์ฐธ๊ณ ๋งํฌ]
[ํ์ต ๊ธฐ๋ก ํ์ ]
- STEP 1 : ํ ํ์ ๊ตฌํ
- STEP 2 : ํ์ ๊ตฌํ ๋ฐ ์ฝ์์ฑ ๊ตฌํ
- STEP 3 : ๋ค์ค ์ฒ๋ฆฌ
- STEP 4 : UI ๊ตฌํ
์ํ์ ๋์ฐฉํ ๊ณ ๊ฐ์ด ์์๋ก ๋๊ธฐํ ๋๊ธฐ์ด ํ์ ์ ๊ตฌํํฉ๋๋ค.
- ์๋ฐฉํฅ LinkedList vs ๋จ๋ฐฉํฅ LinkedList
- ์๋ก ์ด์ผ๊ธฐ๋ฅผ ๋๋๋ฉด์ ๋จ๋ฐฉํฅ์ผ๋ก๋ ์ถฉ๋ถํ ํ๋ฅผ ๊ตฌํํ ์ ์๋ค๋ ์๊ฐ์ด ๋ฆ.
- ๋ ธ๋๋ฅผ ํด๋์ค๋ก ๋ง๋ค๊ณ ์ฐธ์กฐ๋ฅผ ํ์ฉํ์ฌ ๋ชจ๋ ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํ ์ ์๊ฒ ๊ตฌํํ์๋ค.
- ํ
์คํธ๋ฅผ ์ํ Mock ํ์
์์ฑ
- ํ
์คํธ ์งํ์
Node
, LinkedList์head
,tail
์ ์์๋ฅผ ์ ๊ทผํ์ฌ ํ ์คํธ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ๋ค. - ํด๋น ์์๋ค์ ์ธ๋ถ์์ ์ ๊ทผํ๋ฉด ์๋๋ค๋ ํ๋จ์ด ๋ค์ด์ ๋ฐ๋ก MockLinkedList๋ฅผ ๋ง๋ค์ด์ฃผ์ด ์ํํ ํ ์คํธ๋ฅผ ํ ์ ์๋๋ก ๊ตฌํํ์๋ค.
- ํ
์คํธ ์งํ์
- attribute๋ฅผ ํ์ฉ
- ๋ฐํ ๊ฐ์ ์ ์๋ฏธํ๊ฒ ์ฌ์ฉํ์ง ์๊ณ ๋ฒ๋ ค๋๋๋ remove ๊ด๋ จ ๋ฉ์๋์ ์์ฑ
@discardableResult
์ ๋ถ์ฌํ์ฌ ์ปดํ์ผ๋ฌ ๊ฒฝ๊ณ ๊ฐ ๋ฐ์ํ์ง ์๋๋ก ํ์๋ค.
- ๋ฐํ ๊ฐ์ ์ ์๋ฏธํ๊ฒ ์ฌ์ฉํ์ง ์๊ณ ๋ฒ๋ ค๋๋๋ remove ๊ด๋ จ ๋ฉ์๋์ ์์ฑ
-
if vs guard
// 1. if ๊ตฌ๋ฌธ func removeFirst() -> Element? { if isEmpty { return nil } let result = head?.value head = head?.next return result }
// 2. guard ๊ตฌ๋ฌธ func removeFirst() -> Element? { guard isEmpty == false else { return nil } let result = head?.value head = head?.next return result }
-
if๋ฌธ์ผ๋ก ๊ตฌํ ์ ์กฐ๊ฑด๋ฌธ์ด ๊น๋ํ๊ฒ isEmpty๋ก ๋ง์๋จ์ด์ง๊ธฐ ๋๋ฌธ์ ์ฝ๋์ ๊ฐ๋ ์ฑ์ด ์ข๋ค๊ณ ์๊ฐํ๋ค.
- guard๋ฌธ์ด๋ if๋ฌธ์ด๋ ๋ฉ์๋ ์์๋ถ๋ฌธ์์ return์ ํ์ฉํ์ฌ ๋ฉ์๋๋ฅผ ํ์ถํ๋๊ฑด ๋์ผํ๊ธฐ ๋๋ฌธ์ ์ด๋ค ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ ์๊ด์๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
-
guard๋ฌธ
- guard ๊ตฌ๋ฌธ์ ๊ธฐ๋ฅ์ ์ฝ๋ ๋ธ๋ญ์ ๋น ๋ฅธ ์ข ๋ฃ ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์์ด ํจ์ ์ ์ฒด ํ๋ฆ์ ๋ดค์ ๋ guard ๊ตฌ๋ฌธ์ด ๊ฐ๋ ์ฑ์ด ๋ ์ข๋ค๊ณ ์๊ฐํ๋ค. guard๋ฌธ๋ง ๋ณด๋๋ผ๋ ํจ์๋ฅผ ํ์ถํ๋ ๊ตฌ๋ฌธ์ด๋ผ๊ณ ์ฝํ์ง๊ธฐ ๋๋ฌธ์ด๋ค.
- if๋ฌธ ์ฒ๋ผ ์กฐ๊ฑด๋ฌธ์ด ๊น๋ํ์ง๋ ๋ชปํ๊ฒ ๋์์ง๋ง, ํจ์๋ฅผ ํ์ถํ๋ ๋ถ๋ถ์ guard๋ฌธ์ผ๋ก ์ผ๊ด์ฑ ์๊ฒ ๊ตฌ์ฑํ ์ ์๊ฒ ๋์๋ค.
-
์ํฉ
append๋ฅผ ํ ๋ ์ฐ๊ฒฐ๋ ๋ฆฌ์คํธ๋ค์ ๊ฐ์ฅ ๋ง์ง๋ง ๋ถ๋ถ์ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ค์ผํ๋๋ฐ, ์์๋ฅผ ํ์ํ๊ธฐ ์ํด ๋ฐ๋ณต์ ์ผ๋ก ํฌ์ธํฐ๋ฅผ ์ถ์ ํ๋ ์์ ์ ํด์ผํ๋ ์ ์ ๊น๋ํ๊ฒ ํด๊ฒฐํด๋ณด๊ณ ์ถ์๋ค. -
์ด์
Queue๋ฅผ ์ํ LinkedList์ธ ์ ๋ ์๊ณ , ๋ ๊ฐ ์์๋ฅผ ํ์ํ๊ธฐ ์ํด ๋ฐ๋ณต์ ์ผ๋ก ํฌ์ธํฐ๋ฅผ ์ถ์ ํ๊ฒ ๋๋ค๋ฉด ์๊ฐ๋ณต์ก๋๊ฐ O(n)์ด๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ ์ ๊ทผ ๋ฐฉ์์ด ๋งค์ฐ ๋นํจ์จ์ ์ธ ์ ์ ํด๊ฒฐํ๊ณ ์ถ์๋ค. -
ํด๊ฒฐ
ํด๋์ค์ ์ฐธ์กฐ๋ฅผ ํ์ฉํ์ฌ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ฅผ ์ฐ๊ฒฐํ๋๋ก ๊ตฌํํ์๋ค.func append(_ value: Element) { let newNode = Node(value: value) if isEmpty { head = newNode tail = newNode } else { tail?.next = newNode tail = newNode } }
- Linked-list ์๋ฃ๊ตฌ์กฐ์ ์ดํด
- Queue ์๋ฃ๊ตฌ์กฐ์ ์ดํด
- ํ ์คํธ ์ฝ๋ ๋ด๋ถ์์ overrideํ ๋ฉ์๋ ๋ด๋ถ์ super ๋ฉ์๋๋ฅผ ํธ์ถํ๋๋ก ์์
- LinkedList๋ฅผ ํ
์คํธํ๊ธฐ ์ํ Mock ๊ฐ์ฒด ์ญ์
- LinkedList ํ์ ์์ ์ ๊ทผํ ์ ์๋ ํ๋กํผํฐ, ๋ฉ์๋๋ฅผ ํ์ฉํ์ฌ ํ ์คํธ๋ฅผ ํ๋๋ก ๋ฆฌํฉํ ๋ง
- ํ ์คํธ ๋ฉ์๋ ์ด๋ฆ์ ์ ์ ํ๊ฒ ์์
- QueueTests์์ย
setUp()
ย ๋ฉ์๋๋ฅผ ํ์ฉํ๋๋ก ์์
์ํ๊ณผ ๊ณ ๊ฐ์ ํ์ ์ ๊ตฌํํ๊ณ ์ฝ์์ฑ์ ๊ตฌํํ๋ค.
- ๊ตฌํํ ํ์
๋ค ๊ฐ๊ฐ ํ๋์ ์ฑ
์๋ง ๊ฐ๋๋ก ๊ณ ๋ฏผํด๋ณด์๋ค.
์ถ๋ ฅ๋ฌธ
๊น์ง๋ ์ํ์, ์ํ์ด ํด์ผํ ์ผ์ด ์๋๋ผ๊ณ ํ๋จ๋์๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ์ถ๋ ฅ๋ง ํ๋ ํ์ (ViewController)์ ๋ง๋ค์ดDelegate ํจํด
์ ํ์ฉํ์ฌ ๋ถ๋ฆฌํด์ฃผ์๋ค.- ์๊ตฌ์ฌํญ ์์์ ๋ง์ถฐ ์ถ๋ ฅ์ ํด์ฃผ๊ธฐ ์ํด NumberFormatter๋ฅผ ํ์ฉํ๋ ๋ถ๋ถ์ด ํ์ํ๋๋ฐ, ์ด ๋ถ๋ถ์ ์ํ์์ ์ง์ ์ฒ๋ฆฌํ๋ ๊ฑด ์ ํฉํ์ง ์๋ค๋ ์๊ฐ์ด ๋ค์๋ค. ๋ฐ๋ผ์ ๋ฐ๋ก ํ์ ์ผ๋ก ๋นผ์ฃผ์ด static ๋ฉ์๋๋ก ๊ตฌํํด์ฃผ์๋ค.
- ์ํ์ฐธ์กฐ
Delegate ํจํด
์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ชจ๋ธ ํ์
๋ณ๋กviewController
๋ฅผ ๋ง๋ค์ด์ฃผ์๋ค.๋ชจ๋ธ ํ์
์delegate
๋กviewController
๋ฅผ ๊ฐ์ง๊ณ ์๊ณviewController
์ ์๊ธฐ ์์ ์delegate
๋ก ๋๊ฒจ์ฃผ๊ธฐ ์ํด๋ชจ๋ธ ํ์
์ ๊ฐ์ง๊ณ ์์ด์ํ ์ฐธ์กฐ
๊ฐ ๋ฐ์ํ๋ค.๋ชจ๋ธ ํ์
์delegate
๋ฅผ weak ํค์๋(์ฝํ ์ฐธ์กฐ)๋ฅผ ์ฌ์ฉํด์ํ์ฐธ์กฐ
๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
- Delegate ํจํด ์์ฑ์ ๋ค์ด๋ฐ์ ๋ํ ๊ณ ๋ฏผ์ ํด๋ณด์๋ค.
-
๊ตฌ๊ธ์ Swift Style Guide๋ฅผ ์ฐธ๊ณ ํ์ฌ ๋ค์ด๋ฐ์ ํ์๋ค.
The term โdelegateโs source objectโ refers to the object that invokes methods on the delegate. For example, aย
UITableView
ย is the source object that invokes methods on theยUITableViewDelegate
ย that is set as the viewโsยdelegate
ย property.
-
- Delegate ํจํด ๊ตฌํ์ ์ํด ๊ธฐ์กด ๋ชจ๋ธ ํ์
์ ๋ณ๊ฒฝ์ฌํญ์ด ์๊ฒผ๋๋ฐ ์ด๊ฒ ์ฌ๋ฐ๋ฅธ ๊ฒ์ธ์ง ์ ํ๋จ์ด ์์ง ์๋๋ค.
- ๊ธฐ์กด ๊ตฌ์กฐ์ฒด์๋ ํ์
๋ค์
class
๋ก ๋ณ๊ฒฝํด์ค ๋ถ๋ถ์ด ์ถํ retain count ์ถ์ ๋น์ฉ์ด ๋ฐ์ํ ๊ฒ์ด๋ผ๋ ์ฐ๋ ค๊ฐ ์๊ฒผ๋ค.
- ๊ธฐ์กด ๊ตฌ์กฐ์ฒด์๋ ํ์
๋ค์
- Delegate ํจํด ์ฌ์ฉ์ ๊ฐํ ์ํ ์ฐธ์กฐ ๋ฐ์์ ์๋ฐฉํ๊ธฐ ์ํด weak ํค์๋๋ฅผ ์ฌ์ฉํด์ฃผ์๋๋ ์์ผ๋์นด๋ ํจํด์ผ๋ก ์์ฑํ ์ธ์คํด์ค๊ฐ ์์ฑ๊ณผ ๋์์ ํด์ ๊ฐ ๋์๋ค.
- ์ธ์คํด์ค๋ฅผ ์์ฑํ ํ ์ฐธ์กฐ๋ฅผ ํ์ง ์๋๋ค๋ฉด weak ํค์๋ ๋ณด๋ค๋ ์์ผ๋์นด๋ ํจํด์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ํฉํ ๊ฒ์ผ๊น?
- ๋จ์ผ ์ฑ ์ ์์น์ ๋ง๊ฒ ์ญํ ์ Delegate ํจํด์ ํ์ฉํ์ฌ ๋ถ๋ฆฌํด์ฃผ์๋ค. ํ์ง๋ง ํ์ฅ์ฑ์ ๊ณ ๋ คํ์ ๋ ์ด๊ฒ ์ฌ๋ฐ๋ฅด๊ฒ ์ค๊ณํ ๊ฒ์ด ๋ง๋์ง ๋๋ฌด ์ค๋ฒ ์์ง๋ฆฌ์ด๋ํ ๋ถ๋ถ์ ์๋์ง ํ๋จ์ด ์ด๋ ต๋ค.
-
์ํฉ
๊ธฐ์กด์ ์์ผ๋์นด๋ ํจํด์ผ๋ก ์ธ์คํด์ค ์์ฑํ ํ์ ์ด Delegate๋ฅผ ์ฑํํ๊ณ ์๋ ํํ์๋ค. ์ดํ ์ํ์ฐธ์กฐ ๋ฌธ์ ๊ฐ ์ฐ๋ ค๋์ด ๊ฐ ํ์ ๋ค๋ง๋ค delegate ํ๋กํผํฐ์ weak ํค์๋๋ฅผ ๋ถ์ฌ์ฃผ์๋ค.final class Bank { private let bankClerk: BankClerk private var customerQueue = Queue<Customer>() weak var delegate: BankDelegate? ... } func run() { let bankClerk = BankClerk() let bank = Bank(bankClerk: bankClerk) let bankManager = BankManager(bank: bank) let _ = BankClerkViewController(bankClerk: bankClerk) let _ = BankViewController(bank: bank) // ... }
-
์ด์
๊ทธ๋ฐ๋ฐ weakํค์๋๋ฅผ ๋ถ์ฌ์ฃผ๋ ํด๋น ํ์ ์์ ์ถ๋ ฅํด์ฃผ์๋ ๋ฉ์๋๊ฐ ์คํ๋์ง ์์๋ค. init๊ณผ deinit์ ํตํด ๋๋ฒ๊น ์ ํด๋ณด๋ ์์ผ๋์นด๋ ํจํด์ผ๋ก ์์ฑํ ์ธ์คํด์ค๊ฐ ์์ฑ๊ณผ ๋์์ ํด์ ๋๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค.์์ผ๋์นด๋ ํจํด
์ ๊ฐ์ ํด์ฒดํ๊ฑฐ๋ ๋ฌด์ํ๋ ํจํด์ค ํ๋์ด๋ฏ๋กweak ํค์๋
๊ฐ ์ถ๊ฐ๋จ๊ณผ ๋์์ retain count๊ฐ ์ฌ๋ผ๊ฐ์ง ์๊ธฐ ๋๋ฌธ์ ์์ฑ๊ณผ ๋์์ ํด์ ๋๋ ๊ฒ์ด์๋ค. -
ํด๊ฒฐ
์ฌ์ฉํ์ง ์๋ viewController(์ํ์, ์ํ)๋ฅผ ์์์ ๋ด์ผ๋ฉด xcode์์ ๊ณ ๋ฉ์ธ์ง๊ฐ ์ถ๋ ฅ๋๋ค. ์์ผ๋ ์นด๋ ํจํด์ ์ฌ์ฉํด์ ์ํ์ฐธ์กฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๊ณ ํ๋จ๋์ด weak ํค์๋๋ฅผ ์ ๊ฑฐํ๊ณ ์์ผ๋์นด๋ ํจํด์ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.final class Bank { private let bankClerk: BankClerk private var customerQueue = Queue<Customer>() var delegate: BankDelegate? ... } func run() { let bankClerk = BankClerk() let bank = Bank(bankClerk: bankClerk) let bankManager = BankManager(bank: bank) let _ = BankClerkViewController(bankClerk: bankClerk) let _ = BankViewController(bank: bank) ... }
- ํ์ ์ถ์ํ ๋ฐ ์ผ๋ฐํ
- Delegate ํจํด ํ์ฉ
- SOLID์ ๋จ์ผ ์ฑ ์ ์์น
- ์์ผ๋์นด๋ ํจํด๊ณผ weak ํค์๋์ ๊ด๊ณ
- ๊ฐ๋ฐํ ๋ ์ผ๋ํด์ผํ ๊ฒ
- ๊ธฐ๋ฅ์ ์ ํํ ๋์๋ ๋น์ทํ ๊ธฐ๋ฅ์ ๋ฌด์์ด ์๋์ง ํ์ํ๊ธฐ.
- ์ ํํ ๊ธฐ๋ฅ์ด ๋ค๋ฅธ ๊ธฐ๋ฅ๋ณด๋ค ๋์์ ์ ๋ญ๊ฐ ์๋์ง ์๊ฐํด๋ณด๊ธฐ
- ๊ธฐ๋ฅ์ ์ฐพ์ ์ฌ์ฉํ ๋ ์ ํํ ์ด์ ๋ฅผ ์๊ฐํด๋ณด๊ธฐ
CFAbsoluteTime
ํ์ ๋์ ์ Date ํ์ ์ ํ์ฉํ์ฌ ์ฐ์ฐ์๊ฐ ์ธก์ ํ๋๋ก ์์ Core Foundation
๋ด์ฅํจ์๋ณด๋คFoundation
์ ์๋ ๊ธฐ๋ฅ์ ํ์ฉํ๋ ค๋ ์๋- Core Foundation vs Foundation
- ์ฝ์ด ํ์ด๋ฐ์ด์ ์ ์๋ ๊ธฐ๋ฅ์ Foundation์์ ๋ํํ์ฌ ๊ตฌํ๋์ด์ ธ์๋ค.
- ๋ณดํต ์ฑ๊ฐ๋ฐ์ ํ ๋์๋ Foundation์ ๊ธฐ๋ฅ ์์ด ๊ฐ๋ฐํ๊ธฐ์๋ ์ด๋ ค์์ด ์๊ธฐ ๋๋ฌธ์, Core Foundation์ ๋ด์ฅ๋์ด์๋ ๊ธฐ๋ฅ๋ณด๋ค๋ Foundation์ ๋ด์ฅ๋์ด์๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒ์ ์ ํธํ๋ ํธ์ด๋ค.
- Core Foundation vs Foundation
Delegate
ํจํด๊ณผViewController
ํ์ ๋ชจ๋ ์ญ์ - ๋ค์ STEP๋ฅผ ์ง๋ ์ง์ํ์ง ๋ง๊ณ ํ์ฌ STEP์ ์ถฉ์คํ์.
- ์๋ํ๊ณ ์คํจํ๊ณ ๋์๊ฐ๋ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ฉฐ ๊ฐ์ ํด๋๊ฐ๋ ๋ฐฉํฅ์ผ๋ก ์งํํ์.
Message
์ ๋ค์ด๋ฐ์ ๋ช ํํ๊ฒ ๊ฐ์- Menu์ ํ๋กํผํฐ๋ฅผ ํ์ฉํ์ฌ
menuList
์ ํ๋กํผํฐ ๋ด๋ถ ํ๋์ฝ๋ฉ์ ๊ฐ์
- Menu์ ํ๋กํผํฐ๋ฅผ ํ์ฉํ์ฌ
NumberFormatter
๋ฅผ ํ์ฉํ์๋ ๋ถ๋ถ์ Double์ ํ์ฅํ์ฌ ๊ฐ์String(format:)
์ ํ์ฉํ์ฌ description์ ๋ฐํํ๋๋ก ๊ตฌ์ฑ
์ํ์ ์ฌ๋ฌ๋ช ์ด ์ ๋ฌด๋ฅผ ์ฒ๋ฆฌํ ์ ์๋๋ก ๊ตฌํํฉ๋๋ค.
- ์ฌ๋ฌ ์ํ์์ด ๋์์ ๊ณ ๊ฐ์ ์ผ์ ์ฒ๋ฆฌํ๋ ๋ก์ง์ ๊ณ ๋ฏผํ๋ค.
global() ํ
์ ์ํ์์ ์ ๋งํผtask
๋ฅผ ๋ง๋ค๊ณ ๊ฐ๊ฐ์task
์์ ๊ณ ๊ฐ์dequeue
ํด์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์- ํ๋์ while ๊ตฌ๋ฌธ์์ dequeue ํด์ฃผ๊ณ ๊ณ ๊ฐ์ ์ํ ์
๋ฌด์ ๋ฐ๋ผ ์๊ธ ๊ณ ๊ฐ์
DispatchQueue.global()
์ ์ธ๋งํฌ์ด๋ฅผ ์ด์ฉํด์ํ์ ์ == ์ ๊ทผ ๊ฐ๋ฅํ ์ค๋ ๋ ์
๋ง๋๋ ๋ฐฉ์DispatchSemaphore
์value
๋ฅผ 1์ด ์๋ 2๋ 3์ผ๋ก ์ค ๊ฒฝ์ฐRace Condition
์ด ๋ฐ์ํ ์ ์๋ค๋ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ํด๋น ๋ฐฉ๋ฒ์ ์ ์ ํ์ง ๋ชปํ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.Banker
๊ฐ ๊ฐ์ง๊ณ ์๋work()
๋ฉ์๋๋ ํ์ฌ ๊ณต์ ์์์ ์ ๊ทผํ๊ณ ์์ง ์์ง๋ง, ์ถํ ํด๋น ๋ฉ์๋๊ฐ ๊ณต์ ์์์ ์ ๊ทผํ์ง ์์๊ฑฐ๋ผ๋ ๋ณด์ฅ์ด ์๋ค๋ผ๋ ์๊ฐ์ด ๋ค์๋ค.
- ์ถํ ์ํ์์ ์๊ฐ ๋ณ๊ฒฝ๋๋๋ผ๋ ๋์ํ ์ ์๋๋ก ์ํ์ ์ ๋งํผ
DispatchQueue.global()
์task
๋ฅผ ๋ง๋๋1๋ฒ ๋ฐฉ์
์ผ๋ก ๊ตฌํํ๋ค.์ํ์ ์
==DispatchQueue์ ์
- ํ๋ก์ ํธ ์คํ์์์๋ ๋๊ธฐ๋ฒํธ ์์ผ๋ก ์คํ๋๊ณ ์์ง ์์ ์ ์ ๋ฐ๊ฒฌํ๊ฒ ๋์๋ค.
- ์ด ๋ถ๋ถ์ ์ผ๊ณฐ์๊ฒ ์ง๋ฌธํด๋ณด์๊ณ , ์์ฐจ์ ์ผ๋ก ์ ๋ฌด๋ฅผ ํ ์ ์๋๋ก ๊ตฌํํด๋ณด๋ผ๊ณ ํ์ ์ ๊ณ ๋ฏผํ๊ฒ ๋์๋ค.
- ๊ณ ๋ฏผํ ๊ฒฐ๊ณผ, ๋๊ธฐ๋ฒํธ ์์ผ๋ก
์ฐจ๋ก๋๋ก ์ ๋ฌด๊ฐ ์ฒ๋ฆฌ๋์ผ ๋๋ค๊ณ ์๊ฐ
ํ๊ธฐ ๋๋ฌธ์ ๋์ถ์ ๋ฌด์ ์๊ธ์ ๋ฌด๋ฅผ ๋ณด๋ ๊ณ ๊ฐ๋ค์๋๊ฐ์ ๊ณ ๊ฐํ
๋ก ๋๋์ด ๊ด๋ฆฌํ๋๋ก ๊ตฌํํ๋ค.
Banking
์ ๊ฒฝ์ฐrawValue
๋ฅผString
์ผ๋ก ๊ฐ์ง๊ณ ์๋ ํํ์ธ๋ฐ, ์ด ๋ถ๋ถ์ ์ํ์์ด ์ด๋ค ์ ๋ฌด๋ฅผ ์ฒ๋ฆฌํ๋์ง ์๋ ค์ฃผ๊ธฐ ์ํด ์ฌ์ฉํ๋ ค๋ ์๋๋ก ๊ตฌํํ๊ฒ ๋์๋ค.ํ๋กํ ์ฝ ์ฑํ
๊ณผ์ฐ์ฐํ๋กํผํฐ
์ค์ ์ด๋ค ๋ฐฉ์์ผ๋ก ํ์ฉํ ์ง ๊ณ ๋ฏผํด๋ณด์๋ค.CustomStringConvertible
์ ๊ฒฝ์ฐ ์ธ์คํด์ค๋ฅผ ์ํ๋ ํํ์ ๋ฌธ์์ด๋ก ๋ฐํํ๊ณ ์ถ์ ๋ ์ฑํํ์ฌ ์ฌ์ฉํ๋ ํ๋กํ ์ฝ๋ก ์ฐ๋ฆฌ๊ฐ ํ์ฉํ๊ณ ์ ํ์๋ ๋ถ๋ถ์ด๋์ ์ ํฉํ์ง ์๋ค๋ ์๊ฐ์ด ๋ค์๋ค.- ๋ฐ๋ผ์ description์ด๋ผ๋ ์ฐ์ฐํ๋กํผํฐ๋ฅผ ํ์ฉํ์ฌ rawValue๋ฅผ ๋ฐํํ๋๋ก ๊ตฌํํด์ฃผ์๋ค.
- ์ฒ์์ while๋ฌธ ์์
DispatchQueue
๋ฅผ ํธ์ถํ๊ณDispatchSemaphore
์value
๋ฅผ3
์ผ๋ก ์ฃผ์ด 3๊ฐ์ ์ค๋ ๋๋ง ์ ๊ทผํ ์ ์๋๋ก ์ค์ ํด์ฃผ์๋ค. ๊ทธ๋ฐ๋ฐ ์ฌ๋ฌ๋ฒ ๋๋ ค๋ Race Condition์ด ๋ฐ์ํ์ง ์์๋ค. - ์ํ์์ ์(
DispatchSemaphore value
)์ ๊ณ ๊ฐ์ ์๋ฅผ ๋๋ ค์ฃผ๊ณ ํ ์คํธ๋ฅผ ํด๋ณด์๋๋ Race Condition์ด ๋ฐ์ํ์๋ค.- ํ
์คํธ๋ฅผ ํ๋ฉด์ ์๊ฒ๋ ๋ถ๋ถ์
Banker
์work()
๋ฉ์๋๊ฐ ๊ณต์ ์์์ ์ ๊ทผํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ์ง ์์๋ ๊ฒ์ด์๋ค. ํ๋กํผํฐcount
๋ฅผ ๋ง๋ค์ด์ฃผ๊ณ ๊ทธ count์ ์ ๊ทผํ๋๋ก ๊ตฌํํด์ฃผ์๋๋ Race Condition์ด ๋ฐ์ํ๋ ์ํฉ์ ํ์ธํ ์ ์์๋ค.
- ํ
์คํธ๋ฅผ ํ๋ฉด์ ์๊ฒ๋ ๋ถ๋ถ์
- ์ด ์๋ฌธ์ ์ ํ๋ฉด์ ๊ฒฐ๊ตญ
Semaphore์ value๋ฅผ ์ฌ๋ฌ๊ฐ ์ฃผ๋ ๊ฒ
์ ๊ณต์ ์์์ ์ ๊ทผํ ์ ์๋ ์ํฉ์ด๋ผ๋ฉดThread-safeํ์ง ์์ ๊ฒ
์ด๊ณ , ๋ฐ๋ผ์ ์ํ์์ ์๋ฅผDispatchSemaphore
์value
์ ๋ง์ถฐ ์ค๊ณ๋ฅผ ํ๋ ๊ฒ์ ์ ์ ํ์ง ๋ชปํ๋ค๋ ๊ฒฐ๋ก ์ด ๋ฌ๋ค.
์ํฉ
ํ๋ก์ ํธ์์ ยBank ํ์
์ย๊ตฌ์กฐ์ฒด
์ด๊ณ ,numberOfCustomers ํ๋กํผํฐ
๋ฅผ ๊ฐ์ง๊ณ ์๋ค. ์ํ์์ด ์ผ์ ํ ๋, ์ฒ๋ฆฌํ ๊ณ ๊ฐ์ ์๋ฅผยDispatch.global().async
ย ํด๋ก์ ๋ด์์ ์นด์ดํธ(numberOfCustomers
) ํด์ฃผ๋๋ก ํ๋ ค๊ณ ํ์ผ๋ ์์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ์๋ค.์ด์
Escaping closure
์ ๊ฒฝ์ฐ ๊ตฌ์กฐ์ฒด์์๋ ์บก์ณ๊ฐ ๋ถ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์, ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ค๊ณ ํ๋ฉด ์์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
// ๊ฐ๋จํ ์ฝ๋ ์์
struct SomeStruct {
var num = 0
private mutating func test() {
let closure = { // Escaping closure captures mutating 'self' parameter
self.num += 1
}
closure()
}
}
-
Escaping closure
์ ๊ฒฝ์ฐ ๊ตฌ์กฐ์ฒด์์๋ ์บก์ณ๊ฐ ๋ถ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์, ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ค๊ณ ํ๋ฉด ์์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.class์ ๊ฐ์ ์ฐธ์กฐ ํ์ ์ด ์๋ Struct, enum๊ณผ ๊ฐ์ ๊ฐํ์ ์์๋ mutating reference์ ์บก์ณ๋ฅผ ํ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ self ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅ ํ๋ค.
-
ํด๊ฒฐ
Bank ํ์
์ํด๋์ค
๋ก ๋ฐ๊ฟ์ฃผ์๋ค.
- ๋๊ธฐ(Synchronous)์ ๋น๋๊ธฐ(Asynchronous)์ ์ดํด
- ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ ๊ฐ๋ ์ ์ดํด
- ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ์ ์ํ ๊ธฐ๋ฐ๊ธฐ์ (GCD, Operation) ๋ฑ์ ์ดํด
- ์ค๋ ๋(Thread) ๊ฐ๋ ์ ๋ํ ์ดํด
- GCD๋ฅผ ํ์ฉํ ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ ๊ตฌํ
- ๋๊ธฐ(Synchronous)์ ๋น๋๊ธฐ(Asynchronous) ๋์์ ๊ตฌํ ๋ฐ ์ ์ฉ
- Bank ํ์
๋ฆฌํฉํ ๋ง
- ์ํ์ ์๋ฅผ ๋ํ๋ด๋ ํ๋กํผํฐ๋ช number๋ฅผ count๋ก ์์
- Bankํ์ ์ class๊ฐ ์๋ struct๋ก ์์
workBanker()
ย ๋ฉ์๋ ๋ด๋ถ์ while๋ฌธ์ while let์ผ๋ก ์์
- Banker ํ์
์ย
workSpeed()
ย ๋ฉ์๋๋ฅผ ์ ๊ฑฐ - LinketList์ย
removeFirst()
ย ๋ฉ์๋ ๋ด๋ถ๋ฅผ Thread-Safeํ๊ฒ ๊ฐ์- Thread Safe
- ๊ธฐ์กด ๋ก์ง์ ์ํ์ ์๋งํผ global() ํ์ Task๋ฅผ ๋ง๋๋ ๋ฐฉ์์ด์ฌ์ ํ๋์ ๊ณ ๊ฐ ํ์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์ ๊ทผํดย
Race Condition
์ด ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ์์. - ์ฌ๋ฌ ์ค๋ ๋๊ฐ ํ๋์ ๊ณ ๊ฐ ํ์ ์ ๊ทผํด๋ LinkedList์์ ์ฒซ ๋ฒ์งธ ์์๋ฅผ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ ํ๋์ ์ค๋ ๋์์๋ง ์ ๊ทผํ ์ ์๋๋กย
SerialQueue.sync
๋ฅผ ํ์ฉํ์ฌยRace Condition
์ ํด๊ฒฐ
- ๊ธฐ์กด ๋ก์ง์ ์ํ์ ์๋งํผ global() ํ์ Task๋ฅผ ๋ง๋๋ ๋ฐฉ์์ด์ฌ์ ํ๋์ ๊ณ ๊ฐ ํ์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์ ๊ทผํดย
- Thread Safe
์ฝ์์ฑ์ UI์ฑ์ผ๋ก ๊ตฌํํฉ๋๋ค.
- ํ๋ฉด ์ ์ฒด๋ฅผ ์คํ๋ทฐ๋ก ๊ตฌ์ฑํ ์ ์๋๋ก ๊ณ ๋ฏผํด๋ณด์๋ค.
- ๋์ผํ ๊ตฌ์ฑ์ ๊ฐ์ง๊ณ ์๋ ๋ทฐ๋ฅผ Custom View๋ก ๋ถ๋ฆฌํ ์ ์๋๋ก ๊ณ ๋ฏผํด๋ณด์๋ค.
- ๋์ผํ ์์๊ฐ ์๋ ๋ทฐ๋ฅผ ์ปค์คํ ํ์ฌ ์ฌ์ฌ์ฉํ ์ ์๋๋ก ๊ตฌํ
- ๋ทฐ๋ฅผ ๊ทธ๋ฆด ๋ main Thread์์ ๋ฐ๋ก ์ฒ๋ฆฌํ ์ ์๋ ๋ฐฉ๋ฒ์ ๊ณ ๋ฏผํด๋ณด์๋ค.
- delegate๋ฅผ ํ์ฉํ์ฌ ViewController๊ฐ ๋ทฐ๋ฅผ ๊ทธ๋ฆฌ๋ ์์ ์ DispatchQueue.main.async๋ฅผ ํ์ฉํ์ฌ ๋น๋๊ธฐ์ ์ผ๋ก ๋ทฐ๋ฅผ ๊ทธ๋ฆด ์ ์๋๋ก ๊ตฌํ
- ๊ฐ์ข
์์ธ์ฌํญ์ ๋ํด ๋์ฒํ ์ ์๋๋ก ์ด๋ค ๋ก์ง์ ์ถ๊ฐํด์ผํ๋์ง ๊ณ ๋ฏผํด๋ณด์๋ค.
- ๊ณ ๊ฐ 10๋ช ์ถ๊ฐ ๋ฒํผ์ ํด๋ฆญ์ ์ํ์ด ์ผ์ ํ๊ณ ์๋ค๋ฉด ๊ณ ๊ฐ๋ง ์ถ๊ฐํ ์ ์๋๋ก ๋ก์ง ์ถ๊ฐ
- ๊ณ ๊ฐ์ ์ถ๊ฐํ ๋ ๋จผ์ ์ผ์ด ๋๋์ ์ฌ๋ผ์ง Thread(์ํ์)๊ฐ ์๋ ๊ฒฝ์ฐ ๋ค์ ์ผ์ ํ ์ ์๋๋ก DispatchQueue๋ฅผ ์ถ๊ฐํ๋ ๋ก์ง ์ถ๊ฐ (ํ๋กํผํฐ ์ต์ ๋ฒ ํ์ฉ)
-
Bool ํ์ ๋ค์ด๋ฐ์ ํ ๋ ๋ถ์ ๋ฌธ์ ์ฌ์ฉํด๋ ๋ ๊น?
-
Bool ํ์ ๋ณ์๋ฅผ ๋ง๋ค ๋ ๋ถ์ ๋ฌธ์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์๋ guard ๊ตฌ๋ฌธ์ ํ๊ตญ๋ง๋ก ํํํ๋ฉด
ํ์ด๋จธ ์ธ์คํด์ค๊ฐ ์กด์ฌํ์ง ์์ง ์๋๋ค๋ฉด ํจ์๋ฅผ ์ข ๋ฃ ์์ผ๋ผ
๋ผ๊ณ ํํํ ์ ์๋ค.- ๋ค์ ๋งํด
ํ์ด๋จธ ์ธ์คํด์ค๊ฐ ์กด์ฌํ๋ค๋ฉด ํจ์๋ฅผ ์ข ๋ฃ์์ผ๋ผ
๋ก ๋ค์ ํ๋ฒ ์๊ฐํด์ผํ๋ค.
- ๋ค์ ๋งํด
-
ํ์ง๋ง ์ฝ๋๋ ๊ฐ๊ฒฐํ๊ฒ ์์ฑํ ์ ์๋ค.
// ํ์ด๋จธ์ ์ธ์คํด์ค๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ guard ๊ตฌ๋ฌธ์์ ํจ์๋ฅผ ์ข ๋ฃํจ. func open() { let isNotWorking = timer == nil guard isNotWorking else { return } startTimer() // ... }
-
Bool ํ์ ๋ณ์๋ฅผ ๋ง๋ค ๋ ๋ถ์ ๋ฌธ์ ์ฌ์ฉํ์ง ์๋ ๊ฒฝ์ฐ ๋ค์ false ๊ตฌ๋ฌธ์ด ์ถ๊ฐ๋๋ค.
// ํ์ด๋จธ์ ์ธ์คํด์ค๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ guard ๊ตฌ๋ฌธ์์ ํจ์๋ฅผ ์ข ๋ฃํจ. func open() { let isWorking = timer != nil guard isWorking == false else { return } startTimer() // ... }
-
ํ๋กํผํฐ๋ก ํ๋ฒ์ ๊น๋ํ๊ฒ ๋ง๋๋ ๊ฒ์ด ์ข์๊ฑด์ง ์๋๋ฉด false๋ฌธ์ด๋ผ๋ ์ถ๊ฐํ์ฌ ์ฝ๊ธฐ ์์ํ๋๋ก ๊ตฌ์ฑํด์ฃผ์ด์ผ ํ๋๊ฒ ๋ง๋๊ฑด์ง ์๋ฌธ์ด๋ค.
-
-
DispatchQueue๋ ์์ ํ๊ณ ์๋ ๊ฒ์ ์ค๊ฐ์ ์ค์ง์ํฌ ์ ์์๊น?
- cancel ๋ฉ์๋๋ฅผ ํธ์ถํ๋๋ผ๋ ์์ ์ด ์์ ์ค์ด๋ผ๋ฉด ์ค์ง์ํฌ ์ ์๋ค.
- ์ฐํํ๋ ๋ฐฉ๋ฒ์ด ์กด์ฌํ์ง๋ง GCD๊ฐ ์์ ์ ์ทจ์ํ๊ฑฐ๋ ํ๋ ๊ฒ์ ํ ์๋ ์๋ค.
- Operation Queue๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ์ค์ธ ์์ ์ ์ค์ง ํ ์ ์๋ค. [์ฐธ๊ณ ๋งํฌ]
-
Custom View ํด๋์ค ๋ด๋ถ์ ํ๋กํผํฐ๋ฅผ ๊ฐ์ ธ๋ ๋๋๊ฐ?
- ํ์ํ๋ค๋ฉด ์ฌ์ฉํด๋ ๋ฌด๊ดํ๋ค.
- ํน์ ๋ทฐ๋ฅผ ์ฐพ์ ๋ Int, String์ฒ๋ผ ์ค๋ณต๋ ๊ฐ์ด ๋ค์ด์ฌ ๊ฒฝ์ฐ ์ฌ๋ฌ ๋ทฐ๋ฅผ ์ฐพ์์ฌ ์๋ ์๋ค.
- UUID๋ฅผ ํ์ฉํ๋ ํ์ฉํ๋ฉด ๊ณ ์ ํ ๊ฐ์ ๊ฐ์ง ์ ์๋ค.
์ํฉ
UIButton์ View์ ์์๋ฅผ ์ ๋ฐ์ดํธ ํ๋๋ก ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ณ ํ ์คํธ ํด๋ณด์์ผ๋, ๋ฒํผ์ด ํด๋ฆญ๋จ๊ฐ ๋์์ ํ๋ฉด์ด ๋ฉ์ถ๊ณ ์๋ฌ๊ฐ ๋๋ฉด์ ๋ทฐ๊ฐ ์ ๋ฐ์ดํธ ๋์ง ์๋ ์ํฉ์ ๋ง์ฃผํ๋ค.
์ด์
๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ๋ทฐ๋ฅผ ๊ทธ๋ฆฌ๋ ์์ ์ main thread์์ ์ฒ๋ฆฌํด์ฃผ์ด์ผ ํ๋๋ฐ, ๋ฐ๋ก ์ฒ๋ฆฌํด์ฃผ์ง ์์์ ํด๋น ์๋ฌ๊ฐ ๋ฐ์ํ๋ ๊ฒ ๊ฐ๋ค.ํด๊ฒฐ
๋ทฐ๋ฅผ ๊ทธ๋ฆฌ๋ ์์ ์ main thread์์ ์ฒ๋ฆฌํ๋๋ก DispatchQueue.main.async ํด๋ก์ ๊ตฌ๋ฌธ์์ ๋ฃ์ด์ฃผ์๋ค.
์ํฉ
๊ณ ๊ฐ ์ถ๊ฐ๋ฒํผ์ ์ฌ๋ฌ๋ฒ ํด๋ฆญํ๊ณ ์ด๊ธฐํ๋ฅผ ๋๋ฅด๊ฒ ๋๋ฉด ํ์ด๋จธ๊ฐ ๋ฉ์ถ์ง ์์๋ค.
์ด์
ํ์ด๋จธ๊ฐ ์ถ๊ฐ๋ฒํผ ํด๋ฆญ์ ๊ณ์ ์ถ๊ฐ๋๋ฉด์ ์ถ๊ฐ๋ ํ์ด๋จธ๊ฐ ๋๋์ง ์๊ณ ๊ณ์ ์คํ๋๋ ๋ฏ ํ๋ค.ํด๊ฒฐ
์ด๊ธฐํ ๋ฒํผ์ ํด๋ฆญํ ๋, ๋๊ธฐ์ค์ธ ๊ณ ๊ฐ์ด ์์ ๋ ํ์ด๋จธ๋ฅผ ๋ฉ์ถ๋ฉด์ ํ์ด๋จธ์ nil์ ๋์ ํด์ฃผ์๊ณ , ํ์ด๋จธ๊ฐ ์๋์ค์๋ ํ์ด๋จธ๋ฅผ ์ถ๊ฐํ์ง ์๋๋ก ํ๋ ๋ก์ง์ ์ถ๊ฐํด์ฃผ๋ ํด๊ฒฐ๋์๋ค.
- ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ ์ค UI ์์ ์ ๋ฐ์ดํธ์ ์ฃผ์์ ์ดํด
- ์ปค์คํ ๋ทฐ ๊ตฌํ
- ์คํ๋ทฐ ํ์ฉ
- ์ฝ๋๋ก UI ๊ตฌ์ฑ(์คํ ๋ ์ด์์)
- ํ์ด๋จธ ํ์ฉ๋ฐฉ๋ฒ๊ณผ Run Loop