RxSwift - Observable, Observer, Subscribe
ย RxSwift?
RxSwift๋ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ๊ด์ฐฐ ๊ฐ๋ฅํ ์์ฐจ์ ํํ์ ํจ์ ํํ์ ์ฐ์ฐ์๋ฅผ ํตํด ์ฒ๋ฆฌํ๊ฒ๋ ๋์์ค๋ค.
โ RxSwift๋ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ด๊ธฐ ๋๋ฌธ์, ์ด๋ค ๋น๋๊ธฐ ์ด๋ฒคํธ์ ๋ํด ๊ด์ฐฐ ๊ฐ๋ฅํ ํํ๋ก ๋ง๋ค๊ณ , ์ด๋ฅผ ๊ด์ฐฐํ๋ ์ฃผ์ฒด๊ฐ ์์ ๊ฒฝ์ฐ, ์ด ๋น๋๊ธฐ ์ด๋ฒคํธ์ ๋ณํ์ ๋ฐ๋ฅธ ์ ํ๋ฅผ ๋ฐ์ ์ ์๋ค.
โข
๊ด์ฐฐ ๊ฐ๋ฅํ ์์ฐจ์ ์ธ ํํ โ Observable
โข
ํด๋น ์ด๋ฒคํธ์ ๋ณํ๋ฅผ ๊ด์ฐฐํ์ฌ ์ ํ ๋ฐ๋ ๊ฒ โ Observer
ย Observable๊ณผ Observer
ย 1. Observable
์ด๋ค ๋น๋๊ธฐ ์ด๋ฒคํธ์ ๋ํด ๊ด์ฐฐ ๊ฐ๋ฅํ ํํ ๋ก ๋ง๋ ๋ค
โข
๊ด์ฐฐ ๊ฐ๋ฅํ ํํ โ Observable
Observable ์ ๊ด์ฐฐ์ด ๊ฐ๋ฅํ ํ๋ฆ์ผ๋ก, ๋น๋๊ธฐ ์ด๋ฒคํธ์ ์ํ์ค๋ฅผ ์์ฑํ ์ ์๋ ๋์
ย RxSwift์ Observable์ ์ ์
์ ๋ค๋ฆญ ํด๋์ค๋ก ๊ตฌ์ฑ๋์ด ์๋ค.
์ฐ๋ฆฌ๊ฐ ๋น๋๊ธฐ ์ด๋ฒคํธ๋ฅผ ์ด๋ค ๊ด์ฐฐ ๊ฐ๋ฅํ ํํ๋ก ๋ง๋ ๋ค๋ ๊ฒ์,
๋น๋๊ธฐ ์ด๋ฒคํธ๋ฅผ ์ ๋ค๋ฆญ ํ์
์ Observable์ด๋ ํด๋์ค ์ธ์คํด์ค๋ฅผ ๋ง๋ ๋ค๋ ๊ฒ๊ณผ ๊ฐ์ ๊ฒ ์ด๋ค.
์๋ฅผ๋ค๋ฉด,
๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๋น๋๊ธฐ ์ด๋ฒคํธ UIButton ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ๋ณด์.
๋ฒํผ์ ํด๋ฆญ ์ด๋ฒคํธ๊ฐ ์ ์ ์ ์ํด ์ธ์ ๋ฐ์ํ ์ง ์ ์ธํ ๋น์์๋ ๋ชจ๋ฅธ๋ค.
โ ๋ฐ๋ผ์ ์ด๋ฒคํธ๊ฐ ๋ค์ด์์ ๋๋ฅผ ๊ฐ์ ํ๊ณ ํ๋ก๊ทธ๋๋ฐ์ ํ์๋ค.
โ ๋ง์ฝ ๋ฒํผ์ด sync ๋์์ด์๋ค๋ฉด, ๋ฒํผ์ด ๋๋ฆด ๋๊น์ง ์๋ฌด ์์
๋ ํ ์ ์์ ๊ฒ์ด๋ค.
โ ๋ฐ๋ผ์ ๋ฒํผ์ ๋น๋๊ธฐ ์ด๋ฒคํธ!
๊ทผ๋ฐ Reactive Programming ์ด๋,
๋ฐ์ดํฐ์ ํ๋ฆ์ด ๋ณ๊ฒฝ๋์์ ๋ ์ ํํ๋๋ฐ ์ค์ ์ ๋ ํ๋ก๊ทธ๋๋ฐ์ด๋ค.
๋ฐ๋ผ์ ์ฌ๊ธฐ์ ๋ฐ์ดํฐ๋ ๋ฒํผ,
๋ฐ์ดํฐ์ ํ๋ฆ์ด ๋ณ๊ฒฝ๋๋ค๋ ๊ฒ์ ๋ฒํผ์ด ํด๋ฆญ ๋๋ค๋ ๊ฒ
๊ทธ๋ ๋ค๋ฉด ์ด ๋ฒํผ์ ํ๋ฆ ๋ณ๊ฒฝ์ ์ ํํ๊ธฐ ์ํด์
์ด ๋ฒํผ์ ํด๋ฆญ ์ด๋ฒคํธ๊ฐ โ๊ด์ฐฐ์ด ๊ฐ๋ฅํ ํํโ
์ฆ, Observable ์ด ๋์ด์ผ ํ๋ค.
ย ์ ๋ฆฌ
โข
๋ฒํผ์ ํด๋ฆญ์ ๋ํ๋ด๋ UIButton์ tap ์ด๋ฒคํธ๋ ๋น๋๊ธฐ ์ด๋ฒคํธ๋ก,
โข
๋ฐ์ดํฐ์ ๋ณํ์ ๋ํด ๊ด์ฐฐ์ด ๊ฐ๋ฅํ ํํ,
โข
์ฆ, RxSwift์์ ์ด๋ฅผ Observable ํํ๋ก ๋ง๋ค ์ ์๋ค.
๊ทธ๋ฌ๋ฉด ์ด ๋ฒํผ์ด ๋๋ ธ์ ๋ ์ด๋ค ์ผ์ด ์ผ์ด๋๋๋ฉฐ๋
๋ฒํผ์ด ๋๋ ธ๋ค โ ๋ฐ์ดํฐ์ ํ๋ฆ์ด ๋ณ๊ฒฝ ๋์๋ค.
๋ฐ๋ผ์ ์ด ๋ฒํผ์ tap event์ ๋ํ Observable ์
๋ฒํผ์ด ๋๋ ธ์ ๋(๋น๋๊ธฐ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋), ํด๋น ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ค๋ ๊ฒ์ ์๋ ค์ฃผ๊ธฐ ์ํด โํญ๋ชฉ(item)โ ์ด๋ ๊ฒ์ โ๋ฐฉ์ถ(emit)โ ํ๋ค.
Observable์ ๋น๋๊ธฐ ์ด๋ฒคํธ์ โ์ํ์คโ๋ฅผ ์์ฑํ ์ ์๋ ๋์
์ํ์ค๋ผ๊ณ ํ ์ด์ ๊ฐ, ๋ฒํผ์ด ์ฌ๋ฌ๋ฒ ๋๋ฆฌ๋ฉด, ๊ทธ๋งํผ Observable์ ํด๋น ์ด๋ฒคํธ์ ๋ํ ํญ๋ชฉ์ ์์๋๋ก ๋ฐฉ์ถํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ ๋ฆฌํ์๋ฉด,
๋น๋๊ธฐ ์ด๋ฒคํธ๋ฅผ ๊ด์ฐฐ ๊ฐ๋ฅํ ํํ๋ก ๋ง๋ ๊ฒ์ด Observable ์ด๊ณ ,
์ด Observable ์ ์ค์ ๋น๋๊ธฐ ์ด๋ฒคํธ๊ฐ ์ผ์ด๋ฌ์ ๋, ์ด๋ฅผ ์๋ฆฌ๊ธฐ ์ํด
ํด๋น ์ด๋ฒคํธ์ ๋ํ ํญ๋ชฉ(item)์ ์ํ์ค๋ก ๋ฐฉ์ถํ๋ค.
๊ทธ๋ฌ๋ฉด ์ด ๋น๋๊ธฐ ์ด๋ฒคํธ๊ฐ ๋ฐฉ์ถํ๋ ํญ๋ชฉ์ ๋๊ฐ ๋ฐ์๊น? โ Observer
ย 2. Observer
Observer๋ Observable์ ๊ตฌ๋
ํ๋ค.
Observer๋ ๋ด๊ฐ ์ํ๋ ๋น๋๊ธฐ ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ๋ Observable์ด ์์ ๋,
ํด๋น โObservable์ ๊ตฌ๋
โ ์ ํ ๊ฒฝ์ฐ,
๊ทธ Observable์ด ๋น๋๊ธฐ ์ด๋ฒคํธ๊ฐ ์คํ๋์ด ํญ๋ชฉ(item)์ ๋ฐฉ์ถ ํ์ ๋,
๊ทธ ํญ๋ชฉ์ ๋ฐ์ ์ ์๋ค!
๊ทธ๋ฌ๋ฉด Observer๋ ๋๋์ฒด Observable ๊ตฌ๋
์ ์ด๋ป๊ฒ ํ์ง? โ Subscribe ๋ฉ์๋!
๋ํ Observer๊ฐ ์ด Subscribe๋ฅผ ํตํด Observable์ ๊ตฌ๋
ํ์ ๋,
์ด ์ธ ๊ฐ์ง ํด๋ก์ ๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ค์ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌ์ํฌ ์ ์๋๋ฐ
Subscribe ๋ผ๋ ๋ฉ์๋์ ์ํ์ ๋ณด๋ฉด
public func subscribe(
onNext: ((Element) -> Void)? = nil,
onError: ((Swift.Error) -> Void)? = nil,
onCompleted: (() -> Void)? = nil,
onDisposed: (() -> Void)? = nil
) -> Disposable
Swift
๋ณต์ฌ
์์ ๊ฐ์ด onNext, onError, onCompleted ๋ผ๋ ํ๋ผ๋ฏธํฐ๊ฐ ์๊ณ , ๋ชจ๋ ํ์
์ด ํด๋ก์ ํ์
์ธ ๊ฒ์ ์ ์ ์๋ค.
๊ธฐ์กด์ ์ด๋ค ๋น๋๊ธฐ ์ด๋ฒคํธ๋ฅผ ๋๊ธฐ๊ณ ์ถ์ ๋, ํด๋ก์ ๋ก ๋๊ฒผ์๋๋ฐ, ๊ฐ์ ๋งฅ๋ฝ์ด๋ค.
ย onNext:
โข
Observable์ด ์๋ก์ด ํญ๋ชฉ(item)์ ๋ฐฉ์ถํ ๋๋ง๋ค ์ด ํด๋ก์ ๊ฐ ํธ์ถ๋๋ค.
โข
์ด๋ Observable์ด ๋ฐฉ์ถํ๋ ํญ๋ชฉ์ ํด๋ก์ ์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ ๋ฐ๋๋ค.
ย onError:
โข
Observable์ ๊ธฐ๋ํ๋ ๋ฐ์ดํฐ๊ฐ ์์ฑ๋์ง ์์๊ฑฐ๋ ๋ค๋ฅธ ์ด์ ๋ก ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋,
โข
์ด ์ค๋ฅ๋ฅผ ๊ตฌ๋
์์ธ Observer์๊ฒ ์๋ฆฌ๊ธฐ ์ํด ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
ย onCompleted:
โข
Observable์ ์ด๋ฒคํธ๊ฐ ์ข
๋ฃ๋์ด ๋์ด์ ํธ์ถ๋์ง ์์ ๋,
โข
์ด๋ฒคํธ๊ฐ ์๋ฃ ๋์์์ ๊ตฌ๋
์์ธ Observer์๊ฒ ์๋ฆฌ๊ธฐ ์ํด ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
ย ์์ฝ
๋น๋๊ธฐ ์ด๋ฒคํธ๋ฅผ ๊ด์ฐฐ ๊ฐ๋ฅํ ํํ๋ก ๋ง๋ ๊ฒ โ Observable
Observable์ ํด๋น ๋น๋๊ธฐ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋ ํญ๋ชฉ(item)์ ๋ฐฉ์ถํจ
๊ด์ฐฐ ๊ฐ๋ฅํ ํํ์ธ Observable์ ๊ด์ฐฐํ๋ ๊ฒ โ Observer
Subscribe(onNext:โฆ) ๋ฉ์๋ ๋ฅผ ํตํด Observable์ ๊ตฌ๋
ํ ์ ์๋๋ฐ,
Observable์์ ํญ๋ชฉ์ด ๋ฐฉ์ถ๋์ ๋, ์๋ฌ๊ฐ ๋ฌ์ ๋, ์ด๋ฒคํธ๊ฐ ์ข
๋ฃ๋์์ ๋์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ํด๋ก์ ๋ก ์์ฑํ์ฌ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ค๋ค.
ย UIButton ํด๋ฆญ ์ด๋ฒคํธ๋ก ๋ณด๋ Observable๊ณผ Observer, Subscribe
RxSwift์๋ UIKit์ ๋ํ ์ ๋ณด๊ฐ ์๋ค!
๊ทธ๋์ UI์ ๊ด๋ จ๋ Reactive Programming์ ํ๋ ค๋ฉด RxCocoa ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
import RxCocoa
import RxSwift
Swift
๋ณต์ฌ
UIButton์ UIKit์ ์ํด์๊ธฐ ๋๋ฌธ์, RxCocoa๋ฅผ import ํด์ UIButton์ tap์ ๋ํ ๋น๋๊ธฐ ์ด๋ฒคํธ ์ฒ๋ฆฌ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์๋ค. (tap ์ด๋ฒคํธ โ .touchUpInside์ ๋ํ ๋์)
hjButton.rx
.tap
.subscribe(onNext: {
print("Observable์ด ํญ๋ชฉ์ ๋ฐฉ์ถ ํ๋ค!")
},
onError: { error in
print("์๋ฌ๊ฐ ๋ฐ์ํ๋ค!")
},
onCompleted: {
print("ํด๋น ์ด๋ฒคํธ๊ฐ ๋๋ฌ๋ค!")
})
.disposed(by: disposedBag)
Swift
๋ณต์ฌ
hjButton์ ๋ํด tap event๊ฐ ๋ฐ์ํ์ ๊ฒฝ์ฐ,
subscribe(onNext:โฆ)๋ฅผ ํตํด โ๊ตฌ๋
โ์ ํด์
ํด๋น Observable์ด ๋ฐฉ์ถํ๋ ํญ๋ชฉ์ ๋ํด ๋ฐ์ ์ ์๊ณ ,
์ด๋ ์ด ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ๋ก
onNext (ํญ๋ชฉ์ด ๋ฐฉ์ถ ๋์ ๋, ์ฆ ๋ฒํผ์ด ๋๋ ธ์ ๋ ์คํ์ํฌ ํด๋ก์ )
onError (์๋ฌ๊ฐ ๋ฐ์ ํ์ ๋ ์คํ์ํฌ ํด๋ก์ )
onCompleted (์ด๋ฒคํธ๊ฐ ์ข
๋ฃ๋์ ๋ ์คํ์ํฌ ํด๋ก์ )
๋ฅผ ๊ฐ๊ฐ ๋๊ฒจ์ค ์ ์๋ค.
์ฌ๊ธฐ์
Observer๋ฅผ ๋ง๋ ์ ์ด ์๋๋ฐ, ์ด๋ป๊ฒ Observable์ด ๊ตฌ๋
์ด ๋์ด ํญ๋ชฉ์ ๋ฐ์ ์ ์๋๊ฑธ๊น?
์ด๊ฒ์ subscribe(onNext: โฆ)๋ก ํด๋ก์ ๋ฅผ ๋๊ฒจ์ค ๋, ํด๋น ๋ฉ์๋ ์์์
์์ฒด์ ์ผ๋ก AnonymousObserver ๋ ๊ฒ์ ์์ฑํด์, ํด๋น Observable์ subscribe๋ฅผ ํด์ค๋ค.
ย ๊ฒฐ๋ก
subscribe(onNext:โฆ) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ, ๋ฉ์๋ ๋ด๋ถ์์ ์ต์ ๋ฒ๋ฅผ ์์ฒด์ ์ผ๋ก ์์ฑํด์
์ฐ๋ฆฌ๊ฐ ๋ฐ๋ก Observer๋ฅผ ์์ฑํ์ง ์๊ณ ํ๋ผ๋ฏธํฐ๋ก ํด๋ก์ ๋ง ๋๊ฒจ์ค๋
Observable์ ๊ตฌ๋
ํ์ฌ ๋ฐฉ์ถํ๋ ํญ๋ชฉ์ ๋ฐ์ ์ ์๊ฒ ๋ ๊ฒ์ด๋ค.