๋ณธ ๊ธ์ WWDC ๋ฅผ ๋ณด๊ณ , ๋ฒ์ญ ๋ฐ ์์ฝ ๊ทธ๋ฆฌ๊ณ ์คํํด๋ณด๋ ์คํฐ๋ ํ๋ก์ ํธ์ ์ผํ์ ๋๋ค.
Introducing Combine
WWDC19์๋ Apple์ ์ต์ Framework์ธ Combine์ ์๊ฐํฉ๋๋ค. ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ๋ํด์ ์ด์ผ๊ธฐํ์๊ณ ํ๋ฉด์ ์๋ง์ ์ฌ๋๋ฐ์. ๊ฐ์ด ์์๋ฅผ ๋ณด๊ณ ์ดํดํ๋ฉด์ Combine์ ๋ํด์ ์์๋ณด๋๋ก ํฉ์๋ค.
๊ฐ๋จํ ํ์๊ฐ์ ํ๋ฉด์ ์์๋ก ๋ญ๋๋ค. ์ด ํ๋ฉด์์์ ์๊ตฌ์ฌํญ์ ํฌ๊ฒ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ์ฐ์ ์ฌ์ฉ์ ์ด๋ฆ์ด ์ ํจํ์ง ๋คํธ์ํฌ์ ์์ฒญ์ ํด์ ํ์ธ์ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋น๋ฐ๋ฒํธ๊ฐ ์๋ก ์ผ์นํ๋์ง ํ์ธ์ ํฉ๋๋ค. ์ด ๋ชจ๋ ์์ ์ ๋ฉ์ธ ์ค๋ ๋์์ ์ฐจ๋จ๋์ง ์๊ณ ๋ฐ์ํ ์ธํฐํ์ด์ค๋ฅผ ์ ์งํด์ผ ํฉ๋๋ค.
๋จผ์ ์ฌ์ฉ์ ์ด๋ฆ์ ์ ๋ ฅํ๊ธฐ ์์ํฉ๋๋ค. ์ฌ๊ธฐ์๋ ์ด๋ฏธ ๋ง์ ๋น๋๊ธฐ ์์ ์ด ์งํ๋๊ณ ์์ต๋๋ค. Target/Action์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ์ ๋ ฅ์ ๋ํ ์๋ฆผ์ ์์ ํ์ต๋๋ค. ์ฌ๊ธฐ์ ๋ง์ ๋คํธ์ํฌ ์์ฒญ์ผ๋ก ์๋ฒ๋ฅผ overwhelmํ์ง ์๊ธฐ ์ํด์ Timer๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์๊ฐ ์ ๋ ฅ์ ์ ์ ๋ฉ์ถ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค. ๊ทธ๋ฆฌ๊ณ KVO์ ๊ฐ์ ๊ฒ์ ์ฌ์ฉํด์ ํด๋น ๋น๋๊ธฐ ์์ ์ ๋ํ ์งํ๋ฅ ์ ๋ฐ์ดํธ๋ฅผ ์์ ํฉ๋๋ค.
์ด๋ฆ๊ณผ ์ํธ๋ฅผ ์ ๋ ฅํ๋ฉด์ ์๋ฒ์ ํต์ ํ๊ณ ์ ํจํ ๊ฐ์ธ์ง๋ฅผ ์ฒดํฌํด์ค๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ์ ๋ฐ๋ผ UI๋ ์ ๋ฐ์ดํธ ํด์ฃผ๊ฒ ๋ฉ๋๋ค.
Asynchronous Interfaces
- Target/Action
- Notification center
- URLSession
- Key-value observing
- Ad-hoc callbacks
Cocoa SDK ์ ๋ฐ์ ๊ฑธ์ณ์ ๋น๋๊ธฐ ์ธํฐํ์ด์ค๋ ์ ๋ง ์๋นํ ๋ง์ต๋๋ค. ์ด ๋ชจ๋ ๊ฒ๋ค์ ๊ฐ๊ฐ ์ค์ํ๊ณ ๊ฐ๊ธฐ ๋ค๋ฅธ ์ฌ์ฉ๋ฒ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ด๊ฒ๋ค์ ํจ๊ป ์ฌ์ฉํ ๋ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ์ด ๋ชจ๋ ๊ฒ๋ค์ ๋์ฒดํ์ง ์๊ณ , ๊ณตํต์ ์ ์ฐพ๊ธฐ ์ํด Combine์ด ๋ฑ์ฅํ๊ฒ ๋ฉ๋๋ค.
Combine
A unified, declarative API for processing values over time
- Combine์ ์๊ฐ ๊ฒฝ๊ณผ์ ๋ฐ๋ฅธ ๊ฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ํตํฉ ์ ์ธ์ API์ ๋๋ค.
- Combine์ ๊ธฐ์กด์ API๋ฅผ ๋์ฒดํ์ง ์์ต๋๋ค.
Combine Features
- Generic
- Type Safe
- Composition first
- Request driven
- Swift์ฉ์ผ๋ก ๋ง๋ค์ด์ ธ์ Generic๊ณผ ๊ฐ์ Swift ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์์ต๋๋ค.
- Type Safe ํ๋ฏ๋ก ๋ฐํ์์ด ์๋ ์ปดํ์ผ ํ์์ ์ค๋ฅ๋ฅผ ์ก์ ์ ์์ต๋๋ค.
- ์ฌ๋ฌ ๊ฐ๋ฅผ ๊ตฌ์ฑํ๊ณ ์กฐํฉํ์ฌ ์ฝ๊ณ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์์ฒญ ๊ธฐ๋ฐ์ด๋ฏ๋ก ์ฑ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋๊ณผ ์ฑ๋ฅ์ ์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
Combine์ ํต์ฌ ๊ฐ๋
- Publisher
- Subscriber
- Operators
Publishers
- Defines how values and errors are produced
- Combine API์ ์ ์ธ์ ๋ถ๋ถ์ ๋๋ค. Publisher๋ ๊ฐ๊ณผ ์ค๋ฅ๊ฐ ์์ฑ๋๋ ๋ฐฉ์์ ์ ์ํ๋๋ฐ์. ์ค์ ๋ก ๋ฐ๋์ ๊ทธ๊ฒ๋ค์ ์์ฑํ๋ ๊ฒ์ ์๋๋๋ค. ์์ฑํ ์๋ ์๊ณ , ์๋ ์๋ ์๋ค๋ ๊ฒ์ด์ฃ .
- Value type
- ๊ตฌ์กฐ์ฒด๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๊ฐ(Value) ํ์ ์ ๋๋ค.
- Allows registration of a Subscriber
- ๊ตฌ๋ ์(Subscriber) ๋ฑ๋ก๋ ํ์ฉํฉ๋๋ค.
protocol Publisher {
associatedtype Output
associatedtype Failure: Error
func subscribe<S: Subscriber>(_ subscriber: S)
where S.Input == Output, S.Failure == Failure
}
- Output
- ์์ฑํ๋ ๊ฐ์ ์ข ๋ฅ์ ๋๋ค.
- Failure
- ์์ฑํ๋ ์ค๋ฅ์ ์ข ๋ฅ์ ๋๋ค. ์๋ฌ๋ฅผ ์์ฑํ ์ ์๋ ๊ฒฝ์ฐ Never ํ์ (associated type)์ ์ด์ฉํ ์ ์์ต๋๋ค.
- ํต์ฌ ๊ธฐ๋ฅ (Subscribe: ๊ตฌ๋ )
- Subscriber์ ์ ๋ ฅ์ Publisher์ ์ถ๋ ฅ๊ณผ ์ผ์นํด์ผ ํ๊ณ , Subscriber์ ์คํจ๋ Publisher์ ์ ๋ ฅ๊ณผ ์ผ์นํด์ผ ํฉ๋๋ค.
NotificationCenter
extension NotificationCenter {
struct Publisher: Combine.Publisher {
typealias Output = Notification
typealias Failure = Never
init(center: NotificationCenter, name: NotificationCenter.Name, object: Any? = nil)
}
}
๋ค์ ์ฝ๋๋ NotificationCenter๋ฅผ ์ํ Publisher์ ๋๋ค. Output์ Notification, Failure๋ Never ํ์ ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ center, name, object ์ธ ๊ฐ์ง ํญ๋ชฉ์ผ๋ก ์ด๊ธฐํ ๋ฉ๋๋ค. ์ด๊ฒ์ NotificationCenter๋ฅผ ๋์ฒดํ๋ ๊ฒ์ด ์๋๋๋ค. ๋จ์ง ์ ์ฉํ๊ณ ์๋ ๊ฒ์ด์ฃ .
Subscribers
- Receives values and a completion
- Subscriber๋ Publisher์ ๋ฐ๋๋๋ ๊ฐ๋ ์ ๋๋ค. Publisher๋ฅผ ๊ตฌ๋ ํ๊ณ Publiser๊ฐ ์ ํ(finite)ํ ๊ฒฝ์ฐ ์๋ฃ๋ฅผ ํฌํจํ ๊ฐ์ ๋ฐ์ต๋๋ค.
- Reference type
- Subscriber๋ ์ผ๋ฐ์ ์ผ๋ก ๊ฐ์ ๋ฐ์ผ๋ฉด ํ๋(์ฒ๋ฆฌ)ํ๊ณ ์ํ๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ๋๋ฌธ์ class์ ๋์ผํ๊ฒ ์ฐธ์กฐ ํ์ ์ ์ฌ์ฉํฉ๋๋ค.
protocol Subscriber {
associatedtype Input
associatedtype Failure: Error
func receive(subscription: Subscription)
func receive(_ input: Input) -> Subscribers.Demand
func receive(completion: Subscribers.Completion<Failure>)
}
- Input
- Failure
- Subscriber ๊ฐ ์คํจ๋ฅผ ์์ ํ ์ ์๋ ๊ฒฝ์ฐ Never ํ์ (associated type)์ ์ด์ฉํ ์ ์์ต๋๋ค.
- ํต์ฌ ๊ธฐ๋ฅ (Receive: ๊ตฌ๋ ์ ๋ฐ๋ ๊ฒ)
- Receive๋ Publiser์์ Subsriber๋ก ๋ฐ์ดํฐ ํ๋ฆ์ ์ ์ดํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
Assign
extension Subscribers {
class Assign<Root, Input>: Subscriber, Cancellable {
typealias Failure = Never
init(object: Root, keyPath: ReferenceWritableKeyPath<Root, Input>)
}
}
Assign ํด๋์ค๋ Input์ ๋ฐ์ผ๋ฉด ํด๋น ๊ฐ์ฒด์ ํ๋กํผํฐ์ ๊ธฐ๋ก์ ํฉ๋๋ค. Swift์์๋ ํ๋กํผํฐ ๊ฐ์ ์์ฑํ ๋ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์ Assign์ Failure ์ ํ์ Never๋ก ์ค์ ํฉ๋๋ค.
The Pattern
- ๋ง์ฝ์ Subsriber๋ฅผ ๊ฐ์ง๊ณ ์๋ Controller ๊ฐ์ฒด ๋๋ ๋ค๋ฅธ ํ์ ์ด ์๋ค๊ณ ๊ฐ์ ํด๋ด ์๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ Subsciber์ ํจ๊ป Publisher์ subsribe ํจ์๋ฅผ ํธ์ถํด์ ์ฐ๊ฒฐํด์ฃผ์ด์ผ ํ๋ ์ฑ ์์ด ์์ต๋๋ค.
- ์ด ์์ ์์ Publisher๋ Subsriber์๊ฒ Subscription์ ๋ณด๋ด, Subscriber๊ฐ Publisher์๊ฒ ํน์ ์์ ๊ฐ ๋๋ ๋ฌด์ ํ ์์ฒญ์ ํ ์ ์๋๋ก ํฉ๋๋ค.
- Publisher๋ ํด๋น ์ ์ดํ์ ๊ฐ์ Subscriber์๊ฒ ์์ ๋กญ๊ฒ ๋ณด๋ผ ์ ์์ต๋๋ค.
- Publisher๋ ์ ํํ ๊ฒฝ์ฐ ๊ฒฐ๊ตญ Completion ๋๋ Error๋ฅผ ๋ณด๋ ๋๋ค.
์กธ์ ํ๋ ํ์๋ค์ ๋ํ ์๋ฆผ์ ๋ฃ๊ณ ์กธ์ ํ๋ฉด, Wizard ๊ฐ์ฒด๋ค์ ๊ฐ์ ์ผ๊ด์ ์ผ๋ก ์ ๋ฐ์ดํธ ํ๊ณ ์ถ์ต๋๋ค.
- ์กธ์ ์ ๋ํ ์๋ฆผ์ NotificationCenter์ Publisher๋ฅผ ์ด์ฉํด์ ์๋ฆฝ๋๋ค.
- Assign Subscriber๋ฅผ ๋ง๋ค๊ณ merlin์ ํ๋ (grade)์ ์๋ก์ด ๊ฐ์ผ๋ก ๋ณ๊ฒฝํ ์ ์๋๋ก ํฉ๋๋ค.
- ๊ทธ ์ดํ์ ๊ตฌ๋ (subscribe)์ ํตํด ์ฐ๊ฒฐํ ์ ์๋๋ฐ์.
๊ทธ๋ฐ๋ฐ ๋ญ๊ฐ ์์๋๋ก ์ปดํ์ผ๋์ง ์์ต๋๋ค. ๊ทธ ์ด์ ๋ ํ์ ์ด ์ผ์นํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์์์ Publisher์ Output๊ณผ Subscriber์ Input์ ํ์ ์ด ์ผ์นํด์ผํ๋ค๊ณ ํ์์ฃ ? (๊ธฐ์ต์๋๋ฉด ์ด์ฉ ์ ์๊ตฌ์…)
Notification Center์์ Notification์ ๋ณด๋ด์ง๋ง Assign์ด Int ํ์ ์ ๊ฐ์ ์ฐ๊ณ ์ถ์ ์ํฉ์ ๋๋ค. ์ฐ๋ฆฌ๋ ๊ทธ๋ผ ์ง๊ธ Int ํ์ ์ด ํ์ํ๊ฑฐ์ฃ . ๊ทธ๋์ ์ด ์ฌ์ด์ ๋ณํํ๋ ๊ณผ์ ์ด ํ์ํ๋ฐ์. ์ด๋ฅผ ์ํด ํ์ํ ๊ฒ์ด Operator์ ๋๋ค.
Operator
- Publisher ํ๋กํ ์ฝ์ ์ฑํํฉ๋๋ค. ์ฑํํ ๋๊น์ง๋ Publisher์ธ ๊ฒ์ด์ฃ .
- ์ ์ธ์ ์ด๋ฏ๋ก ๊ฐ ํ์ ์ ๋๋ค.
- ๊ฐ ๋ณ๊ฒฝ, ์ถ๊ฐ, ์ ๊ฑฐ ๋๋ ๋ค์ํ ์ข ๋ฅ์ ๋์์ ์ํํฉ๋๋ค.
- upstream์ด๋ผ๊ณ ๋ถ๋ฆฌ์ฐ๋ ๋ค๋ฅธ Publisher๋ฅผ ๊ตฌ๋ ํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ downstream์ด๋ผ๊ณ ๋ถ๋ฅด๋ Subscriber์๊ฒ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ ๋๋ค.
Map
extension Publishers {
struct Map<Upstream: Publisher, Output>: Publisher {
typealias Failure = Upstream.Failure
let upstream: Upstream
let transform: (Upstream.Output) -> Output
}
}
Map์ด๋ผ๋ Operator๋ ๊ฒฐ๊ตญ Publisher์๋ค์? Map์ ์ด๋ค Upstream์ ์ฐ๊ฒฐํ๊ณ Upstream์ Output์ ์์ฒด Output์ผ๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ด๊ธฐํ๋๋ ๊ตฌ์กฐ์ฒด์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์์ฒด์ ์ผ๋ก Failure๋ฅผ ์์ฑํ์ง ์์ต๋๋ค. ๋จ์ํ Upstream์ Failure ํ์ ์ mirroringํ๊ณ ๊ทธ๋ฅ ์ ๋ฌํฉ๋๋ค.
let converter = Publishers.Map(upstream: graduationPublisher) { note in
return note.userInfo?["NewGrade"] as? Int ?? 0
}
์ด ์ฝ๋๋ง ์ ๊น ์ดํดํ๊ณ ๋์ด๊ฐ๋ฉด ์ข์ ๊ฒ ๊ฐ์์. (์ฐธ ํฅ๋ฏธ๋กญ๋ค์..ใ ) ๊ธฐ์กด์ ์ปดํ์ผ ์๋ฌ๊ฐ ๋ฌ๋ ์ด์ ๋ Publisher์ Subscriber์ ํ์ ์ด ๋ง์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋ ๊ธฐ์ ์ฐ๋ฆฌ๋ ์ค๊ฐ ๊ณผ์ ์ด ํ์ํ๊ณ , ๊ทธ ์ญํ ์ ๋์์ฃผ๋ Operator๊ฐ ๋ฑ์ฅํ ๊ฒ์ด์ฃ . Operator ์ญ์ ๊ฒฐ๊ตญ ์ด์ (upstream)์ ๊ฐ์ ๊ฐ์ง๊ณ ์์ ๋ณ๊ฒฝํ๊ณ ๋ ๋ค๋ฅธ Output์ ๋ด๋ณด๋ด๋ Publisher๋ผ๊ณ ๋ด๋ ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ ๋ค์ ๋์์์ ์ง๊ธ ์ฐ๋ฆฌ๋ Notification์ Int๋ก ์ธ ์ ์๊ฒ ํ๊ณ ์ถ์ ๊ฒ์ด์์์? graduationPublisher์ upstream์ผ๋ก ๊ฐ์ ธ์์ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๋ฉด ๋ฉ๋๋ค. graduationPublisher์ Output์ธ Notification์ userInfo Int ๊ฐ์ ๋ค์ ๋ฐํํด์ฃผ๋ฉด ๋ ๊ฒ ๊ฐ์์. ๊ทธ๋ฌ๋ฉด ์ด์ ์ ์์ ์ผ๋ก subscribe๊ฐ ๊ฐ๋ฅํด์ง๋๋ค.
extension Publisher {
func map<T>(_ transform: @escaping (Output) -> T) -> Publishers.Map<Self, T> {
return Publishers.Map(upstream: self, transform: transform)
}
}
๋ค์๊ณผ ๊ฐ์ด ๊ตฌ๋ฌธ์ ์ข ๋ ๊ฐ๋จํ๊ฒ ์ฌ์ฉํ ์๋ ์์ต๋๋ค. ์ด๋ ๊ฒ extension์ ์ด์ฉํ๋ฉด ๋ชจ๋ Publisher๊ฐ ์ฌ์ฉํ ์ ์๋ ํจ์๋ฅผ ์ธ ์ ์๊ฒ ๋์ฃ .
let cancellable = NotificationCenter.default.publisher(for: .graduated, object: merlin)
.map { note in return note.userInfo?["NewGrade"] as? Int ?? 0 }
.assign(to: \.grade, on: merlin)
์ด ๊ตฌ๋ฌธ์ ๋ณด๋ฉด ๋จ๊ณ๋ณ๋ก ๋งค์ฐ ์ ํ์ ์ด๊ณ ์ดํดํ๊ธฐ ์ฌ์ด ํ๋ฆ์ ์ ๊ณตํ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. Assign์ cancelable ํญ๋ชฉ์ ๋ฐํํฉ๋๋ค. Cancelation ๋ํ Combine์ ๋ด์ฅ๋์ด ์์ต๋๋ค. Cancelation์ ํตํด ํ์ํ ๊ฒฝ์ฐ Publisher ๋ฐ Subscriber๋ฅผ ์กฐ๊ธฐ์ ํด์ ํ ์ ์์ต๋๋ค.
์ด ๋จ๊ณ๋ณ ๊ตฌ๋ฌธ์ Combine ์ฌ์ฉ ๋ฐฉ๋ฒ์ ํต์ฌ์ ๋๋ค. ๊ฐ ๋จ๊ณ๋ ์ฒด์ธ์ ๋ค์ ๋ช ๋ น์ด ์ธํธ๋ฅผ ์ค๋ช ํฉ๋๋ค. ์ฒซ ๋ฒ์งธ Publisher์์ ์ผ๋ จ์ Operator๋ฅผ ๊ฑฐ์ณ Subscriber๋ก ๋๋๋ ๊ฐ์ ๋ฐํํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฌํ Operator๋ฅผ ๋ง์ด ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ฅผ Declarative Operator API๋ผ๊ณ ๋ถ๋ฆ ๋๋ค.
Declarative Operator API
- Functional transformations
- Map, Filter, Reduce ๋ฑ์ด ์์ต๋๋ค.
- List operations
- Publisher์ ์ฒซ ๋ฒ์งธ, ๋ ๋ฒ์งธ ๋๋ ๋ค์ฏ ๋ฒ์งธ element๋ฅผ ์ทจํ๋ ๊ฒ๊ณผ ๊ฐ์ ์์ ์ ๋์ดํฉ๋๋ค.
- Error handling
- ์ค๋ฅ๋ฅผ ๊ธฐ๋ณธ๊ฐ ๋๋ ๋์ฒด๊ฐ์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ๊ณผ ๊ฐ์ ์์ ๋ ๊ฐ๋ฅํฉ๋๋ค.
- Thread or queue management
- ์ค๋ ๋, ํ์์ ์ด๋, ๋ฌด๊ฑฐ์ด ์์ ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋ ์ด๋, UI ์์ ์ ๋ฉ์ธ ์ค๋ ๋๋ก ์ด๋ From ๋ฃจํ, ๋์คํจ์น ํ, ํ์ด๋จธ ์ง์, ํ์์์ ๋ฑ๊ณผ ๊ฐ์ ์์ ์ญ์ ์ง์ํฉ๋๋ค.
- Scheduling and time
์ฌ์ค Operator๊ฐ ๋๋ฌด ๋ง์์ ์ฐ์ฐ์๋ฅผ ์ฐพ๊ณ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ๋ถ๋ด์ ๋๋ ์ ์์ต๋๋ค.
Try composition first
Apple์์ ๊ถ์ฅํ๋ ๊ฒ์ Combine์ ๋ํ ํต์ฌ ๋์์ธ ์์น์ผ๋ก ๋์๊ฐ๋ ๊ฒ์ ๋๋ค. ๋ฐ๋ก Composition์ธ๋ฐ์. ์ ์ด์ ์ค๊ณ๋ถํฐ ๋ง์ ์์ ์ ์ํํ๋ ๋ช ๊ฐ์ง Operator๋ฅผ ์ ๊ณตํ๋ ๋์ , ์ฝ๊ฐ์ ํต์ฌ ์์ ๋ง ์ํํ๋ Operator๋ฅผ ๋ง์ด ์ ๊ณตํ์ฌ ์ดํดํ๊ธฐ ์ฝ๋๋ก ๊ตฌ์ฑํ์ต๋๋ค. ๊ฐ๋ฐ์๋ค์ด ์ฝ๊ฒ ์ดํดํ ์ ์๋๋ก Swift Collection API์์ ์ด๋ฆ์ ๋ง์ด ๋ฐ์๋ค๊ณ ํฉ๋๋ค.
์ผ์ชฝ์ ๋๊ธฐ API์ด๊ณ , ์ค๋ฅธ์ชฝ์๋ ๋น๋๊ธฐ API์ ๋๋ค. ์์ชฝ์ ๋จ์ผ ๊ฐ, ์๋์ชฝ์ ๋ค์์ ๊ฐ์ ๋ค๋ฃน๋๋ค. ๋จ์ผ ๊ฐ์ ๋น๋๊ธฐ์ ์ผ๋ก ๋ํ๋ด์ผ ํ๋ ๊ฒฝ์ฐ Future๋ฅผ ์ฌ์ฉํ๊ณ , ๋ค์์ ๊ฐ์ ๋น๋๊ธฐ์ ์ผ๋ก ๋ํ๋ด์ผ ํ๋ ๊ฒฝ์ฐ Publisher๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
Operator Example
์ด ์์๋ ํค๊ฐ ์๊ฑฐ๋ ์ ์๊ฐ ์๋ ๊ฒฝ์ฐ 0์ ๋ฐํํ๊ณ ์์ต๋๋ค. ์๋ชป๋ ๊ฐ์ด ์ ์ฅ๋๋๋ก ํ๋ ๊ฒ๋ณด๋ค nil์ ๋ฐํํ๋๋ก ํ๋ ๊ฒ์ด ๋ ์ข์๋ณด์ ๋๋ค.
compactMap
์ด ๋, Swift 4.1์ ๋์ ๋ compactMap์ ์ด์ฉํด๋ณผ ์ ์์ต๋๋ค. compactMap๋ ์ญ์ Combine์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ฌ๋ฉด ์ด์ ๊ณผ ๋ค๋ฅด๊ฒ ํด๋ก์ ์์ nil์ ๋ฐํํ๋ฉด compactMap์ ์ด๋ฅผ ํํฐ๋งํ์ฌ downstream์ผ๋ก ๋ ์ด์ ์งํ๋์ง ์๋๋ก ํฉ๋๋ค.
filter
์ด๋ฒ์๋ filter operator๋ฅผ ์ด์ฉํด์ 5ํ๋ ์ด์๋ง ๊ฑธ๋ฌ์ง๋๋ก ํด๋ณด๊ฒ ์ต๋๋ค. Array์์ ์ฌ์ฉ๋๋ filter์ ๋์์ด ์ผ์นํฉ๋๋ค.
prefix
๋๋ ๋ฐ๋ณต๋๋ ์์ ๋์ 3๋ฒ๊น์ง๋ง ๊ฐ์ ์ ๋ฌํ๊ณ ์ถ์ผ๋ฉด prefix operator๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
Combining Publishers
2๊ฐ์ง Operator๋ฅผ ๋ ์๊ฐํ๊ฒ ์ต๋๋ค.
Zip
๋ง๋ฒ์ฌ ์ฑ์์ ์งํก์ด๋ฅผ ์์ฑํ๋ ๋จ๊ณ์ ๋๋ค. ์งํก์ด๋ฅผ ๋ง๋ค๊ธฐ ์ํด์๋ 3๊ฐ์ง ์ค๋ ๊ฑธ๋ฆฌ๋ ๋น๋๊ธฐ ์์ ์ด ์๋ฃ๋์ด์ผ ํฉ๋๋ค. ์ฌ์ฉ์๊ฐ ๊ณ์ํ๋๋ก ํ์ฉํ๋ ค๋ฉด ์์ ์์ ์ด ์๋ฃ๋์ด์ผ ํ๊ฒ ์ฃ . zip์ ์ด์ฉํ๋ฉด 3๊ฐ์ ์์ ์ด ๋ชจ๋ ์๋ฃ๋ ์์ ์ ์บ์นํด์ Continue ๋ฒํผ์ ํ์ฑํ ์ํฌ ์ ์์ต๋๋ค.
Zip์ ์ฌ๋ฌ Upstream์ ๋จ์ผ Tuple๋ก ๋ณํํฉ๋๋ค. downstream์ผ๋ก ๊ฐ์ ์ ๋ฌํ๊ณ ์์ ์ ์งํํ๋ ค๋ฉด ๋ชจ๋ upstream์์ ์ ๋ ฅ(Input)์ด ํ์ํฉ๋๋ค. ์ฒซ ๋ฒ์งธ Publisher์์ A๋ฅผ ์์ฑํ๊ณ , ๋ ๋ฒ์งธ Publisher์์ 1์ ์์ฑํ๋ฉด ์ด์ Tuple์ ๋ง๋ค๊ณ ํด๋น ๊ฐ์ Subscriber์๊ฒ downstream์ผ๋ก ๋ณด๋ผ ์ ์์ต๋๋ค.
์ด ์ฑ์์๋ Bool ํ์ ์ ์ ๊ณตํ๋ 3๊ฐ์ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋๋ฐ 3๊ฐ์ upstream์ด ํ์ํ Zip ๋ฒ์ ์ ์ฌ์ฉํฉ๋๋ค. Tuple์ ๋จ์ผ Bool๋ก ๋งคํํ๊ณ ์ฌ๊ธฐ์์ ๋ฒํผ์ isEnabled ์์ฑ์ ๋ฐ๊ฟ์ค๋๋ค. 3๊ฐ์ ์์ ์ด ๋ชจ๋ ์๋ฃ๋๋ฉด true๊ฐ์ด ์ธํ ๋๊ณ ๋ฒํผ์ด ํ์ฑํ ๋ฉ๋๋ค.
CombineLatest
Play ๋ฒํผ์ด ํ์ฑํ๋๊ธฐ ์ ์ 3๊ฐ์ ์ค์์น๋ฅผ ๋ชจ๋ ํ์ฑํํด์ผ ํ๊ณ , ํ๋๋ผ๋ ๋นํ์ฑํ๋๋ค๋ฉด Play ๋ฒํผ๋ ๋นํ์ฑํํด์ผ ํฉ๋๋ค. ์ด๋ด ๋ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ด CombineLatest์ ๋๋ค.
Zip๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ฌ๋ฌ upstream์ Input์ ๋จ์ผ ๊ฐ์ผ๋ก ๋ณํํฉ๋๋ค. ๊ฐ upstream์์ ๋ฐ์ ๋ง์ง๋ง ๊ฐ์ ์ ์ฅํ๊ณ ์ด๋ฅผ ๋จ์ผ downstream ๊ฐ์ผ๋ก ๋ณํํฉ๋๋ค. ์ฒซ ๋ฒ์งธ Publisher๊ฐ A๋ฅผ ์์ฑํ๊ณ ๋ ๋ฒ์งธ Publisher๊ฐ A1์ ์์ฑํ๋ฉด ์ด๋ฅผ ๋ฌธ์์ดํํ๊ณ downstream์ผ๋ก ๋ด๋ ค๋ณด๋ด๊ณ ๋์ค์ ๋ ๋ฒ์งธ Publisher๊ฐ ์ ๊ฐ์ ์์ฑํ๋ฉด ์ฒซ ๋ฒ์งธ Publisher์ ์ด์ ๊ฐ๊ณผ ๊ฒฐํฉํ์ฌ ์ ๊ฐ์ ๋ณด๋ ๋๋ค.
upstream์ด ๋ณ๊ฒฝ๋๋ฉด ์๋ก์ด ์ด๋ฒคํธ๊ฐ ๋ฐ์ํฉ๋๋ค.
Combine์ ์ฌ์ฉํ๊ธฐ ์ํด์ ๋ชจ๋ ๊ฒ์ ๋ณํํ ํ์๋ ์์ต๋๋ค. ๋ช ๊ฐ์ง๋ถํฐ ์์ํด๋ณด์ธ์.
- NotificationCenter์ ์๋ฆผ์ ์์ ํ๊ณ ์กฐ์น ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ ค๋ฉด filter๋ฅผ ์ด์ฉํด๋ณด์ธ์.
- ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ์ ๊ฐ์ค์น๋ฅผ ๋ถ์ฌํ๋ฉด ๋คํธ์ํฌ ์์ ์ ํฌํจํ์ฌ Zip์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- URLSession์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ JSON Decoder๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น ๋ฐ์ดํฐ๋ฅผ ํน์ ๊ฐ์ฒด๋ก ๋ณํํ๋ ๊ฒฝ์ฐ์๋ ๋์์ด ๋ฉ๋๋ค. decode operator๋ฅผ ํ์ธํด๋ณด์ธ์.