์๋ ํ์ธ์ ์ ์ธ์ ๋๋ค : )
์ฐธ ์ค๋๋ง์ RxSwift ๊ฒ์๊ธ ์ฐ๊ฒ ๋์์ต๋๋ค.. ๋ฌธ ๋ซ์๊ฑฐ ์๋๊ตฌ์ ์ ์์์ ํ๋ ค๊ตฌ์.. ๋ค..
์ฌ์ค ๊ทธ๋์ RxSwift ๊ณต๋ถ๋ฅผ ์์ ์ํ ๊ฒ์ ์๋๋ฐ์.. ๋ญ๊ฐ ๊ฒ์๊ธ์ ์ธ ๋ ํ์คํ ์ ๋ณด๋ฅผ ์ ๋ฌํด์ผํ๋ค๋ ์๊ฐ์ ์ข ๋ ๊ณต๋ถํ๊ณ ์ ๋ฆฌํด์ ์ฌ๋ฆฌ์ ์ข ๋ ํ๊ณ ... ํ๋ค๊ฐ ์ด๋ ๊ฒ ๋ฏธ๋ฃจ๊ฒ ๋ ๊ฒ ๊ฐ๋ค์ ํํซ
์ด์ ๋ ์ด์ ๋ฏธ๋ฃฐ ์ ์๋ค! ๋ง์ด ๋ถ์กฑํด๋ ๊ธ๋ก ์ ๋ฆฌํ๋ฉด์ ํ์คํ ์ดํดํ๋ ๋ถ๋ถ๋ค์ด ๋ง์ ๊ฒ ๊ฐ๊ธฐ๋ ํ๊ณ , ์ต๊ทผ์ ํ๋ก์ ํธ์์ RxSwift๋ฅผ ์ด์ฉํด ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ ์ผ์ด ๋ง์๋ฐ ์ ํํ ์์ง ๋ชปํ๋ ๋ถ๋ถ์ด ๋ง๋ค๊ณ ๋๊ผ์ต๋๋ค.. ๊ทธ๋์ ์ ๋๋ก ์๊ณ ์ฝ๋๋ฅผ ์ง๊ณ ์ถ์ด์ ๋ค์ RxSwift ๊ณต๋ถ๋ฅผ ์ด์ฌํํ๋ฉฐ ํฐ์คํ ๋ฆฌ์๋ ์ ๋ฆฌ๋ฅผ ํด๋ณด๋ ค๊ณ ํฉ๋๋ค!
๋ง์ง๋ง์ผ๋ก Observable์ ๋ํด ์ ๋ฆฌํ๋๋ผ๊ตฌ์.. ๊ทธ๋์ Subject๋ถํฐ ๋ค์ ์์ํด๋ณด๊ฒ ์ต๋๋ค ์์ข์ข!
์ด๋ฒ ๊ฒ์๊ธ์ RxSwift: Reactive Programming with Swift ์ฑ ์ Subjects ์ฑํฐ์ ReactiveX ์ ๋ฌธ์๋ฅผ ๋ฒ์ญํ๋ฉด์ Subject์ ๋ํด ์ ๋ฆฌํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
Subject๋?
Subject๋ฅผ ํ๋ง๋๋ก ์ ์ํ์๋ฉด Observable์ด์ Observer์ธ ๊ฒ์ ๋๋ค.
์ด๊ฒ์ด ๋์ฒด ๋ฌด์จ ๋ง์ด๋... ์ง๊ธ๋ถํฐ ์ฐจ๊ทผ์ฐจ๊ทผ ์์๊ฐ๋ด ์๋ค.
Observable์ '๊ด์ฐฐ๊ฐ๋ฅํ ๋ฐ์ดํฐ์ ํ๋ฆ' ์ ๋๋ก ์ ์ํ ์ ์์ผ๋ฉฐ ์ผ์ ๊ธฐ๊ฐ ๋์ ๊ณ์ํด์ ์ด๋ฒคํธ๋ฅผ ์์ฑํ์ฌ ๋ฐฉ์ถํ๋ ๊ฐ์ฒด์ ๋๋ค.
ํ์ง๋ง ์ค์ ์ฑ ๊ฐ๋ฐ์์ ์ผ๋ฐ์ ์ผ๋ก ํ์ํ ๊ฒ์ ์ค์๊ฐ์ผ๋ก Observable์ ์๋ก์ด ๊ฐ์ ์๋์ผ๋ก ์ถ๊ฐํ๊ณ subscriber์๊ฒ ๋ฐฉ์ถํ๋ ๊ฒ์ ๋๋ค. ์ฆ, observable์ด์ observer๋ก ๋์ํ๋ ๋ฌด์ธ๊ฐ๊ฐ ํ์ํ๋ค๋ ๊ฒ์ด์ฃ . ์ฐ๋ฆฌ๊ฐ ํ์ํ ์ด ๋ฌด์ธ๊ฐ๊ฐ ๋ฐ๋ก Subject์ ๋๋ค.
๋ณธ๊ฒฉ์ ์ผ๋ก Subject์ ๋ํด ์์๊ฐ๊ธฐ์ ์์ ๊ฐ๋จํ ์ฝ๋๋ถํฐ ๋ณด๊ณ ์์ํด๋ด ์๋ค!
example(of: "PublishSubject") {
// 1
let subject = PublishSubject<String>()
// 2
subject.onNext("Is anyone listening?")
// 3
let subscriptionOne = subject
.subscribe(onNext: { (string) in
print(string)
})
// 4
subject.on(.next("1")) // Print: 1
// 5
subject.onNext("2") // Print: 2
}
PublishSubject๋ฅผ ์ด์ฉํ ๊ฐ๋จํ ์ฝ๋์ธ๋ฐ์, ์ฃผ์์ ๋ฐ๋ผ๊ฐ๋ฉด์ ์ฝ๋๋ฅผ ์ดํด๋ด ์๋ค.
1. PublishSubject ์์ฑ
๋จผ์ subject๋ผ๋ ์ด๋ฆ์ PublishSubject ๊ฐ์ฒด๋ฅผ ํ๋ ์์ฑํด์ฃผ์๋๋ฐ์,
PublishSubject๋ ์ด๋ฆ์์๋ ์ ์ถํ ์ ์๋ฏ์ด ์ ๋ฌธ ์ถํ์ฌ์ฒ๋ผ ์ ๋ณด๋ฅผ ๋ฐ์ ๊ตฌ๋ ์๋ค์๊ฒ ๋ฐฐํฌํฉ๋๋ค. (PublishSubject์ ๋ํด์๋ ๋ค์์ ๋ ์์ธํ ์ ๋ฆฌํ ๊ฒ์!) ์์ ์ฝ๋์์๋ String ํ์ ์ผ๋ก ์์ฑํ์ผ๋ String ํ์ ์ ๋ณด๋ง ๋ฐ์ ์ ์๊ณ ๋ ๋ฐฐํฌํ ์ ์๊ฒ ์ฃ ?
๊ฐ์ฒด๊ฐ ์ด๊ธฐํ๋์๋ค๋ฉด ์ด์ ์ ๋ณด๋ฅผ ๋ฐ์ ์ค๋น๊ฐ ๋์๋ค๋ ๊ฒ์ ๋๋ค.
2~3. ๊ตฌ๋ ์ ํ์ง ์์ ์ํ๋ผ๋ฉด ๊ฐ์ ์ ๋ฌ๋์ง ์๋๋ค
2๋ฒ ์ฝ๋์์ subject์ ์๋ก์ด ๋ฌธ์์ด ๊ฐ์ด ์ถ๊ฐ๋์์ต๋๋ค. ํ์ง๋ง, ์ด ์ฝ๋๋ ํ๋ฆฐํธ๋์ง ์์ต๋๋ค.
์๋ํ๋ฉด ์์ง observer๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ทธ๋์ 3๋ฒ์์ subject๋ฅผ subscribe ํด์ฃผ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ ํ ์๋ฌด๊ฒ๋ ์ถ๋ ฅ๋์ง ์์ต๋๋ค.
์ ๊ตฌ๋ ์ ํ๋๋ฐ๋ ์ถ๋ ฅ์ด ๋์ง ์๋๋ฉด! PublishSubject๋ ์ค์ง ํ์ฌ์ subscriber์๊ฒ๋ง ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํฉ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ด๋ฒคํธ๊ฐ ์ถ๊ฐ๋์์ ๋ ๊ตฌ๋ ์ ํ์ง ์๊ณ ์์๋ค๋ฉด ๊ตฌ๋ ํ ์ดํ์๋ ๊ทธ ๊ฐ์ ๋ฐ์ ์ ์์ต๋๋ค.
4~5. ๊ตฌ๋ ์ดํ ์ถ๊ฐ๋ ๊ฐ ๋ด๋ณด๋ด๊ธฐ
์ด์ ๊ตฌ๋ ์ ํ์ผ๋ ์ดํ์ ์ถ๊ฐ๋๋ ๊ฐ๋ค์ ๋ชจ๋ ์ ๋ฌ๋ฐ์ ์ ์๊ฒ ์ฃ ??
๋น์ฐํ ์ด์ผ๊ธฐ๊ฒ ์ง๋ง subject๋ฅผ String ํ์ ์ผ๋ก ์ ์ธํ๊ธฐ ๋๋ฌธ์ ์ถ๊ฐ๋๋ next ์ด๋ฒคํธ ๋ด์ ๊ฐ์ String ํ์ ์ด์ด์ผ๋ง ํฉ๋๋ค! .on(.next(_:))๋ subscribe ์ฐ์ฐ์์ ์ ์ฌํ ๋ฐฉ์์ผ๋ก ์๋ก์ด next ์ด๋ฒคํธ๋ฅผ subject์ ์ถ๊ฐํ๊ณ , ์ด๋ฒคํธ ๋ด์ ๊ฐ๋ค์ ํ๋ผ๋ฏธํฐ๋ก ํต๊ณผ์ํค๋ ์ฐ์ฐ์์ ๋๋ค. ์ด ์ฐ์ฐ์๋ subscribe์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ถ์ฝํ์ด ์กด์ฌํฉ๋๋ค. 5๋ฒ ์ฝ๋์ ๊ฐ์ด .onNext(_:)๋ก ์ถ์ฝํด์ ํจ์ฌ ๋ ๋ณด๊ธฐ ํธํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค! ์ด์ ์ถ๊ฐ๋ ๊ฐ์ด ๋ชจ๋ ํ๋ฆฐํธ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
Subject์ ์ข ๋ฅ
Subject๋ observable์ธ ๋์์ observer์ธ ๊ฒ์ ๋๋ค.
์์์ ๊ฐ๋จํ ์ฝ๋๋ฅผ ํตํด์ subject๊ฐ ์ด๋ป๊ฒ ์ด๋ฒคํธ๋ฅผ ๋ฐ๋์ง(observer์ ์ญํ ), ๊ทธ๋ฆฌ๊ณ ์ด๋ป๊ฒ ๊ตฌ๋ ๋๋์ง(observable์ ์ญํ )๋ฅผ ์ดํด๋ณด์์ต๋๋ค. next ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ ์ด๊ฒ์ ๋ค์ subscriber์๊ฒ ๋ฐฉ์ถํ๋ ๊ณผ์ ์ ๊ฐ๋จํ ์ดํด๋ณด์๋๋ฐ subject์ ๋ํด ์กฐ๊ธ ์ดํด๊ฐ ๊ฐ์๋์??? ์ด์ Subject์ ์ข ๋ฅ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค!
RxSwift์๋ 4๊ฐ์ง ์ข ๋ฅ์ Subject๊ฐ ์์ต๋๋ค.
- PublishSubject: ๋น ์ํ๋ก ์์ํ์ฌ ์๋ก์ด ๊ฐ๋ง์ subscriber์ ๋ฐฉ์ถํฉ๋๋ค.
- BehaviorSubject: ์ด๊ธฐ๊ฐ์ ๊ฐ์ง ์ํ๋ก ์์ํ์ฌ, ์๋ก์ด subscriber์๊ฒ ์ด๊ธฐ๊ฐ ๋๋ ์ต์ ๊ฐ์ ๋ฐฉ์ถํฉ๋๋ค.
- ReplaySubject: ์ ํด์ง ๋ฒํผ ์ฌ์ด์ฆ๋ฅผ ๊ฐ์ง ์ฑ๋ก ์ด๊ธฐํ๋๊ณ ๋ฒํผ ์ฌ์ด์ฆ ๋งํผ์ ๊ฐ๋ค์ ์ ์งํ๋ฉด์ ์๋ก์ด subscriber์๊ฒ ๋ฐฉ์ถํฉ๋๋ค.
- AsyncSubject: subject๊ฐ completed ์ด๋ฒคํธ๋ฅผ ๋ฐ์ ๋๋ง ์ํ์ค์ ๋ง์ง๋ง next ์ด๋ฒคํธ๋ง์ ๋ฐฉ์ถํฉ๋๋ค. (๊ฑฐ์ ์ฌ์ฉ๋์ง ์๋ Subject์ด๊ธฐ ๋๋ฌธ์ raywenderich ์ฑ ์์ ๋ค๋ฃจ์ง ์๋๋ค๊ณ ํฉ๋๋ค)
ํ๋์ฉ ์์ธํ ์ดํด๋ด ์๋ค!
PublishSubject
PublishSubject๋ ๊ตฌ๋ ๋ ์๊ฐ ๊ตฌ๋ ์๋ค์๊ฒ ์๋ก์ด ์ด๋ฒคํธ ์์ ์ ์๋ฆฌ๊ณ ์ถ์ ๋ ์ฉ์ดํฉ๋๋ค.
์ด๋ ๊ตฌ๋ ์ ๋ฉ์ถ๊ฑฐ๋ ํน์ subject๊ฐ completed๋ error ์ด๋ฒคํธ๋ก ์ข ๋ฃ๋ ๋๊น์ง ์ง์๋ฉ๋๋ค.
์์ ๊ทธ๋ฆผ์์ ๋งจ ์์ค์ด PublishSubject๋ฅผ ๋ํ๋ธ ๊ฒ์ด๊ณ , ๊ทธ ์๋ ๋ ์ค์ด ๊ตฌ๋ ์๋ค์ ๋๋ค.
์๋ก ํฅํ๋ ํ์ดํ๋ค์ ๊ตฌ๋ ์ ๋ํ๋ด๊ณ , ์๋๋ก ํฅํ๋ ํ์ดํ๋ค์ ์ด๋ฒคํธ์ ๋ฐฉ์ถ์ ๋ํ๋ด๋ ๊ฒ์ธ๋ฐ์,
๋๋ฒ์งธ ์ค์์๋ 1๋ฒ์ด ์ถ๊ฐ๋ ์ดํ์ ๊ตฌ๋ ์ ํ๊ธฐ ๋๋ฌธ์ ๊ตฌ๋ ์์ ์ดํ์ ๋ฐฉ์ถ๋๋ 2, 3 ์ด๋ฒคํธ๋ง์ ๋ฐ๋ ๊ฒ์ ํ์ธํ ์ ์์ผ๋ฉฐ, ๋ง์ง๋ง ์ค์์๋ 2๋ฒ๊น์ง ์ถ๊ฐ๋ ์ดํ์ ๊ตฌ๋ ํ๊ธฐ ๋๋ฌธ์ 3๋ฒ ์ด๋ฒคํธ๋ง์ ๋ฐ์ ๊ฒ์ ์ ์ ์์ต๋๋ค.
์ฝ๋๋ก ํ ๋ฒ ์ดํด๋ด ์๋ค!
example(of: "PublishSubject") {
let subject = PublishSubject<String>()
subject.onNext("Is anyone listening?")
// ์ฒซ๋ฒ์งธ subscriber
let subscriptionOne = subject
.subscribe(onNext: { (string) in
print(string)
})
subject.on(.next("1"))
subject.onNext("2")
// 1
// ๋๋ฒ์งธ subscriber
let subscriptionTwo = subject
.subscribe({ (event) in
print("2)", event.element ?? event)
})
// 2
subject.onNext("3")
// Print: 3
// Print: 2) 3
// 3
subscriptionOne.dispose()
subject.onNext("4")
// Print: 2) 4
// 4
subject.onCompleted()
// Print: 2) completed
// 5
subject.onNext("5")
// 6
subscriptionTwo.dispose()
let disposeBag = DisposeBag()
// 7
subject
.subscribe {
print("3)", $0.element ?? $0)
}
.disposed(by: disposeBag)
// Print: 3) completed
subject.onNext("?")
}
์ฒ์์ ์์ํ๋ฉด์ ๋ดค์๋ ์ฝ๋ ์๋ ๋ถํฐ ์ฃผ์์ ๋ฐ๋ผ๊ฐ๋ฉด์ ์ดํด๋ณผ๊ฒ์!
1. ๋๋ฒ์งธ subscriber ์ถ๊ฐ
subscriptionTwo๋ผ๋ ์ด๋ฆ์ผ๋ก ๋๋ฒ์งธ ๊ตฌ๋ ์๋ฅผ ์ถ๊ฐํด์ฃผ์์ต๋๋ค.
์ด๋ฒคํธ๋ค์ ์ต์ ๋ ๊ฐ์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ์ด ๊ฐ๋ค์ next ์ด๋ฒคํธ๋ก ๋ฐฉ์ถ๋๊ธฐ ๋๋ฌธ์ nil ๋ณํฉ ์ฐ์ฐ์๋ฅผ ์ด์ฉํ์ฌ nil์ด ์๋๋ผ๋ฉด ๊ฐ์ด ํ๋ฆฐํธ๋๋๋กํ๊ณ nil์ด๋ผ๋ฉด ์ด๋ฒคํธ๋ง ํ๋ฆฐํธ๋๋๋ก ํด์ฃผ์์ต๋๋ค.
2. ๊ตฌ๋ ์๊ฐ ๋ ๋ช ์ธ ์ํ์์ subject์ ์๋ก์ด ๊ฐ ์ถ๊ฐ
subject์ "3"์ด๋ผ๋ ๊ฐ์ ์ถ๊ฐํด์ฃผ์์ต๋๋ค.
ํ์ฌ ๊ตฌ๋ ์๊ฐ subscriptionOne, subscriptionTwo ๋ ๋ช ์ด๊ธฐ ๋๋ฌธ์ 3์ด๋ผ๋ ๊ฐ์ ๊ตฌ๋ ์๋ค์ ์ํด ํ ๋ฒ์ฉ ์ถ๋ ฅ๋์ด ์ด ๋ ๋ฒ ํ๋ฆฐํธ๋๊ฒ ๋ฉ๋๋ค.
3
2) 3
3. subscriptionOne ๊ตฌ๋ ์ค๋จ ํ subject์ ์๋ก์ด ๊ฐ ์ถ๊ฐ
.dispose()๋ฅผ ํตํด ์ฒซ๋ฒ์งธ ๊ตฌ๋ ์์ ๊ตฌ๋ ์ ์ค๋จ์์ผฐ์ต๋๋ค. ์ด๋ ๊ฒ ๋๋ฉด ์ด์ ๊ตฌ๋ ์๊ฐ subscriptionTwo ๋ฐ์ ์๊ธฐ ๋๋ฌธ์ ์ดํ ์ถ๊ฐ๋๋ ๊ฐ์ธ "4"๋ ํ ๋ฒ๋ง ์ถ๋ ฅ๋๊ฒ ๋ฉ๋๋ค.
2) 4
4. subject ์ข ๋ฃ
PublishSubject๊ฐ completed๋ error ๊ฐ์ ์ข ๋ฃ ์ด๋ฒคํธ๋ฅผ ๋ฐ๊ฒ ๋๋ค๋ฉด, subject๋ ๋ ์ด์ ๊ตฌ๋ ์๋ค์๊ฒ ์๋ก์ด next ์ด๋ฒคํธ๋ค์ ๋ฐฉ์ถํ์ง ์์ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ฉด ์ด์ ์๋ฌด๊ฒ๋ ์ถ๋ ฅ๋์ง ์๋๋ค๊ณ ์์ํ ์ ์์ต๋๋ค.
ํ์ง๋ง, subject๋ ์ด๋ฌํ ์ข ๋ฃ ์ด๋ฒคํธ๋ค์ ์ดํ ์ subscriber๋ค์๊ฒ ์ฌ๋ฐฉ์ถํฉ๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก completed๊ฐ ์ถ๋ ฅ๋๊ฒ ๋ฉ๋๋ค.
2) completed
5~7. subject ์ข ๋ฃ๋ ์ดํ ์๋ก์ด ๊ตฌ๋ ์ ์ถ๊ฐ
subject๋ completed ์ด๋ฒคํธ๋ฅผ ๋ฐ์ ์ด์ ์ข ๋ฃ๋์์ผ๋ 5๋ฒ์์ ์๋ก์ด ๊ฐ์ด ์ถ๊ฐ๋์ง๋ง ์ด๋ฅผ ๋ฐฉ์ถํ์ง๋ ์์ต๋๋ค.
6๋ฒ์์๋ ๋ ๋ฒ์งธ ๊ตฌ๋ ์๊ฐ ๊ตฌ๋ ์ ์ค๋จํ๊ณ 7๋ฒ์์๋ ์๋ก์ด ๊ตฌ๋ ์๊ฐ ์๊ธฐ๊ฒ ๋๋๋ฐ์, subject๋ ์ด๋ฏธ ์ข ๋ฃ๋ ์ํ์์ ์๋ก์ด subscriber๊ฐ ์๊ธด๋ค๊ณ ํด์ ์ข ๋ฃ๋ subject๊ฐ ๋ค์ ์๋ํ์ง๋ ์์ต๋๋ค. ๋ค๋ง, .completed ์ด๋ฒคํธ๋ง์ ๋ฐฉ์ถํฉ๋๋ค.
3) completed
์ด๋ฅผ ํตํด subject๊ฐ ์ข ๋ฃ๋์์ ๋ ๊ธฐ์กด์ ์กด์ฌํ๋ ๊ตฌ๋ ์๋ค์๊ฒ๋ง ์ข ๋ฃ ์ด๋ฒคํธ๋ฅผ ์ ๋ฌํ ๋ฟ๋ง ์๋๋ผ ๊ทธ ์ดํ์ ๊ตฌ๋ ํ subscriber์๊ฒ๋ ์ข ๋ฃ ์ด๋ฒคํธ๋ฅผ ์๋ ค์ค๋ค๋ ํน์ง์ด ์๋ค๋ ๊ฒ์ ์ ์ ์์์ต๋๋ค. ์ด๊ฒ์ด ๋๋๋ก ๋ฒ๊ทธ์ ์์ธ์ด ๋ ์ ์์ผ๋ ์ฃผ์ํด์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค!
BehaviorSubject
BehaviorSubject๋ ๋ง์ง๋ง next ์ด๋ฒคํธ๋ฅผ ์๋ก์ด ๊ตฌ๋ ์์๊ฒ ๋ฐ๋ณตํ๋ค๋ ์ ๋ง ๋นผ๋ฉด PublishSubject์ ์ ์ฌํฉ๋๋ค.
์์ ๊ทธ๋ฆผ์ ํตํด ํ ๋ฒ์ ์ดํดํ ์ ์์ ๊ฒ ๊ฐ์๋ฐ์, ์ฒซ ์ค์ด BehaviorSubject์ด๊ณ ๊ทธ ์๋ ๋ ์ค์ด subscriber๋ค์ ๋๋ค!
์ฒซ๋ฒ์งธ ๊ตฌ๋ ์์ธ ๋๋ฒ์งธ ์ค์ 1๋ฒ ์ด๋ฒคํธ๊ฐ ๋ฐ์๋ ์ดํ์ ๊ตฌ๋ ์ ์์ํ๋๋ฐ, ๊ตฌ๋ ์ฆ์ ๋ง์ง๋ง ์ด๋ฒคํธ์ธ 1์ ๋ฐ๊ณ ์ดํ์ ๋ฐฉ์ถ๋๋ ๊ฐ๋ค์ ๋ฐ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ๋ง์ง๋ง ์ค๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ตฌ๋ ์ ์์ํ ๋ ๊ตฌ๋ ์ ์ ๋ง์ง๋ง ์ด๋ฒคํธ๋ฅผ ๋ฐ์ต๋๋ค.
์ด์ ์ฝ๋๋ฅผ ํตํด ์ดํด๋ด ์๋ค!
// 1
enum MyError: Error {
case anError
}
// 2
func print<T: CustomStringConvertible>(label: String, event: Event<T>) {
print(label, event.element ?? event.error ?? event)
}
//3
example(of: "BehaviorSubject") {
// 4
let subject = BehaviorSubject(value: "Initial value")
let disposeBag = DisposeBag()
}
1. ์๋ฌ ํ์ ์ ์
๋ฐ์ํ ์ ์๋ ์๋ฌ๋ฅผ Error enum์ผ๋ก ๋ง๋ค์ด์ค๋๋ค.
2. print ํจ์ ์ ์
Generic ๋ฌธ๋ฒ์ ์ฌ์ฉํด ์ด๋ฒคํธ ๋ด์ ๊ฐ์ด ์์ผ๋ฉด ๊ฐ์ ํ๋ฆฐํธํ๊ณ , ์๋ฌ๊ฐ ์์ผ๋ฉด ์๋ฌ๋ฅผ, nil์ด๋ผ๋ฉด ์ด๋ฒคํธ๋ง์ ์ถ๋ ฅํ ์ ์๋ print ๋ฉ์๋๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
3~4. BehaviorSubject ๊ฐ์ฒด ์์ฑ
์๋ก์ด BehaviorSubject ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
BehaviorSubject๋ ํญ์ ์ต์ ์ ๊ฐ์ ๋ฐฉ์ถํ๊ธฐ ๋๋ฌธ์ ๋ฐ๋์ ์ด๊ธฐ๊ฐ์ ๊ฐ์ ธ์ผ ํฉ๋๋ค!
4๋ฒ์ ํ๋จ์ ์๋์ ์ฝ๋๋ฅผ ์ถ๊ฐํด๋ด ์๋ค.
// 6
subject.onNext("X")
// 5
subject
.subscribe{
print(label: "1)", event: $0)
}
.disposed(by: disposeBag)
// 7
subject.onError(MyError.anError)
// 8
subject
.subscribe {
print(label: "2)", event: $0)
}
.disposed(by: disposeBag)
5. ์์ฑํ subject๋ฅผ ๊ตฌ๋ ํ๊ณ dispose
1) Initial value
์์์ ์์ฑํ subject๋ฅผ ๊ตฌ๋ ํ๋ฉด, subject ์์ฑ ์ดํ ๋ค๋ฅธ ๊ฐ์ด ์ถ๊ฐ๋์ง ์์๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ด ์ด๊ธฐ๊ฐ์ด ํ๋ฆฐํธ ๋ฉ๋๋ค.
6. subject๋ฅผ ๊ตฌ๋ ํ๊ธฐ ์ ์ ์๋ก์ด ๊ฐ์ ์ถ๊ฐํ๋ค๋ฉด
1) X
5๋ฒ ์ฝ๋ ์๋จ์ subject์ "X"๋ฅผ ๊ฐ์ง .onNext(_:) ๋ฉ์๋๋ฅผ ์ถ๊ฐํด๋ด ์๋ค. ์ด๋ ๊ฒ ๋๋ฉด subject๋ฅผ ๊ตฌ๋ ํ๊ธฐ ์ ์ต์ ์ ๊ฐ์ด "X"๊ฐ ๋๊ธฐ ๋๋ฌธ์ ์ด๊ธฐ๊ฐ์ธ Initial Value๊ฐ ์๋๋ผ X๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
7~8. subject์ error ์ด๋ฒคํธ ์ถ๊ฐ ํ ๊ตฌ๋ ํ๊ธฐ
1) anError
2) anError
subject์ error ์ด๋ฒคํธ๋ฅผ ์ถ๊ฐํ๊ณ ์๋ก์ด ๊ตฌ๋ ์๋ฅผ ์ถ๊ฐํด์ฃผ์์ต๋๋ค.
์ด๋ ๊ฒ ๋๋ฉด ๋ ๋ช ์ ๊ตฌ๋ ์์ ์ํด error ์ด๋ฒคํธ๊ฐ ํ ๋ฒ์ฉ ์ฐํ ์ด ๋ ๋ฒ ์ถ๋ ฅ๋๊ฒ ๋ฉ๋๋ค.
BehaviorSubject์ ๊ฒฝ์ฐ ๋ทฐ๋ฅผ ์ต์ ๋ฐ์ดํฐ๋ก ๋ฏธ๋ฆฌ ์ฑ์ฐ๋ ค๋ ๊ฒฝ์ฐ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค!
์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ํ๋กํ ํ๋ฉด์ ์ปจํธ๋กค์ BehaviorSubject์ ๋ฐ์ธ๋ฉํ์ฌ ์ฑ์ด ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋์ ์ต์ ๊ฐ์ ์ฌ์ฉํ์ฌ ๋ทฐ๋ฅผ ๋ฏธ๋ฆฌ ์ฑ์ ๋์ ์ ์์ต๋๋ค.
ReplaySubject
ReplaySubject๋ ์์ฑ ์ ์ค์ ํ ํน์ ์ฌ์ด์ฆ๊น์ง, ๋ฐฉ์ถํ๋ ์ต์ ์์๋ฅผ ์ผ์์ ์ผ๋ก cacheํ๊ฑฐ๋ bufferํ๊ณ ํด๋น ๋ฒํผ๋ฅผ ์๋ก์ด ๊ตฌ๋ ์์๊ฒ ๋ฐฉ์ถํฉ๋๋ค.
์์ ๊ทธ๋ฆผ์์ ์ฒซ๋ฒ์งธ ์ค์ด ๋ฒํผ ์ฌ์ด์ฆ๊ฐ 2์ธ ReplaySubject, ๊ทธ ์๋ซ์ค๋ค์ ๊ตฌ๋ ์๋ค์ ๋๋ค.
์ฒซ๋ฒ์งธ ๊ตฌ๋ ์(์ค๊ฐ์ค)๋ ์ด๋ฏธ subject๋ฅผ ๊ตฌ๋ ํ๊ณ ์๋ ์ํ์ด๊ธฐ ๋๋ฌธ์ 1๊ณผ 2๊ฐ ๋ฐฉ์ถ๋๋ฉด ์ด๋ค์ ๋ฐ์ต๋๋ค.
๋๋ฒ์งธ ๊ตฌ๋ ์(๋ง์ง๋ง์ค)๋ 2๊ฐ ๋ฐฉ์ถ๋ ์ดํ ๊ตฌ๋ ํ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ฒํผ ์ฌ์ด์ฆ์ธ 2๋งํผ์ ๊ฐ์ ๋ฐ๊ฒ ๋์ด ๊ตฌ๋ ์ด์ ์ ๋ฐฉ์ถ๋ 1๊ณผ 2๋ฅผ ๋ชจ๋ ๋ฐ๊ฒ ๋ฉ๋๋ค.
์ฃผ์ํด์ผ ํ ์ ์ ReplaySubject์ ๋ฒํผ๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ฐ์ง๊ณ ์๋ค๋ ์ ์ ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ด๋ฏธ์ง๋ ๋ฐฐ์ด๊ณผ ๊ฐ์ด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํฌ๊ฒ ์ฐจ์งํ๋ ๊ฐ๋ค์ ํฐ ์ฌ์ด์ฆ์ ๋ฒํผ๋ก ๊ฐ์ง๋ ๊ฒ์ ๋ฉ๋ชจ๋ฆฌ์ ์์ฒญ๋ ๋ถํ๋ฅผ ์ฃผ๊ฒ ๋ฉ๋๋ค.
์ฝ๋๋ก ์ดํด๋ด ์๋ค.
example(of: "ReplaySubject") {
// 1
let subject = ReplaySubject<String>.create(bufferSize: 2)
let disposeBag = DisposeBag()
// 2
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
// 3
subject
.subscribe {
print(label: "1)", event: $0)
}
.disposed(by: disposeBag)
subject
.subscribe {
print(label: "2)", event: $0)
}
.disposed(by: disposeBag)
}
1. subject ์์ฑ
๋ฒํผ ์ฌ์ด์ฆ๊ฐ 2์ธ ReplaySubject๋ฅผ ์์ฑํฉ๋๋ค. ReplaySubject๋ .create(bufferSize:) ๋ฉ์๋๋ฅผ ์ด์ฉํ์ฌ ์์ฑ ๋ฐ ์ด๊ธฐํ๋ ์ ์์ต๋๋ค.
2. subject์ ์๋ก์ด ๊ฐ ์ถ๊ฐ
์์ฑํ subject์ 1, 2, 3์ด๋ผ๋ ์ธ ๊ฐ์ง ์๋ก์ด ๊ฐ์ ์ถ๊ฐํ์ต๋๋ค.
3. subject ๊ตฌ๋
1) 2
1) 3
2) 2
2) 3
subject์ ๋ํ ๊ตฌ๋ ์๋ค์ ๋ ๊ฐ ์์ฑํ๊ฒ ๋๋ฉด ์์์ ์ถ๊ฐํ ๊ฐ๋ค ์ค ์ด๋ค ๊ฐ์ด ์ถ๋ ฅ๋ ๊น์??
๋ง์ง๋ง 2๊ฐ์ ๊ฐ๋ค์ด ๊ฐ๊ฐ์ ๊ตฌ๋ ์๋ค์ ์ํด ํ ๋ฒ์ฉ ์ถ๋ ฅ๋๊ฒ ๋ฉ๋๋ค. ์๋ํ๋ฉด ๋ฒํผ ์ฌ์ด์ฆ๊ฐ 2์ด๊ธฐ ๋๋ฌธ์ ๋๋ค!
3๋ฒ ์ฝ๋ ํ๋จ์ ์๋์ ์ฝ๋๋ฅผ ์ถ๊ฐํด๋ณด๊ฒ ์ต๋๋ค!
subject.onNext("4")
subject.subscribe {
print(label: "3)", event: $0)
}
.disposed(by: disposeBag)
์๋ก์ด ๊ฐ์ธ "4"๋ฅผ subject์ ์ถ๊ฐํ ํ, ์๋ก์ด ๊ตฌ๋ ์๋ฅผ ์์ฑํด์ฃผ์์ต๋๋ค.
"4"๋ผ๋ ์๋ก์ด ๊ฐ์ด ์ถ๊ฐ๋๋ฉด ๊ธฐ์กด์ ๊ตฌ๋ ์๋ค( 1), 2) )์ ์ด ๊ฐ์ ๋ฐ๊ฒ ๋ ๊ฒ์ด๊ณ , ์๋ก์ด ๊ตฌ๋ ์๋ ๋ฒํผ ์ฌ์ด์ฆ์ธ 2๋งํผ ์ต์ ์ ๊ฐ์ ๋ฐ๊ฒ ๋๋ฏ๋ก ์๋์ ๊ฐ์ด ์ถ๋ ฅ๋๊ฒ ๋ฉ๋๋ค.
1) 4
2) 4
3) 3
3) 4
๊ทธ๋ ๋ค๋ฉด subject๊ฐ error ์ด๋ฒคํธ๋ฅผ ๋ฐ๊ฒ ๋๋ค๋ฉด ์ด๋ป๊ฒ ์ถ๋ ฅ๋ ๊น์??
์๋์ ์ฝ๋๋ฅผ subject.onNext("4") ํ๋จ(์ ๊ตฌ๋ ์ ์์ฑ ์ )์ ์ถ๊ฐํด๋ณด๊ฒ ์ต๋๋ค.
subject.onError(MyError.anError)
/* Prints:
1) 4
2) 4
1) anError
2) anError
3) 3
3) 4
3) anError
*/
subject๊ฐ error๋ฅผ ํตํด ์ข ๋ฃ๋๊ณ ๋ ์ดํ์ ๊ตฌ๋ ์์ธ 3)์๊ฒ error ์ด๋ฒคํธ๋ฅผ ์ฌ์ ์กํ๊ณ ์์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ์ด ๋ 3)์๊ฒ ๋ฒํผ์ ์๋ ๊ฐ๋ค ๋ํ ์ ๋ฌํ๊ณ ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ด๋ฐ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋ ์ด์ ๋ subject๊ฐ ์ข ๋ฃ๋์์ด๋ ๋ฒํผ๋ ์ฌ์ ํ ๋์๋ค๋๊ณ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. error๋ฅผ ์ถ๊ฐํ ๋ค์์ ์ด๋ฒคํธ์ ์ฌ๋ฐฉ์ถ์ ๋ง์ผ๋ ค๋ฉด dispose()๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
subject.dispose()
/* Prints:
3) Object `RxSwift.(ReplayMany in _33052C2CE59F358A8740AFDD4371DD39)<Swift.String>` was already disposed.
*/
์์ ์ฝ๋๋ฅผ ์ถ๊ฐํ๊ฒ ๋๋ฉด, ์๋ก์ด ๊ตฌ๋ ์๋ ์๋ฌ ์ด๋ฒคํธ๋ง ๋ฐ๊ฒ ๋ฉ๋๋ค. ์๋ํ๋ฉด ๊ตฌ๋ ์ ์ subject ์์ฒด๊ฐ dispose ๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ทธ๋ฌ๋, ReplaySubject์ ๋ช ์์ ์ผ๋ก dispose()๋ฅผ ํธ์ถํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ํ์ํ ์์ ์ ์๋๋๋ค.
์๋ํ๋ฉด ๋ง์ฝ subject์ ๊ตฌ๋ ์ disposeBag์ ๋ฃ๊ณ , ViewController๋ ViewModel ๊ฐ์ ํด๋น subject์ ์์ ์๊ฐ ํ ๋น ํด์ ๋๋ฉด ๋ชจ๋ ๊ฒ๋ค์ด dispose ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ฌ๊ธฐ๊น์ง Subject์ ๋ํด ์์๋ณด์๋๋ฐ์.. ํ๋๋ค์...
Subject๋ฅผ ์ดํดํ๋ ๋ฐ ์กฐ๊ธ์ด๋๋ง ๋์์ด ๋์์ผ๋ฉด ์ข๊ฒ ๊ณ ์์ผ๋ก๋ RxSwift ๊ฒ์๊ธ์ ๊พธ์คํ ์ฌ๋ ค๋ณด๋๋ก ๋ ธ๋ ฅํด๋ณด๊ฒ ์ต๋๋ค..ใ
'๐ iOS > RxSwift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[RxSwift] Traits - Driver, Signal, Control Property/ControlEvent (0) | 2023.04.29 |
---|---|
[RxSwift] Traits - Single, Completable, Maybe (0) | 2023.04.17 |
[RxSwift] Relay๋? (0) | 2023.02.17 |
[RxSwift] Observable (0) | 2022.05.02 |
[RxSwift] RxSwift์ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ (7) | 2022.04.07 |