
์๋ ํ์ธ์, ์ด๋ฒ์ RxSwift๋ฅผ ๋ค๋ฃจ๋ฉด์ ์ฝ๊ฒ ํท๊ฐ๋ฆด ์ ์๋
Observable vs Observer vs Subject vs Relay ์ฐจ์ด๋ฅผ ์ ๋ฆฌํด๋ณด๋ ค๊ณ ํฉ๋๋ค!
๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ํ ๋ฐฉ๋ฒ ์ค ํ๋
Asynchronous Programming with Observable Stream
RxSwift๋ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ค ๋น๋๊ธฐ ์ด๋ฒคํธ(๋ฒํผ ํญ, ํค๋ณด๋ ๋ฑ ์ ์ ์ ๋ฐ์)๊ฐ ์์ ๋,
๊ทธ ์ด๋ฒคํธ๋ฅผ ๊ด์ฐฐ ๊ฐ๋ฅํ ํํ๋ก ๋ง๋ค๊ณ (Observable), ๊ทธ ์ด๋ฒคํธ๋ฅผ ๊ด์ฐฐํ๋ ๊ฒ(Observer)์ด ์๋ค๋ฉด ํด๋น ๋ณํ์ ๋ฐ๋ผ ์ด๋ค ๋์์ ์งํํ ์ ์์ต๋๋ค.
์ฆ, Observable๊ณผ Observer๋ฅผ ํตํด ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ์ฌ Stream(๋ฐ์ดํฐ ํ๋ฆ)์ ํต์ ํ ์ ์๊ณ , Operator๋ก Steam์ ๋ณ๊ฒฝ, ์กฐ์ํ ์ ์๋ค๋ ๋ป์ ๋๋ค.
์์ ์ธ๊ธํ๋ฏ์ด Observable์ ๋น๋๊ธฐ ์ด๋ฒคํธ๋ฅผ ๊ด์ฐฐ ๊ฐ๋ฅํ ํํ๋ก ๋ง๋ค์ด์ค๋๋ค.
let emailText = Observable.just("a@a.com")
Observable์ด ๋ง๋ค์ด์ค ๊ด์ฐฐ ๊ฐ๋ฅํ ์ด๋ฒคํธ๋ฅผ ๊ด์ฐฐํ๊ณ ์ฒ๋ฆฌํ๋๊ฒ Observer์ ๋๋ค.
Observer๋ ์ด๋ป๊ฒ ๊ด์ฐฐํ๋๊ฑธ๊น์?
๋ฐ๋ก Observable๋ฅผ ๊ตฌ๋ (Subscribe)ํด์ ๊ด์ฐฐํ ์ ์์ต๋๋ค.
๋ง์ฝ ๊ด์ฐฐ์ ๊ทธ๋ง๋๊ณ ์ถ๋ค๋ฉด ๊ตฌ๋
์ทจ์(disposeBag)๋ฅผ ํ๋ฉด ๋ฉ๋๋ค.
dispose๋ Subscribe ์ค์ธ Stream์ ์ํ๋ ์๊ธฐ์ ์ ๋ฆฌํ๋๋ก ํด์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํด์ค๋๋ค.
emailText.subscribe(with: self) { owner, value in
owner.emailTextField.text = value
} onError: { error in
print("onError")
} onCompleted: {
print("onCompleted")
} onDisposed: {
print("onDisposed")
}
.disposed(by: disposeBag)
์ด๋ฒคํธ๋ 3๊ฐ์ง ์ข ๋ฅ๋ก ๋๋ ์ง๋ฉฐ Observer๋ ์ด์ ๋ํด ๊ฐ๊ฐ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
Observable์ Next ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ๊ณ โ Error ํน์ Completed ์ด๋ฒคํธ๋ฅผ ๋ง๋๊ฒ ๋๋ฉด ์ข ๋ฃ๊ฐ ๋๊ณ โ ์ข ๋ฃ๋๋ฉด disposed๋ฅผ ํธ์ถํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์ ๋ฆฌ
์์ผ๋ก ์ฌ์ดํด์ด ๋์๊ฐ๊ฒ ๋ฉ๋๋ค.
ํ์ง๋ง UI ๊ด๋ จ ์ด๋ฒคํธ๋ ๋์ฝ๋ฉ ์คํจ, ์ํ ์ฝ๋ ์ค๋ฅ ๊ฐ์ Error ์ด๋ฒคํธ๊ฐ ๋ ์ผ์ด ์๋๋ฐ ๊ตณ์ด ์ฒ๋ฆฌํด์ผํ ๊น์? ๊ทธ๋ด ํ์๊ฐ ์์ฃ .
๊ทธ๋์ ๊ฐ ์ ๋ฌ๋ง ํ๋ Next ์ด๋ฒคํธ๋ง ์ฒ๋ฆฌํ ์ ์๊ณ , Next ์ด๋ฒคํธ๋ง ์ฒ๋ฆฌํ๊ฒ๋ ๊ฐ์ ํ ์๋ ์์ต๋๋ค.
์ด๋ ๋ค์์ Subscribe vs Bind vs Drive ์ฐจ์ด๋ฅผ ์ ๋ฆฌํ๋ฉด์ ๋ค๋ค๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด๋ฒคํธ๋ฅผ ๋ณด๋ด๋ฉด์ ๋์์ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
Observable์ ์ด๋ฒคํธ๋ฅผ ๋ณด๋ด๊ธฐ๋ง ํ ์ ์๊ณ , Observer๋ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌ๋ง ํ ์ ์๋ ์์ฌ์์ด ์๋๋ฐ ์ด๋ฅผ ๋ณด์ํ ์ ์์ฃ .
Subject์๋ 4๊ฐ์ง ์ข ๋ฅ๊ฐ ์์ต๋๋ค.
let num = BehaviorSubject(value: 0)
let number = PublishSubject<Int>()
๊ฐ์ฅ ํฐ ์ฐจ์ด๋ ์ด๊ธฐ๊ฐ์ด ์๋ ์๋๋ ์์ง๋ง,
Subscribe ์ด์ ์ emitํ ์ด๋ฒคํธ๋ฅผ ๋ฐ์ ์ ์๋ ์๋๊ฐ ํฝ๋๋ค.
BehaviorSubject์ธ ๊ฒฝ์ฐ, Subscribe ์ด์ ์ onNext ๋ก Next ์ด๋ฒคํธ๋ฅผ ๋ฐ๊ฒ๋๋ฉด ๊ฐ์ฅ ์ต๊ทผ์ ์ ๋ฌ๋ ์ด๋ฒคํธ ํ๋๋ฅผ ๋ฐ์ ์ ์์ต๋๋ค.
PublishSubject๋ Subscribe ์ด์ ์ ์ด๋ฒคํธ๋ค์ ๋ชจ๋ ๋ฌด์๋ฉ๋๋ค.
์๋ฅผ ๋ค๋ฉด TextField์ text๋ฅผ Subject๊ฐ ๊ด์ฐฐํ์ฌ 2๊ธ์ ๋ฏธ๋ง์ธ ๊ฒฝ์ฐ ๊ฒฝ๊ณ ์ฐฝ์ ๋์ด๋ค๊ณ ํด๋ด ์๋ค.
TextField์ text ์ค orEmtpy๋ text๊ฐ ๋ณํ ๋๋ง๋ค ๊ฐ์ ๋ณด๋ด์ฃผ๋ ์ด๋ฒคํธ์ธ๋ฐ์, ํน์ง์ ํด๋น TextField๊ฐ ์๋ ๋ทฐ๊ฐ ๋ก๋๋์๋ง์ ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ์ฌ ๋งจ ์ฒ์์ ํญ์ ๋น ๊ฐ์ด ๋ค์ด์ต๋๋ค.
๋ง์ฝ ์ด text๋ฅผ BehaviorSubject๊ฐ ๊ด์ฐฐํ๋ค๋ฉด ๋น๊ฐ์ด ๋ค์ด์ด๊ณผ ๋์์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์ ๋์์ ํ๊ฒ ๋๊ณ , ๋น์ฐํ ๋น๊ฐ์ 2๊ธ์ ๋ฏธ๋ง์ด๋ฏ๋ก ์ ์ ๋ ํ๋ฉด์ ๋ค์ด์์๋ง์ ๊ฒฝ๊ณ ์ฐฝ์ ๋ณด๊ฒ ๋๋ ๋ถ์์ฌ๊ฐ ์ผ์ด๋๊ฒ ๋ฉ๋๋ค.
์ด๋ด ๋ Subscribeํ๊ธฐ ์ ๊น์ง ๋์ํ์ง ์๋ PublishSubject๋ฅผ ํตํด์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
Relay๋ ์ฌ์ค์ Subject์ ๋๋ค.
์์ '๊ฐ ์ ๋ฌ๋ง ํ๋ Next ์ด๋ฒคํธ๋ง ์ฒ๋ฆฌํ ์ ์๊ณ , Next ์ด๋ฒคํธ๋ง ์ฒ๋ฆฌํ๊ฒ๋ ๊ฐ์ ํ ์๋ ์์ต๋๋ค.' ๋ผ๊ณ ํ๋๋ฐ์
์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ ์ ์์ผ๋ฉด์, Next ์ด๋ฒคํธ๋ง ์ฒ๋ฆฌํ ์ ์๋ ๊ฒ์ด ๋ฐ๋ก Relay์ ๋๋ค.
Next ์ด๋ฒคํธ๋ง ์ฒ๋ฆฌํ๋ ๊ฒฝ์ฐ๋ ๋ณดํต UI ๊ด๋ จ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ ๋์ด๊ธฐ ๋๋ฌธ์ Relay๋ UI ์ฒ๋ฆฌ์ ์ ํฉํ๋ค๊ณ ํ ์ ์์ต๋๋ค.
UI๊ฐ Error์ Compledted ์ด๋ฒคํธ๋ฅผ ๋ฐ๊ฒ ๋๋ฉด ๋์ด์ Next ์ด๋ฒคํธ๋ฅผ ์ ๋ฌ ๋ฐ์ ์ ์๊ฒ ๋๊ณ , ๊ทธ๋ฌ๋ฉด ๋ฐ์ํ์ ์ฅ์ ์ด ์ฌ๋ผ์ง๊ฒ ๋๊ฒ ์ฃ .
๊ทธ๋์ Relay๋ disposed๊ฐ ๋๊ธฐ ์ ๊น์ง Subscribe๊ฐ ํด์ ๋์ง ์์ต๋๋ค. disposed๊ฐ ํธ์ถ๋๋ deinit ์์ ์ด๋ ์ง์ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์ด์ผ ํฉ๋๋ค.
Relay์๋ 3๊ฐ์ง ์ข ๋ฅ๊ฐ ์์ผ๋ฉฐ ๋์๋ฐฉ์์ Subject์ ๋์ผํฉ๋๋ค.
์ฝ๊ฐ์ ๋ค๋ฅธ ์ ์ ๊ฐ์ ํ ๋นํ์ฌ Next ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ ๋ ์ฌ์ฉํ๋ ๋ฉ์๋๊ฐ ์กฐ๊ธ ๋ค๋ฆ ๋๋ค.
onNextacceptvalue.onNext(num)
value.accept(num)
RxSwift์ Observable vs Observer vs Subject vs Relay ์ฐจ์ด์ ๋ํด ์ ๋ฆฌํด๋ณด์๋๋ฐ์,
๋์์ด ๋์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค! ๊ฐ์ฌํฉ๋๋ค.