์ฌ๊ธฐ ์ด์์จ์ด ์ ์ด๋์..
Index
Not Open | Open |
---|---|
![]() |
- ์ค์ 10์ ~
- ์ ์ฌ 12-2์
- ์ ๋ 6-7์
- ์ฃผ๋ง์ ํด์
- ์ฌ๊ณ ์ถ์ผ๋ฉด ์ธ์ ๋ ์ง ๋งํ๊ธฐ
- STEP 1 โ 12.21 18:00
- STEP 2 โ 12.24 18:00
- STEP 3 โ 12.28 18:00
- ๋จ์
- ๋ฉ์ธ์ง
- ๊ตฌํ ์ Issue๋ฅผ ์์ฑํ๋ฉฐ ์๊ตฌ์ฌํญ์ ๋ํด ํ๋ฒ ๋ ์๊ฐํด๋ณธ๋ค.
- ์ฐ๋ฆฌ๊ฐ ๋ฃ์ด์ค ์ธ๋ฑ์ค์ ์๋ ์์นํ๋ ๋ ธ๋๋ฅผ ์์ ๋ณ์์ ์ ์ฅ(๋ณต์ฌ)ํ๊ณ , ์๋ ์์นํ๋ ๋ ธ๋์ ์ฐ๋ฆฌ๊ฐ ๋ฃ์ด์ค ๋ ธ๋๋ฅผ ๋ฃ์
- ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ฐ์ ๋ฃ์ ๋ ธ๋๋ฅผ ๋ฃ๊ณ ์ถ์ ์ธ๋ฑ์ค์ ๋ค์ ๋ ธ๋๋ก ์์ ๋ณ์์ ์ ์ฅํ๋ ๋ ธ๋๋ฅผ ์ค์ (์๋ ํด๋น ์ธ๋ฑ์ค์ ์์นํ๋ ๋ ธ๋)
- ์๋ก์ด ๋ ธ๋๊ฐ ๋ค์ด๊ฐ์ผ๋ฏ๋ก, prev์ next๋ฅผ ์ ๋ ธ๋์ ์ฐ๊ฒฐ
๋ณดํต์ removeLast()
๊ธฐ๋ฅ์ Queue์ FIFO ํน์ฑ์ ๋ฐ๋ผ removeFirst()
๋ก ์์ ํด์ฃผ์์
์ด ๊ณผ์ ์์ ๋ฐ๋ก ์กฐ๊ฑด์ ๋ง๋ค์ด ์ฃผ์ง ์์ head = nil
์ ํ๊ฒ ๋๋ฉฐ head๋ถํฐ ์ฐ๊ฒฐ๋์ด ์๋ ํ์์ LinkedList๊ฐ ์ ๋ถ ๋๊ฒจ๋ฒ๋ฆฌ๋ ๋ฌธ์ ๋ฐ์
head.next
์ head
๋ฅผ ํ ๋นํ๋ ๊ฒ์ด ์๋ head
๋ ์ด์ head.next
์ธ ๋ฐฉ์์ ์ฌ์ฉ ์ ์์ ์ผ๋ก ๋์ํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐ
// before
func removeFirst() -> T? {
guard head != nil else {
return nil
}
let data = head?.data
if head?.next != nil {
head?.next = head
}
head = nil
return data
}
// after
func removeFirst() -> T? {
guard head != nil else {
return nil
}
let data = head?.data
if head?.next != nil {
head = head?.next
} else {
head = nil
}
return data
}
removeFirst()
์ ํ
์คํธ๋ฅผ ์งํํ๋ฉฐ ๋ฐํ ๊ฐ์ ์ฌ์ฉํ ํ์๊ฐ ์๋ค๊ณ ์๊ฐ๋์ด@discardableResult
ํค์๋๋ฅผ ๋ถ์
ํด๋น ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ Queue์ Dequeue()
์๋ ๋งฅ๋ฝ์ ์ํด @discardableResult
์ ๋ถ์
๋จ๋ฐฉํฅ์ผ๋ก ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ฅผ ๊ตฌํํ๋ ๊ณผ์ ์์ ๋ฆฌ์คํธ์ ๋งจ ๋ง์ง๋ง ๋
ธ๋ ๋ค์์ ๋
ธ๋๋ฅผ ์ถ๊ฐํด์ฃผ๋ append()
๋ฅผ ํ๋ ค๋ฉด ๋ฆฌ์คํธ์ ๋๊น์ง ์ํํด์ผํ๋ค๋ ๋จ์ ์ด ์์
์ด๋ฅผ ๊ฐ์ ํ๊ณ ์ ์๋ฐฉํฅ ์ฐ๊ฒฐ๋ฆฌ์คํธ๋ก ์์
์๋ฐฉํฅ์ผ๋ก ์ฐ๊ฒฐํ์ฌ append()
๋ฅผ ํ ๋, ๋ชจ๋ node๋ฅผ ์ํํ์ง ์๊ณ ๋ฐ๋ก tail์ ์ฐพ๊ธฐ๋๋ฌธ์ ๋จ๋ฐฉํฅ์ ๋จ์ (๋ง์ ๋น์ฉ(์ํ))์ ๋ณด์
- ๋ ธ๋๋ ํ์ ๋ด๋ถ์์ ๊ฐ์ ํ์ ์ธ ์์ ์ ์ฐธ์กฐํ๊ธฐ๋๋ฌธ์ ๊ตฌ์กฐ์ฒด๋ก ๊ตฌํํ ์ ์์
- ๋ ธ๋๋ฅผ ํด๋์ค๋ก ์์ฑํ์ฌ ํ ๋ ธ๋์ ๋ํด ์ฐธ์กฐ ํด์ ๋ฅผ ํด์ค ๊ฒฝ์ฐ, ARC๋ก ์ธํด ๋ฉ๋ชจ๋ฆฌ์์ ๋ด๋ ค๊ฐ๊ฒ๋ ๋ง๋ค์ด์ค ์ ์์ผ๋ฏ๋ก ํด๋์ค๋ก ์์ฑ
- LinkedList๋ queueํ์ ์์ ์๋ณธ๊ฐ(๋ ธ๋)์ด ๊ณ์ ๋ณ๊ฒฝ๋์ด์ผ ํ๊ธฐ๋๋ฌธ์ ๋ณต์ฌํ๋ ๊ฒ์ด ์๋, ์๋ณธ์ ์ฐธ์กฐํ์ฌ ์๋ณธ๊ฐ์ ๋ณ๊ฒฝํ๊ธฐ ์ํด ํด๋์ค๋ก ์์ฑ
- ํ ์คํธํ๋ ค๋ ํ์ ์ ์ธ์คํด์ค ํ๋กํผํฐ์ ์ ๊ทผ์ ์ด๋ฅผ ์ฃผ์๋๋ฐ, ์ด๋ ์ธ๋ถ์์ ์ฌ์ฉํ๋ ๊ฒ์ ๋ง๊ธฐ ์ํด ์ค์ ํ์์
- Unit Test ์งํ์ ํด๋น ํ๋กํผํฐ์ ์ ๊ทผํ์ฌ ํ ์คํธ๋ฅผ ํด์ผํ๋๋ฐ, ์ ๊ทผ์ ์ด๊ฐ ์ค์ ๋์ด ์์ผ๋ฏ๋ก ํ ์คํธ ํ์ง ๋ชปํ๋ ๋ฌธ์ ๊ฐ ๋ฐ์
- ๊ทธ๋ด ๋ Mock ํ์ ์์ฑ ํ ํด๋น ํ์ ์ ํ ์คํธ๋ง์ ์ํด ์ฌ์ฉํ๋ฉด ๋จ ์ด๋ก์จ Mock์ ์๋ณธ ํ์ ์ ๋ณธ๋ ์ํ ์ ์ง
- Step1์์ ๊ตฌํํ Queue๋ฅผ ์ด์ฉํด ๊ณ ๊ฐ ๊ด๋ฆฌ
- ์ง์์ ๊ณ ๊ฐ ์ ๋ฌด์ฒ๋ฆฌ, ์ ๋ฌด์ฒ๋ฆฌ ์๊ฐ ๊ตฌํ
- ํ์ ์ถ์ํ ๋ฐ ์ผ๋ฐํ
- ์ญํ ๋ถ๋ฆฌ
- ์ํ๊ด๊ณ๋ก ์ค๊ณํ์ฌ ๋จ๋ฐฉํฅ ์์กด์ ํจ์ผ๋ก์จ ์ํ ์ฐธ์กฐ ๋ฑ์ ์ํฉ ๋ฐฉ์ง
// Bank
mutating func letClerkWork() {
while waitingLine.isEmpty == false {
bankClerk.work(&waitingLine)
}
}
// Clerk
func work(_ waitingLine: inout Queue<Customer>) {
guard let customer = waitingLine.dequeue() else {
return
}
print("\(customer.waitingNumber)๋ฒ ๊ณ ๊ฐ ์
๋ฌด ์์")
Thread.sleep(forTimeInterval: 0.7)
print("\(customer.waitingNumber)๋ฒ ๊ณ ๊ฐ ์
๋ฌด ์ข
๋ฃ")
}
- ํจ์ ์ธ๋ถ์ ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝํ๋ฉฐ ์ฌ์ฉํ๊ธฐ์ํด์
inout Parameter
๋ฅผ ์ฌ์ฉํด์ผ ํจ - ํ์๋ค์ ์ด๋ก์ธํด ๊ฐ๋ ์ฑ์ด ๋จ์ด์ ธ ๋ณด์ธ๋ค๋ ์๊ฐ์ด ๋ค์๊ณ , ๊ฐ ํ์ ์ ์ญํ ์ ๋ ๋ถ๋ช ํ ํ๋ค๋ฉด ์ด๋ฅผ ํด๊ฒฐํ ์ ์์ ๊ฒ์ด๋ผ ์๊ฐํ์๊ณ ์ฝ๋ ๊ฒํ ๊ฒฐ๊ณผ, ๊ธฐ์กด์ ์ํ์ ์ผ๋ก ์ค๊ณํ ์ผ์ ์ง์์ด ํ๊ณ ์์๊ณ ์ด๋ฅผ ์ํ์ด ์ผ์ ํ ๋ค, ์ผ์ ๊ฒฐ๊ณผ๋ฅผ ์ง์์ด ๋ฐ์ ์ฒ๋ฆฌํ๋ ๋ก์ง์ผ๋ก ๋ณ๊ฒฝํ์์
Bank์ ์ ๋ฌด ๋ง๊ฐ์ ์๋ฆฌ๋ ์ถ๋ ฅ๋ฌธ์ ๊ตฌํํ ๋, ๋ช ๋ช ์ ๊ณ ๊ฐ์ ๋ฐ์๋์ง ์์์ผ ํ์
์๊ฐํ ๋๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
-
์ฒ์์ BankManager๊ฐ ์์ฑํ์ฌ์ฃผ๋ ๋๋คํ ๊ณ ๊ฐ์ ์๋ฅผ ๊ฐ์ ธ์ Bank ์ธ์คํด์ค ํ๋กํผํฐ์ ํ ๋นํด ์ค ๋ค ๊ทธ๊ฒ์ ์ฌ์ฉํ๋ ๊ฒ
struct Bank { var totalNumber = 0 mutating func setWaitingLine(with numberOfCustomer: () -> Int) { totalNumber = numberOfCustomer() for number in 1...totalNumber { waitingLine.enqueue(Customer(waitingNumber: number)) } } }
-
Bank์ย
letClerkWork()
ย ๋ฉ์๋ ๋ด๋ถ์์ ์ด๊ธฐ๊ฐ 0์ ๊ฐ์ง ์ง์ญ ๋ณ์๋ฅผ ์์ฑํ์ฌ loop๊ฐ ํ๋ฒ ๋ ๋(dequeue
ํ๋ฒ)๋ง๋ค ํด๋น ์ง์ญ ๋ณ์์ ์นด์ดํธ ํด์ฃผ๋ ๋ฐฉ์์ผ๋ก ๊ฐ์ ํ ๋นํ์ฌ ์ฌ์ฉํ๋ ๊ฒstruct Bank { mutating func letClerkWork() { let taskTime = 0.7 var numberOfCustomer = 0 while waitingLine.isEmpty == false { let customer = dequeueWaitingLine() bankClerk.handleTask(of: customer, until: taskTime) numberOfCustomer += 1 } noticeCloseDown(totalCustomer: numberOfCustomer, taskTime: taskTime) } }
์ธ์คํด์ค ํ๋กํผํฐ: ์ ํฌ๊ฐ ์ค๊ณํ ํ๋ก๊ทธ๋จ ๋ด์์ Bank
๋ผ๋ ์ธ์คํด์ค๋ ์ํ์ด ์ด๋ฆฌ๋ ์์ ๋ถํฐ ์
๋ฌด๊ฐ ์ข
๋ฃ๋๋ ์์ ๊น์ง ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ผ๊ฐ ์์ด ํ๋กํผํฐ๊ฐ ์ฌ์ฉ๋์ง ์์ ๋์๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ฐจ์งํ๊ณ ์๋ค.
ํจ์ ๋ด๋ถ์ ์ง์ญ๋ณ์: ํจ์์ ์คํ์ด ๋๋๋ฉด ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋์ง๋ง, ๋ฐ๋ณต์ ์ธ ์ฐ์ฐ์ด ์ผ์ด๋ ์ฒ๋ฆฌ๋น์ฉ์ด ์๋ชจ๋๋ค๋ ๋จ์ ์ด ์๋ค.
๊ณ ๋ฏผ ๊ฒฐ๊ณผ
์ธ์คํด์ค ํ๋กํผํฐ๋ฅผ ์ฑํํ์๋ค.
- ์ด์ : ํด๋น ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ๋ ๋ฉ์๋๊ฐ ๋จ ํ๊ฐ๋ผ๋ฉด ์ง์ญ ๋ณ์๊ฐ ๋ง๊ฒ ์ง๋ง, ํด๋น ํ๋กํผํฐ๋ฅผ ๋ ๊ณณ์์ ์ฌ์ฉํด์ค์ผ ํ์ผ๋ฏ๋ก, ๋ ๋ฉ์๋๊ฐ ๋ฐ๋ณต์ ์ผ๋ก ์ง์ญ๋ณ์๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ฆฌ๊ณ ๋ด๋ฆฌ๊ณ ์ ๋น์ฉ๋ณด๋ค ์ธ์คํด์ค๊ฐ ์์ฑ๋ ๋ ํ๋ฒ๋ง ์ฌ๋ ค์ฃผ๋ ๊ฒ์ด ๋ ๋ซ๊ฒ ๋ค๊ณ ํ๋จํ์๋ค.
- ์ฝ๋ ์์ฑ ์ , UML๊ณผ ํ์ ์ ์ถ์ํ, ์ผ๋ฐํ๋ฅผ ํตํด ๊ฐ ํ์ ์ ์ฑ ์์ ๋ถ๋ช ํ ํ์์
์ํ์์ด ๊ณ ๊ฐ์ ์ง์ ๋ถ๋ฌ์ฌ์ง, ์ํ์ด ์ํ์์๊ฒ ๊ณ ๊ฐ์ ๋๊ฒจ์ค์ง ๋ฑ์ ๊ฐ๊ฐ ์์ ์ ์ฑ ์์ ๊ฐ์ง๊ฒ ํ์ฌ ๊ด๊ณ๋ฅผ ๋ถ๋ช ํ ํ๋ค๋ฉด ์ดํ ๋จ์ผ ์ฑ ์๊ณผ ์์กด์ฑ ๊ด๋ฆฌ์ ์ฉ์ดํ ๊ฒฐ๊ณผ๋ฅผ ๋ถ๋ฌ์ด์ ์๊ฒ๋์์
in-out
ย ํ๋ผ๋ฏธํฐ๋ ๊ธฐ์กด ํ๋ผ๋ฏธํฐ์ ๊ฐ์ ๋ณ๊ฒฝ์ํค๋ ๊ฒ์ด ์๋ ๊ธฐ์กด ํ๋ผ๋ฏธํฐ๋ฅผ ๋ณต์ฌํ์ฌ ํจ์ ๋ด๋ถ์์ ๊ฐ์ ์์ ํ๊ณ , ํจ์๊ฐ ๋ฐํ๋ ๋ ๊ธฐ์กด ํ๋ผ๋ฏธํฐ ๊ฐ์ ๋ณต์ฌ๋(์์ ๋) ๊ฐ์ผ๋ก ํ ๋น
https://www.swift.org/documentation/api-design-guidelines/#naming
- ์ฌ๋ฌ ์ํ์๋ค์ด ๋์์ ์ผ์ ์ฒ๋ฆฌํ๋ ๋ก์ง ๊ตฌํ
- CustomQueue๋ฅผ ๊ตฌํํ์ฌ ํน์ ์ผ์ ์ฒ๋ฆฌํ๋ ์ง์์ด ํ๋ช ์ธ ์ํฉ์ Serial Queue๋ฅผ ์ฌ์ฉํ๊ณ , ์ฌ๋ฌ๋ช ์ธ ์ํฉ์ Concurrent Queue๋ฅผ ์ฌ์ฉํ์ฌ ์ผ์ ์ฒ๋ฆฌํ๋๋ก ๊ตฌํ
- Concurrent Queue์์ ์์ ์ ์ฒ๋ฆฌํ๊ธฐ ์ ์์ ์ ์์๋ฅผ ์ ํ๊ธฐ ์ํด Serial Queue์์ ์์๋๋ก ์ผ์ Concurrent Queue๋ก ๋ณด๋ด๋ ๋ก์ง ๊ตฌํ
- Race Codition ๋ฐฉ์ง
- 2๊ฐ์ ์ค๋ ๋๊ฐ ์ ๊ทผํด๋ Race Condition์ ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก ์์๋๋ก ์์ ์ด ์ฒ๋ฆฌ๋ ์ ์๋๋ก ๊ตฌํ
- ์ผ์ ์ข ๋ฅ, ์ผ์ ์ข ๋ฅ์ ๋ฐ๋ฅธ ์ฒ๋ฆฌ์๊ฐ์ enum์ผ๋ก ๋ฐ๋ก ๋นผ์ฃผ์ด ํ๋์ฝ๋ฉ ๋ฐฉ์ง ๋ฐ ์ฝ๋ ์ ๋ฆฌ
์๊ธ ์
๋ฌด๋ฅผ ์ฒ๋ฆฌํ๋ ์ํ์์ 2๋ช
์ด๋ผ๋ ์กฐ๊ฑด์ด ์์ด, ๊ณต์ ์์์ ์ ๊ทผํ ์ ์๋ ์ค๋ ๋์ ์๋ฅผ 2๊ฐ๋ก ์ ์ดํด์ฃผ๊ธฐ ์ํดย semaphore
๋ฅผ ์ฌ์ฉํ์๋ค.ย
DispatchSemaphore
๋ย semaphore
๋ฅผ ์นด์ดํธํ๋ ์์ผ๋ก ๋์ํ๋๋ฐ,ย semaphore.wait()
์ ์์น๋ฅผ ์ด๋๊ณณ์ ์์ฑํด์ฃผ์ด์ผ ํ๋์ง ๊ณ ๋ฏผ์ด ๋์๋ค.
์๋์ ๊ฐ์ด ๋๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ ๊ฒ ๊ฐ์๋ฐ, ์ฒซ๋ฒ์งธ๋ ๋น๋๊ธฐ๊ฐ ์์๋ ๋ count -1์ ํด์ฃผ๋ ๋ฐฉ๋ฒ์ด๊ณ ๋๋ฒ์งธ๋ ๋น๋๊ธฐ ์์ ์ ์ count๋ฅผ ํ๋ ๋ฐฉ๋ฒ์ด๋ค.ย
wait()
๋ ๊ฐ์ ์ ๊ทผํ๋ค๊ณ ์๋ฆฌ๋ ๋ฉ์๋๋ผ๊ณ ์๊ฐํด์ ๋น๋๊ธฐ๊ฐ ์์๋๋ ๋ด๋ถ์ ์์ฑํด์ฃผ์๋ค.
// 1. ๋น๋๊ธฐ ๋ด๋ถ์ ์์ฑํ๋ ๋ฐฉ๋ฒ
case .deposit:
depositQueue.async(group: workGroup) {
semaphore.wait()
taskTime = BankTask.deposit.processingTime
self.bankClerk.handleTask(of: customer, until: taskTime)
numberOfCustomer += 1
semaphore.signal()
}
// 2. ๋น๋๊ธฐ ์์ ์ ์ ์์ฑํ๋ ๋ฐฉ๋ฒ
case .deposit:
semaphore.wait()
depositQueue.async(group: workGroup) {
taskTime = BankTask.deposit.processingTime
self.bankClerk.handleTask(of: customer, until: taskTime)
numberOfCustomer += 1
semaphore.signal()
}
// before: ๊ณ ๊ฐ์ ๋ฒํธํ ์์๋๋ก ์ผ์ฒ๋ฆฌ๊ฐ ๋์ง ์์.
switch customer.task {
case .deposit:
depositQueue.async(group: workGroup) {
semaphore.wait()
self.bankClerk.handleTask(of: customer, until: BankTask.deposit.processingTime)
numberOfCustomer += 1
semaphore.signal()
}
// after: ๊ณ ๊ฐ์ ๋ฒํธํ ์์๋๋ก ์ผ์ฒ๋ฆฌ
switch customer.task {
case .deposit:
sequenceQueue.async {
depositQueue.async(group: workGroup) {
semaphore.wait()
self.bankClerk.handleTask(of: customer, until: BankTask.deposit.processingTime)
numberOfCustomer += 1
semaphore.signal()
}
}
/*
sequenceQueue - Serial Queue
depositQueue - Concurrent Queue
*/
๋์ถ(Loan)์ ๋ด๋นํ๋ ์ง์์ ํ๋ช ์ด๋ผ Serial Queue๋ฅผ ์ฌ์ฉํ์ฌ ๋จ์ผ ์ค๋ ๋๋ก ์ผ์ ์ฒ๋ฆฌํ ์ ์๋๋ก ํ์๊ณ , ์์๋๋ก ์ฒ๋ฆฌํ๋ Serial Queue์ ํน์ฑ์ผ๋ก ์ธํด ๋์ถํ๋ฌ์จ ๊ณ ๊ฐ์ ์์๋ ์ ์์ ์ผ๋ก ์ถ๋ ฅ
๊ทธ๋ฆฌ๊ณ ์๊ธ(Deposit)์ ๋ด๋นํ๋ ์ง์์ ๋๋ช ์ด๋ผ Concurrent Queue๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ค ์ค๋ ๋๋ก ์ผ์ ์ฒ๋ฆฌํ๋๋ก ํ์์
ํ์ง๋ง, ํด๋น ๊ณผ์ ์์ ๊ณ ๊ฐ์ ์๋ฒ๋๋ก ์ผ์ด ์์๋์ง ์๋๋ค๋ ๋ฌธ์ ๋ฐ์
ํ์ ํ ์์ธ์ผ๋ก Concurrent Queue์ ํน์ฑ์ ์์๋ฅผ ์ค์ํ ํ์ง ์๋๋ค๋ ์ ์์ ๋ฐ์ํ ๋ฌธ์ ๋ก ํ์ ํ์ฌ ํด๋น Task๋ฅผ Serial Queue๋ก ๊ฐ์ธ์ฃผ์ด ์์๋๋ก Task๋ฅผ Concurrent Queue์ ๋ฃ์ด์ฃผ์ด ์ฒ๋ฆฌํ๊ฒ ํ์ฌ ์์๋๋ก ์ฒ๋ฆฌํ๋๋ก ๊ตฌํ
ํ์ง๋ง ๊ฒฐ๊ณผ์ ์ผ๋ก Task๊ฐ ์ฒ๋ฆฌ๋๋ ๊ฑด Concurrent Queue์์ ๋ค์ค ์ค๋ ๋์ ํ ๋น๋์ด ์ฒ๋ฆฌ๋๋๋ฐ ์ ๊ณต์๋ฌธ์์ ๋ช ์๋ Concurrent Queue์ ํน์ฑ์ ์์๋ฅผ ์ค์ํ ํ์ง ์๋๋ค๋ ์ ์๋ ๋ถ๊ตฌํ๊ณ ์์๋๋ก ์ถ๋ ฅ์ด ์ ๋๋ ๊ฒ์ด ์ด์ํ๋จ ์๊ฐ์ด ๋ค์๊ณ , ์์์ Serial Queue๋ฅผ ๊ฑฐ์ณ ์์๋ฅผ ์ ํด์ค๋ ๊ฒฐ๊ณผ๊ฐ ์์๋๋ก ์ถ๋ ฅ๋๋ ๊ฒ๊ณผ ์๊ด์ด ์์ ๊ฒ ๊ฐ์๋ฐ ์ ์ ์์ ์ผ๋ก ๋์ํ์ง?, ์ด์ ์ฝ๋๋ ๋๊ฐ์๊ฑฐ ์๋๊ฐ? ๋ผ๋ ์๊ฐ์ด ๋ค์๋ค.
๊ทธ ๊ฒฐ๊ณผ ์ด๋ GCD์ ์์ญ์ด๋ฉฐ, ์ฐ๋ฆฌ๋ sequenceQueue.async { }
ย Serialํ๊ฒย depositQueue.async(group: workGroup)
์ฝ๋๋ฅผ ์คํ์์ผ์ ์์๋๋ก ์ฒ๋ฆฌํ๊ฒ ๋ง๋ค๊ธฐ๋ง ํ๋ฉด ๋๋ ๊ฒ์์ ์์์
private func finishWork(workingTime: Double) {
delegate?.didFinishWork(totalCustomer: totalCustomer, workingTime: workingTime)
totalCustomer = 0
}
์ํ์ ์ผ์ด ๋๋๋ฉด ์ํ ๋ง๊ฐ๋์๋ค๊ณ ์๋ ค์ฃผ๋ ๊ฒ์ย BankManager
์ ์ญํ ์ด ์๋๊น ํ๋ ๊ณ ๋ฏผ์ ํ์๊ณ , ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ์ํด delegation pattern์ ํ์ฉํ์ฌ ์ํ์ ์
๋ฌด๊ฐ ๋๋ ์ ๋งค๋์ ์๊ฒ ์ํ ์
๋ฌด๊ฐ ๋๋ฌ๋ค๊ณ ์๋ฆฌ๊ณ , ๋งค๋์ ๊ฐ ๋ง๊ฐ ๋ฉ์ธ์ง๋ฅผ ์ถ๋ ฅํด์ฃผ๋ ๋ฐฉ์์ ์ฑํํ์์
Bank ํ์ ์ด ๊ตฌ์กฐ์ฒด์ธ ๊ฒฝ์ฐ ๋ด๋ถ ๋ฉ์๋ ์์ ํ์ถ ํด๋ก์ ๋ ๊ฐ์ ์บก์ฒํ ์ ์์๋ค.
์ด์ ๋ ํด๋ก์ ๊ฐ ๊ฐ์ ์บก์ฒํ ๋ ์๋ณธ์ ๊ฐ์ ์บก์ฒํ๋ ๊ฒ์ด ์๋ ๊ตฌ์กฐ์ฒด ๋ณต์ฌ๋ณธ์ ์บก์ฒํ๊ธฐ๋๋ฌธ์ ์๋ฌด๊ฒ๋ ๋ณ๊ฒฝ๋์ง ์์ผ๋ฏ๋ก ์ปดํ์ผ ์๋ฌ๋ฅผ ๋ด๋ ๊ฒ์ด๋ค.
์ด๋ฌํ ์ด์ ๋ก Bank๋ฅผ ํด๋์ค๋ก ๋ณ๊ฒฝํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์๋ค.
- ๋๊ธฐ(Synchronous)์ ๋น๋๊ธฐ(Asynchronous)์ ์ดํด
- GCD
- ์ค๋ ๋
- ํด๋ก์ ์บก์ณ
- ButtonStackView - Button x2
- TimerStackView - Label x2
- CustomerStatusStackView - StatusLabel + ScrollView + CustomerListStackView
- CustomerListStackView - CustomerLabel
extension UIView {
func anchor(top: NSLayoutYAxisAnchor? = nil,
left: NSLayoutXAxisAnchor? = nil,
bottom: NSLayoutYAxisAnchor? = nil,
right: NSLayoutXAxisAnchor? = nil,
paddingTop: CGFloat = 0,
paddingLeft: CGFloat = 0,
paddingBottom: CGFloat = 0,
paddingRight: CGFloat = 0,
width: CGFloat? = nil,
height: CGFloat? = nil) {
translatesAutoresizingMaskIntoConstraints = false
if let top = top {
topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
}
if let left = left {
leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true
}
if let bottom = bottom {
bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true
}
if let right = right {
rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true
}
if let width = width {
widthAnchor.constraint(equalToConstant: width).isActive = true
}
if let height = height {
heightAnchor.constraint(equalToConstant: height).isActive = true
}
}
}
UIView์ Extension์ ๊ตฌํํ์ฌ ํด๋น ๋ฉ์๋๋ฅผ ์์ฑ
์ด๋ฅผ ํตํด ๋ ์ด์์ ์ค์ ์ฝ๋๊ฐ ๊ฐ๊ฒฐํด์ง๊ณ ๊น๋ํด๋ณด์ด๋ ํจ๊ณผ๊ฐ ์์๋ค.
์คํฌ๋กค์ ์ํด ์คํฌ๋กค ๋ทฐ ์์ ์น์ด์ง๋ ์คํ๋ทฐ์ ํฌ๊ธฐ๋ฅผ ์คํฌ๋กค๋ทฐ์ ๋ง์ถค
class CustomerStatusStackView: UIStackView {
private func configLayout() {
customerListScrollView.anchor(left: leftAnchor, right: rightAnchor)
customerListStackView.anchor(top: customerListScrollView.topAnchor, left: customerListScrollView.leftAnchor, bottom: customerListScrollView.bottomAnchor, right: customerListScrollView.rightAnchor)
}
}
class CustomerLabel: UILabel {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
convenience init(task: String, waitingNumber: Int) {
self.init()
configUI()
setText(waitingNumber, task)
}
}
class CustomerStatusStackView: UIStackView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init(coder: NSCoder) {
fatalError("init(coder:) hastitlenot been implemented")
}
convenience init(title: String, bgColor: UIColor) {
self.init()
configUI()
configLayout()
statusLabel.text = title
statusLabel.backgroundColor = bgColor
}
}
convenience init
์ ๊ตฌํํ์ฌ ํ๋ผ๋ฏธํฐ๋ก ํ์ดํ๊ณผ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ ๋ฑ์ ๋ฐ์ ์ฌ์ฌ์ฉํ ์ ์๊ฒ ๊ตฌํ
๊ณ ๊ฐ ์ถ๊ฐ ๋ฒํผ์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ ๋ ํ์ด๋จธ๊ฐ ์์๋๊ณ , ๊ณ ๊ฐ์ ์ผ์ฒ๋ฆฌ๊ฐ ๋ชจ๋ ์ข ๋ฃ๋์์ ๋ ํ์ด๋จธ๊ฐ ๋ฉ์ถ๋๋ก ๊ตฌํ
๋ทฐ์ปจํธ๋กค๋ฌ๊ฐ BankClerk
์ delegate์ด๋ค.
- Delegate pattern์ ์ฌ์ฉํ์ฌ ์ง์์ด ์ผ์ ์ฒ๋ฆฌํ๊ธฐ ์์ํ์์ ๋ ๋ทฐ์
CustomerLabel
์ ์ถ๊ฐํด์ฃผ๋๋ก ๊ตฌํ - Delegate pattern์ ์ฌ์ฉํ์ฌ ์ง์์ด ์ผ์ฒ๋ฆฌ๋ฅผ ์ข
๋ฃํ์์ ๋ ๋ทฐ์
CustomerLabel
์ ์ญ์ ํด์ฃผ๋๋ก ๊ตฌํ
extension ViewController: BankClerkDelegate {
func bankClerkStartWork(waitingNumber: Int, task: String) {
DispatchQueue.main.async { [self] in
let customer = waitingLineStackView.removeLabel()
customer.removeFromSuperview()
workingLineStackView.addLabel(customer)
}
}
func bankClerkFinishWork(waitingNumber: Int, task: String) {
DispatchQueue.main.async { [self] in
let customer = workingLineStackView.removeLabel()
customer.removeFromSuperview()
}
}
}
class BankClerk {
delegate?.bankClerkStartWork(waitingNumber: customer.waitingNumber, task: task)
Thread.sleep(forTimeInterval: taskTime)
delegate?.bankClerkFinishWork(waitingNumber: customer.waitingNumber, task: task)
}
Bank
์์์ ์ผ์ฒ๋ฆฌ๊ฐ ์ข
๋ฃ๋์์ ๋ ViewController
์์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์ ํ์ด๋จธ๋ฅผ ์ข
๋ฃ์ํค๊ณ , View
๋ฅผ ์
๋ฐ์ดํธํด์ผํ๋ค.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(stopTimer), name: .finishWork, object: nil
}
@objc func stopTimer() {
timer.invalidate()
}
}
class Bank {
workGroup.notify(queue: .main) {
NotificationCenter.default.post(name: .finishWork, object: nil)
}
}
๊ณ ๊ฐ์ ์ผ์ ์ฒ๋ฆฌํ๋ ์ง์๋ค์ ๋น๋๊ธฐ๋ก ์ผ์ ์ฒ๋ฆฌํ๊ณ , ์ด๋ค์ Group
์ผ๋ก ๋ฌถ์ด ํด๋น ๋น๋๊ธฐ ๋์์ด ์ข
๋ฃ๋์์๋ ๋์์ ์ ์ํ ์ ์๋ DispatchGroup.notify()
๋ฅผ ๊ตฌํํ์ฌ ViewController
์ NotificationCenter
์ Notification
์ Post
ํ๊ฒ๋ ๊ตฌํ