RxSwift
1. RxSwift ๊ฐ๋
1) Reactive Programming์ด ๋ฌด์์ธ์ง ์ค๋ช
ํด์ฃผ์ธ์.
Reactive Programming ์ ๋ฐ์ดํฐ์ ํ๋ฆ์ ๋ฐ์ํ๋ฉฐ ๋ก์ง์ ๊ตฌ์ฑํ๋ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ ๋๋ค.
๋ฐ์ดํฐ์ ์ํ๋ณํ๋, ์ด๋ฒคํธ์ ๋ฐ๋ฅธ ๋ก์ง์ ์์ฑํฉ๋๋ค.
์ด ๋, ๋ฐ์ดํฐ์ ํ๋ฆ์ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๊ธฐ ๋๋ฌธ์ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ข์ต๋๋ค.
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๊ฒฐํฉํด ๊ฐ๋ ์ฑ ์ข๊ณ ์ ์ง๋ณด์ ์ข์ ์ฝ๋๋ฅผ ์ง๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
2) RxSwift ๋ฅผ ์ ์ผ๊ณ ์ฅ๋จ์ ์ด ๋ญ๊ฐ ์๋์?
๋น๋๊ธฐ ์ฝ๋๋ฅผ ์ฝ๊ฒ ์์ฑํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋คํธ์ํฌ ํต์ ์ ์ํด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์์ ์ Observable ์ ๋ด์์ ์์ฑํ๋ค๋ฉด, Observable ์ด ๋ฑ์ด๋ด๋ onNext, onCompleted ๋ฑ์ ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ฝ๊ฒ ํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด Data Binding ์ ํธํ๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํฉ๋๋ค. map ์ด๋ filter ๋ฑ์ Operator ๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ๊ธฐ ์ข์ต๋๋ค.
๋ฐ์ดํฐ ํ๋ฆ์ ๋ค๋ฃฐ ๋ ์ ์ฉํ ํด๋์ค๋ค์ด ๋ง์ต๋๋ค. Observable, Subject ๋ฑ์ ํด๋์ค๋ฅผ ์ฌ์ฉํด์ ๋ฐ์ดํฐ ํ๋ฆ์ ํจ๊ณผ์ ์ผ๋ก ๋ค๋ฃฐ ์ ์์ต๋๋ค.
3) RxSwift ์ Combine ์ฐจ์ด๋ฅผ ์ค๋ช
ํด์ฃผ์ธ์.
RxSwift ๋ ์ ํ์ด ๋ง๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋๋๋ค. Rx๋ Swift ๋ฟ ์๋๋ผ Java, Python ์์๋ ์ฌ์ฉ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ๋ฐ๋ฉด์ Combine ์ ์ ํ์ด ๋ง๋ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ์ด๋ก ์ธํด ํ์๋๋ ํน์ง์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
RxSwift ๋ฅผ ์ฌ์ฉํ์ ์, Rx ๋ฅผ ์ฌ์ฉํ๋ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค๊ณผ ์ํตํ ์ ์์ต๋๋ค. ๋ก์ง์ ํต์ผ ์ํฌ ์ ์์ต๋๋ค.
Combine ์ ์ฌ์ฉํ์ ์, ์ข ๋ ์์ ์ ์ธ ํจ๊ณผ๋ฅผ ๊ธฐ๋ํ ์ ์์ต๋๋ค. ์ด๋๋ ๊ฐ์๊ธฐ Rx ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฌธ์ ๊ฐ ์๊ธด๋ค๋ฉด ๊ทธ๊ฑด ์ ํ์ ์ฑ ์์ด ์๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
4) RxCocoa ๋ฅผ ์ธ ๋ ์ฅ์ ? ์ด๋ค ๊ฒฝํ์ ํ๋์
RxCocoa ๋ฅผ ์ฌ์ฉํ๋ฉด rx.tap ์ ํตํด ๋ฒํผ ํญ ์ด๋ฒคํธ๋ฅผ Observable ๋ก ๊ฐ์ฃผํด์ ๋ฒํผ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ throttle ์ด๋ debounce ๋ฑ์ ๊ธฐ๋ฅ์ ์ฝ๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
// ์ ์ ๊ฒ์ ๋ฒํผ์ ๋๋ ์ ๋ ์ด๋ฒคํธ ์ฒ๋ฆฌ
searchUserButton.rx.tap
// throttle ์ฒ๋ฆฌ
.throttle(.seconds(3), latest: false, scheduler: MainScheduler.instance)
.bind(onNext: { [weak self] in
let searchUserViewController = SearchUserViewController()
self?.navigationController?.pushViewController(searchUserViewController, animated: true)
UITableView ์ delegate ๋ฉ์๋๋ฅผ RxCocoa ๋ฅผ ํตํด ๊น๋ํ๊ฒ ์์ฑํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด tableView ์ willDisplay ๋ฅผ rxcocoa ๋ฅผ ํตํด tableView.rx.willDisplayCell { cell, index .. } ๋ก ๊น๋ํ๊ฒ ์์ฑํ ์ ์์ต๋๋ค.
// ํผ๋ ๋ฌดํ์คํฌ๋กค
feedTableView.rx.willDisplayCell
.subscribe(on: MainScheduler.instance)
.bind { [weak self] cell, index in
guard let self = self else { return }
// ...
// ํ
์ด๋ธ ๋ทฐ์ ๋ง์ง๋ง cell ์ด ๋ค๊ฐ์์ ๋ ์๋ก์ด ํผ๋ ํจ์น
if index.row == currentListLen - 1 {
self.viewModel.fetchFeedList()
}
}
2. Observable
1) RxSwift ์ Observable ์ด๋ ๋ฌด์์ธ์ง ์ค๋ช
ํด์ฃผ์ธ์.
RxSwift ์ Observable ์ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ด๋ฉฐ, ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ๋ ํด๋์ค์ ๋๋ค. ์ต์ ๋ฒ ํจํด์ Publisher ์ ๊ฐ๋ค๊ณ ์๊ฐํ ์ ์์ต๋๋ค.
Observable ์ ๊ตฌ๋ ํ๊ฒ๋๋ฉด, ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ๋๋ง๋ค ๊ทธ์ ๊ฑธ๋ง๋ ํ๋์ ํ ์ ์๊ฒ ๋ฉ๋๋ค.
next : ์ผ๋ฐ์ ์ธ ๋ฐ์ดํฐ or ์ด๋ฒคํธ ๋ฐฉ์ถ
error : ์๋ฌ ๋ฐฉ์ถ, ์คํธ๋ฆผ ์ข ๋ฃ
complete : ์ฑ๊ณต์ ์ธ ์ด๋ฒคํธ ๋ฐฉ์ถ + ์คํธ๋ฆผ ์ข ๋ฃ
Observable ์ Disposable ํ์ ์ ๋ฐํํฉ๋๋ค.
let observable = Observable<Int>.create { observer in
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onCompleted()
return Disposables.create()
}
observable.subscribe(onNext: { value in
print(value)
})
2) RxSwift์์ Hot Observable๊ณผ Cold Observable์ ์ฐจ์ด๋ฅผ ์ค๋ช
ํ์์ค.
Hot Observable ์ ์ด๋ฒคํธ๊ฐ ๊ตฌ๋ ์ฌ๋ถ์ ์๊ด์์ด ๋ฐ์ํ๊ณ ์๋ค๊ฐ, ๊ตฌ๋ ์ ํ ์์ ๋ถํฐ ์ด๋ฒคํธ๋ฅผ ๋ฐ์๋ณผ ์ ์๋ Observable ์ ๋๋ค.
Cold Observable ์ ๊ตฌ๋ ์ ์์ํ์ ๋ ๋น๋ก์ ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ๋ Observable ์ ๋๋ค. RxSwift์ ๊ธฐ๋ณธ Observable ์ Cold Observable ์ ๋๋ค.
Hot Observable ์ TV ์ง์ํ ๋ฐฉ์ก, Cold Observable ์ ๋ทํ๋ฆญ์ค์ ๋น์ ํ ์ ์์ต๋๋ค.
3) Single, Completable, Maybe์ ์ฐจ์ด์ ์ ๋ํด ์ค๋ช
ํ๊ณ , ์ธ์ ์ ์ฉํ๋ฉด ์ข์์ง ์ค๋ช
ํ์์ค.
๋จผ์ Single, Completable, Maybe ๋ ๋ชจ๋ Observable ์ ๋๋ค.
Single ์ Success / Error ๋ ์ค ํ๋๋ง์ ์ค์ง ํ๋ฒ๋ง ๋ฐฉ์ถํฉ๋๋ค. ์ ํํ ํ ๊ฐ์ง ์์๋ฅผ ํ ๋ฒ๋ง ๋ฐฉ์ถํ ๋ ์ฌ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋คํธ์ํฌ ์์ฒญ์ ๋ณด๋ด๊ณ ์์ฒญ์ ๋ํ ์๋ต ํ๋ฒ ๋ฐ์์ผํ ๊ฒฝ์ฐ Single ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
func fetchData() -> Single<Data> {
return Single.create { single in
// ... ๋คํธ์ํฌ ์์ฒญ ์ฒ๋ฆฌ ...
if let data = responseData {
single(.success(data))
} else {
single(.error(NetworkError.failed))
}
return Disposables.create()
}
}
Completable ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ์ง ์์ผ๋ฉฐ, ์์ ์ด ์๋ฃ ๋์์์ ๋ํ๋ผ ๋ ์ฌ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๋ ์์ฒญ์ ํ๊ณ , "์ ์ก ์๋ฃ" or "์ ์ก ์คํจ"๋ฅผ ์ถ๋ ฅํ๊ณ ์ถ์ ๊ฒฝ์ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค.
func sendData() -> Completable {
return Completable.create { completable in
// ... ๋ฐ์ดํฐ ์ ์ก ์ฒ๋ฆฌ ...
if success {
completable(.completed)
} else {
completable(.error(NetworkError.failed))
}
return Disposables.create()
}
}
Maybe ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ ์๋ ์๊ณ ํ์ง ์์ ์๋ ์์ต๋๋ค. ์ฃผ๋ก "๋ฐ์ดํฐ๊ฐ ์๋์ง ์ฌ๋ถ"๋ฅผ ๋ฐํํ๋ ์์ ์ ์ฌ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ก์ปฌ ์คํ ๋ฆฌ์ง์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ์์ ์ ์ํํ๊ณ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ๊ทธ ๊ฐ์ ๋ฐํ, ๊ทธ๋ ์ง ์์ผ๋ฉด completed ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
func readData() -> Maybe<Data> {
return Maybe.create { maybe in
// ... ๋ฐ์ดํฐ ์ฝ๊ธฐ ์ฒ๋ฆฌ ...
if let data = readData {
maybe(.success(data))
} else {
maybe(.completed)
}
return Disposables.create()
}
}
3.Disposable
1) Disposable ์ ๊ฐ๋
์ ์ค๋ช
ํด์ฃผ์ธ์
RxSwift ์ Disposable ์ Observable ์ ๊ตฌ๋ ์ ํด์ ํ๋ ๋ฐ ์ฌ์ฉ๋๋ ๊ฐ๋ ์ ๋๋ค.
Observable ์ subscribe() ๋ฉ์๋๋ฅผ ํตํด์ ๊ตฌ๋ ์ ์์ํ๊ณ , ์ด subscribe ๋ฉ์๋๋ Disposable ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
Disposable.dispose() ๋ฅผ ํ๋ฉด ๊ตฌ๋ ์ด ํด์ ๋ฉ๋๋ค.
let disposable = observable.subscribe(onNext: { value in
print("Received value: \(value)")
})
disposable.dispose() // ๊ตฌ๋
์ทจ์
์๋ฅผ ๋ค์ด Observable ์ด UI ์ด๋ฒคํธ๋ฅผ ๋ฐํํ๋๋ฐ, ์ ์ ๊ฐ ๊ทธ ํ๋ฉด์์ ๋๊ฐ๋ค๋ฉด ๋ ์ด์ ๊ทธ Observable ์ ํ์๊ฐ ์์ด์ง ๊ฒ์ด๊ธฐ ๋๋ฌธ์ dispose() ํด์ค์ผ ํฉ๋๋ค.
2) DisposeBag ์ ๋ํด์ ์ค๋ช
ํด์ฃผ์ธ์. ์ธ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํ๋์?
DisposeBag ์ ์ฌ์ฉํ๋ฉด, ๊ตฌ๋ ์ ํด์ ํ ๋์๋ค์ ๋ด์ ํ ๋ฒ์ dispose ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
DisposeBag ์ด Dispose() ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฑฐ๋, DisposeBag ์ด ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋ ๋, DisposeBag ์ ํฌํจ๋ Disposable ๊ฐ์ฒด๋ค์ด ํจ๊ป ํด์ ๋ฉ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ViewController ๋ ViewModel ์์ DisposeBag ์ ์ฌ์ฉํ๊ฒ ๋๋๋ฐ, ํด๋น ๊ฐ์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋ ๋ DisposeBag ๋ ํจ๊ป ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
4. Subject, Driver, Relay
1) Observable ๊ณผ Subject ์ ์ฐจ์ด๋ฅผ ์ค๋ช
ํด์ฃผ์ธ์
Observable ์ Cold Observable ์ด๊ณ , Subject ๋ Hot Observable ์ ๋๋ค.
Subject ๋ Observer ์ ์ญํ ๊ณผ Observable ์ ์ญํ ์ ๋ชจ๋ ํ ์ ์์ต๋๋ค.
์ฆ, Observable ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฒคํธ๋ฅผ ๋ฐํํ ์ ์๊ณ ,
Observer ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฒคํธ๋ฅผ ์์ ๋ฐ๊ณ , ๊ทธ ์ด๋ฒคํธ์ ๋ง๋ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์์ต๋๋ค.
๋ค์๋งํ๋ฉด, Observer ๋ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ์ง ๋ฏธ๋ฆฌ ์ ํด์ง ํํ์ ์คํธ๋ฆผ์ด์ง๋ง, Subject ๋ Subject ์ธ๋ถ์์ ์๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ค ์๋ ์๊ณ , ๊ตฌ๋ ๋ ํ ์ ์๋ ์ ์ฐ์ฑ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
// ์์ ์ฝ๋ 1 : Observable ๊ณผ Subject ์ ๋์ ์ฐจ์ด
// Observable
let observable = Observable<Int>.create { observer in
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onCompleted()
return Disposables.create()
}
observable.subscribe(onNext: { value in
print(value)
})
// Subject
let subject = PublishSubject<Int>()
subject.onNext(1)
subject.onNext(2)
subject.onNext(3)
subject.subscribe(onNext: { value in
print(value)
})
// ์์ ์ฝ๋ 2 : ์ Subject ๊ฐ Observer ์ Observable ์ ์ญํ ์ ๋ชจ๋ ํ๋ค๊ณ ํ๋๊ฐ.
import RxSwift
// Observable ๋ก์ "initial value" ๋ฐฉ์ถ
let subject = BehaviorSubject(value: "initial value")
// ์๋ก์ด ๊ฐ์ ์๋์ผ๋ก ์ฝ์
-> Observer ๋ก์ "new value" ๋ผ๋ ๊ฐ์ ์์ ํ์
subject.onNext("new value")
subject.subscribe(onNext: { value in
print("Received value: \(value)")
})
// ์๋ก์ด ๊ฐ์ ์๋์ผ๋ก ์ฝ์
subject.onNext("another value")
/* ์ถ๋ ฅ ๊ฒฐ๊ณผ
Received value: new value
Received value: another value
*/
2) Subject์ ์ข
๋ฅ์ ์ฐจ์ด์ ์ ๋ํด ์ค๋ช
ํ์์ค.
PublishSubject ์ BehaviorSubject ์ ๋ํด ์ค๋ช ํด๋ณด๊ฒ ์ต๋๋ค.
๊ฐ์ฅ ํฐ ์ฐจ์ด๋ ์ด๊ธฐ๊ฐ์ด ์๋๋ ์๋๋ ์ธ๋ฐ์, PublishSubject ์ ๊ฒฝ์ฐ, ์๋ก์ด ๊ตฌ๋ ์๊ฐ ์๊ฒผ์ ๋ , ์ต๊ทผ์ ๋ฐ์ํ๋ ์ด๋ฒคํธ์ ๊ฐ์ ์ ๋ฌํ์ง ์์ต๋๋ค. ๋ฐ๋ฉด์ BehaviorSubject ๋ ์๋ก์ด ๊ตฌ๋ ์๊ฐ ์๊ฒผ์ ๋, ์ต๊ทผ์ ๋ฐ์ํ๋ ์ด๋ฒคํธ์ ๊ฐ์ ์ ๋ฌํฉ๋๋ค.
3) Subject์ Driver์ ์ฐจ์ด๋ฅผ ์ค๋ช
ํ์์ค.
Subject ์ Driver ๋ ๋ชจ๋ RxCocoa ์ Observable ์ด์ง๋ง, ๋ช๊ฐ์ง ์ฐจ์ด์ ์ด ์์ต๋๋ค.
Subject ๋ Observer ์ Observable ์ ์ญํ ์ ๋ชจ๋ ์ํํ ์ ์๋ ํด๋์ค์ ๋๋ค.
Observable ์ฒ๋ผ ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ ์ ์์ง๋ง, ์ธ์ ๋ ์ง ์๋์ผ๋ก ์ด๋ฒคํธ๋ฅผ ์๋ก ์์ ๋ฐ์ ์์ฑํ ์ ์๊ธฐ ๋๋ฌธ์ ์ ์ฐํฉ๋๋ค.
Driver ๋ UI ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ค๊ณ๋ Observable ์ ๋๋ค. UI ์ด๋ฒคํธ๋ ๋ฉ์ธ ์ค๋ ๋์์ ์๋ํด์ผ ํ๋ฏ๋ก, Driver ๋ ์๋์ผ๋ก MainScheduler ์์ ์๋๋ฉ๋๋ค.
๋ํ Driver ๋ error ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ์ง ์์ผ๋ฉฐ, ๊ตฌ๋ ์ด ํด์ ๋๊ธฐ ์ ๊น์ง ํญ์ ๋ฉ๋ชจ๋ฆฌ์ ์กด์ฌํฉ๋๋ค.
4) Subject ์ Relay ์ ์ฐจ์ด๋ฅผ ์ค๋ช
ํด์ฃผ์ธ์.
๊ณตํต์ ์ผ๋ก๋ ๋ ๋ค RxCocoa ์ ํฌํจ๋์๊ณ , Observer ์ ์ญํ ๊ณผ Observable ์ ์ญํ ์ ์ํํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค.
์ฆ, ์ด๋ฒคํธ์ ๋ฐํ๋ ํ ์ ์๊ณ , ์ด๋ฅผ ๊ตฌ๋ ํด ์ด๋ฒคํธ์ ๊ฑธ๋ง๋ ํ๋ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์์ต๋๋ค.
์ฐจ์ด์ ์ฒซ๋ฒ์งธ๋ก๋, Subject ๋ RxSwift ์ ํด๋์ค์ด๊ณ , Relay ๋ RxCocoa ์ ํด๋์ค๋ผ๋ ๊ฒ์ ๋๋ค.
๋๋ฒ์งธ๋ก๋, Subject ๋ completed ๋ error ๋ฅผ ํตํด์ ์คํธ๋ฆผ์ ์ข ๋ฃ์ํค์ง๋ง, Relay ๋ Dispose ๊ฐ ๋๊ธฐ ์ ๊น์ง ๊ณ์ ๋์ํฉ๋๋ค.
์ธ๋ฒ์งธ๋ก๋, Subject ์ ๋ฐ์ดํฐ ์คํธ๋ฆผ ๊ฐ ์ถ๋ ฅ์ ๊ตฌ๋ ์ ํตํด ๊ฐ๋ฅํ๊ณ , Relay ์ ๋ฐ์ดํฐ ์คํธ๋ฆผ ๊ฐ ์ถ๋ ฅ์ .value ๋ฅผ ํตํด์ ๊ฐ๋ฅํฉ๋๋ค.
5) Driver ์ Relay ์ ์ฐจ์ด๋ฅผ ์ค๋ช
ํด์ฃผ์ธ์.
Driver ๋ MainScheduler ์์ ํ๋ํ๋ ๊ฒ์ ๋ณด์ฅํ๊ณ , Relay ๋ ๊ทธ๋ ์ง ์์ต๋๋ค.
๋ฐ๋ผ์ UI ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ ๋ Driver ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข ๋ ์ ์ ํ๊ณ , Relay ๋ ๋น UI ์ด๋ฒคํธ์์๋ ๊ฐ๋จํ๊ฒ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํ๊ธฐ ์ข์ต๋๋ค.
https://velog.io/@heyksw/iOS-%EB%A9%B4%EC%A0%91-%EC%A4%80%EB%B9%84#-rxswift-%EA%B4%80%EB%A0%A8
Last updated