RxSwift

[RxSwift] Observable & Observer (just, of, from, create)

yeggrrr๐Ÿผ 2024. 6. 24. 04:31

 

RxSwfit

Reactive eXension + Swift
๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ง๊ด€์ ์œผ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

RxSwift๋Š” ๊ตฌ๋…(Observe)์„ ํ•ด์„œ ๋ฐ์ดํ„ฐ ๋ณ€ํ™”์— ๋ฐ˜์‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

 

Observable & Observer

โ–ท Observable์„ ํ†ตํ•ด์„œ ์ด๋ฒคํŠธ ๊ฐ’์„ ๋ฐฉ์ถœ(Emit)ํ•  ์ˆ˜ ์žˆ๊ณ , ์ด ๊ฐ’์„ ๊ตฌ๋…(Subscribe)ํ•˜์—ฌ ๊ด€์ฐฐํ•˜๊ณ  ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

โ–ท ํ•˜๋‚˜ ์ด์ƒ์˜ ๊ด€์ž˜์ฐจ(Observer)๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ณ€ํ™”์— ๋ฐ˜์‘ํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค. (ex. UI ์—…๋ฐ์ดํŠธ, ํด๋ฆญ ์ด๋ฒคํŠธ, ...)
→ Observable์„ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ๋Š” Observer

โ–ท Observable์€ 3๊ฐ€์ง€ ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.
 - onNext: ๋‹ค์Œ ๊ฐ’์„ ์ „๋‹ฌํ•˜๋Š” ์ด๋ฒคํŠธ(์ƒˆ๋กœ์šด ๊ฐ’์ด ๋ฐฐ์ถœ๋  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ)
 - onError: ๊ฐ’ ๋ฐฐ์ถœ ๊ณผ์ •์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด error๋ฅผ ๋ฐฉ์ถœํ•˜๊ณ  ์ข…๋ฃŒ์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ(= disposed)
 - onCompleted: ์„ฑ๊ณตํ•  ๊ฒฝ์šฐ ์ด๋ฒคํŠธ ์‹œํ€€์Šค๋ฅผ ์ข…๋ฃŒ์‹œํ‚ค๋Š” ์ด๋ฒคํŠธ(= disposed)

 

Observable LifeCycle

1. Observable ์ƒ์„ฑ
2. Subscribe๋ฅผ ํ•œ ์‹œ์ ๋ถ€ํ„ฐ Observable ์‹คํ–‰
3. next๋ฅผ ํ†ตํ•ด ์ด๋ฒคํŠธ ๋ฐฉ์ถœ


Observable ์ƒ์„ฑ ๋ฐฉ๋ฒ•

์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋˜๋Š” ์‹œ์ ์€ Observer๊ฐ€ Observable๋ฅผ ๊ตฌ๋…(subscribe)์„ ํ•œ ์ดํ›„ ๋ถ€ํ„ฐ์ด๋‹ค.

Observable๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ 4๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

1. just
2. of
3. from
4. Create



just๋Š” ์˜ค์ง ํ•˜๋‚˜์˜ ๊ฐ’์„ ๋ฐฉ์ถœํ•˜๋Š” Observable Sequence๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

let observable = Observable.just(1)

์ด๋ ‡๊ฒŒ ๋‹จ ํ•˜๋‚˜์˜ ํ•ญ๋ชฉ๋งŒ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค.
์ด ์ƒํƒœ๋กœ subscribe(๊ตฌ๋…)์„ ํ•˜๊ฒŒ ๋˜๋ฉด,

obaservable.subscribe { value in
            print(value)
        } onError: { error in
            print(error)
        } onCompleted: {
            print("onCompleted")
        } onDisposed: {
            print("onDisposed")
        }
        .disposed(by: disposeBag)
        
// <์‹คํ–‰ ๊ฒฐ๊ณผ>
// 1
// onCompleted
// onDisposed

์ด๋ ‡๊ฒŒ 1์„ ํ•œ๋ฒˆ ๋ฐฉ์ถœํ•˜๊ณ , ๋ฐ”๋กœ complete → dispose ๋œ๋‹ค.
์ด๋ ‡๊ฒŒ ํ•˜๋‚˜๋งŒ ๋ฐฉ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งŒ์•ฝ ๋ฐฐ์—ด์„ just์— ๋„ฃ์€ ๊ฒฝ์šฐ์—๋Š” ๋ฐฐ์—ด ์ž์ฒด๋ฅผ ๋ฐฉ์ถœํ•˜๊ณ  ์ข…๋ฃŒ๋œ๋‹ค.



of๋Š” 1๊ฐœ ์ด์ƒ์˜ ํ•ญ๋ชฉ์„ ๋ฐฉ์ถœํ•˜๋Š” Observable Sequence๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

let observable = Observable.of(1, 2, 3) // 1๋ฒˆ
let observable = Observable.of([1, 2, 3]) // 2๋ฒˆ


1๋ฒˆ์€ 1 → 2→ 3→ ์ข…๋ฃŒ!

2๋ฒˆ์ฒ˜๋Ÿผ of์˜ ์ธ์ž๋กœ ๋ฐฐ์—ด์„ ๋„ฃ๊ฒŒ ๋˜๋ฉด,
[1, 2, 3] → ์ข…๋ฃŒ!
์ด๋ ‡๊ฒŒ ๋‹จ์ผ ์š”์†Œ๋กœ ๋ฐฉ์ถœํ•œ๋‹ค.

of๋Š” ์ด๋ ‡๊ฒŒ ๋ฐฉ์ถœํ•˜๊ณ  ์‹ถ์€ ๋งŒํผ ํ•ญ๋ชฉ์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค. ๋‹จ, ํƒ€์ž…์„ ๋ชจ๋‘ ๋™์ผํ•ด์•ผํ•œ๋‹ค.

// 1๋ฒˆ
obaservable.subscribe { value in
            print(value)
        } onError: { error in
            print(error)
        } onCompleted: {
            print("onCompleted")
        } onDisposed: {
            print("onDisposed")
        }
        .disposed(by: disposeBag)
        
// <์‹คํ–‰ ๊ฒฐ๊ณผ>
// 1
// 2
// 3
// onCompleted
// onDisposed

1๋ฒˆ์—์„œ ๋„˜๊ฒจ์ค€ 1, 2, 3์„ ์ˆœ์„œ๋Œ€๋กœ ๋ฐฉ์ถœํ•˜๊ณ  dispose๋œ๋‹ค.

// 2๋ฒˆ
obaservable.subscribe { value in
            print(value)
        } onError: { error in
            print(error)
        } onCompleted: {
            print("onCompleted")
        } onDisposed: {
            print("onDisposed")
        }
        .disposed(by: disposeBag)
        
// <์‹คํ–‰ ๊ฒฐ๊ณผ>
// [1, 2, 3]
// onCompleted
// onDisposed

์ด๋ ‡๊ฒŒ 2๋ฒˆ์ฒ˜๋Ÿผ ๋ฐฐ์—ด์„ ๋„ฃ์€ ๊ฒฝ์šฐ์—๋Š”
ํŒŒ๋ผ๋ฏธํ„ฐ ํ•˜๋‚˜๋ฅผ ํ•ญ๋ชฉ์œผ๋กœ ์ทจ๊ธ‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— just์ฒ˜๋Ÿผ ๋ฐฐ์—ด์„ ํ•˜๋‚˜์˜ ํ•ญ๋ชฉ์œผ๋กœ ๋ฐฉ์ถœํ•œ๋‹ค


from์€ ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ๋“ค์„ ์ˆœ์„œ๋Œ€๋กœ Observable Sequence๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

let observable3 = Observable.from([1, 2, 3])

 

from์€ ๊ฐ๊ฐ์˜ ๊ฐ’๋“ค์€ ๋ฐ›์„ ์ˆ˜ ์—†๊ณ , ์˜ค์ง ๋ฐฐ์—ด๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

obaservable.subscribe { value in
            print(value)
        } onError: { error in
            print(error)
        } onCompleted: {
            print("onCompleted")
        } onDisposed: {
            print("onDisposed")
        }
        .disposed(by: disposeBag)
   
// <์‹คํ–‰ ๊ฒฐ๊ณผ>
// 1 
// 2
// 3
// onCompleted
// onDisposed

์ด๋ ‡๊ฒŒ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ณด๋‚ธ ๋ฐฐ์—ด์˜ ์š”์†Œ๋“ค์„ ์ˆœ์„œ๋Œ€๋กœ ํ•˜๋‚˜์”ฉ ๋ฐฉ์ถœํ•œ๋‹ค.



์ •๋ฆฌํ•ด๋ณด๋ฉด,
Observable๋ฅผ ๊ตฌ๋…ํ•œ ์‹œ์ ๋ถ€ํ„ฐ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•œ ํ•ญ๋ชฉ๋“ค์ด ์ˆœ์„œ๋Œ€๋กœ ๋ฐฉ์ถœ๋˜๊ณ , ์ด ๊ณผ์ •์ด ๋๋‚˜๋ฉด complete๊ฐ€ ๋ถˆ๋ฆฌ๋ฉด์„œ dispose๋œ๋‹ค.

of๋Š” Observable ๋ฐฐ์—ด์„ ๋งŒ๋“ค๊ณ ! from์€ ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ๋“ค์„ Observable๋กœ ๋งŒ๋“ ๋‹ค.
ํƒ€์ž…์œผ๋กœ ๋ณด๋ฉด, of๋Š” Observable<[Int]>,  from์€ Observable<Int> ์ด๋‹ค.


๋งˆ์ง€๋ง‰์œผ๋กœ
create๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ Observer๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š” ํด๋กœ์ €๋ฅผ ์ „๋‹ฌ๋ฐ›๋Š” Observable Sequence๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
์œ„์—์„œ ์–ธ๊ธ‰ํ–ˆ๋˜ onNext, onError, onCompleted๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. (onError, onCompleted 1๋ฒˆ๋งŒ ํ˜ธ์ถœ ๊ฐ€๋Šฅ)

 let obaservable = Observable<Int>.create { observer in
            observer.onNext(1)
            observer.onNext(2)
            observer.onCompleted()
            observer.onNext(3)
            return Disposables.create()
        }

create๋Š” just, of, from ๊ณผ ๋‹ค๋ฅด๊ฒŒ ์ด๋ ‡๊ฒŒ ํด๋กœ์ €๋ฅผ ์ด์šฉํ•ด์„œ
onNext๋ฅผ ํ†ตํ•ด ์–ด๋–ค ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ• ์ง€,
์–ธ์ œ onComplete, onError ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ• ์ง€๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.
๋‹จ, onComplete, onError๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด, dispose๊ฐ€ ๋˜์–ด ์ข…๋ฃŒ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ดํ›„์—๋Š” ์–ด๋–ค ๋ฉ”์„œ๋“œ๋„ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค.

obaservable.subscribe { value in
            print(value)
        } onError: { error in
            print(error)
        } onCompleted: {
            print("onCompleted")
        } onDisposed: {
            print("onDisposed")
        }
        .disposed(by: disposeBag)

// <์‹คํ–‰ ๊ฒฐ๊ณผ>
// 1
// 2
// onCompleted
// onDisposed

์‹คํ–‰๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด, onCompleted ๋‹ค์Œ์— ํ˜ธ์ถœ๋œ 3์€ ๋ฐฉ์ถœ๋˜์ง€ ์•Š์€ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

subscribe(๊ตฌ๋…)์„ ํ•œ ํ›„, dispose ํ•˜๋Š” ๋ฐฉ๋ฒ•

Observer๊ฐ€ Observable์„ subscribe๋ฅผ ํ†ตํ•ด์„œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›๋Š”๋‹ค.

๋งŒ์•ฝ, ๋”์ด์ƒ Observable์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด..?

์ด๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด Disposable์ด๋‹ค.

Disposable์€ subscribe ์ค‘์ธ ์ƒํ™ฉ์—์„œ ์›ํ•œ๋Š” ์‹œ๊ธฐ์— dispose(์ฒ˜๋ฆฌ)ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

.dispose() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. 

ํ•˜์ง€๋งŒ,

ํด๋ž˜์Šค ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ๋˜๋Š” ์‹œ์ (deinit)์— Disposable์ด ๋˜๋Š”๋ฐ, ํด๋ž˜์Šค๊ฐ€ RootVC์ธ ๊ฒฝ์šฐ์—๋Š” ๋ฉ”๋ชจ๋ฆฌ์—์„œ Disposable์ด ๋˜์ง€ ์•Š๋Š”๋‹ค.

์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ์ง์ ‘ ํ•„์š”ํ•œ ์‹œ์ ์— dispose๋ฅผ ํ˜ธ์ถœํ•ด ์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ, ๊ตฌ๋… ๊ฐ์ฒด๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ๊ด€๋ฆฌํ•˜๊ธฐ ํž˜๋“ค์–ด์ง„๋‹ค.

์ด๋Ÿฌํ•œ ๋ฌธ์ œ์ ๋“ค์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— DisposeBag์„ ์‚ฌ์šฉํ•œ๋‹ค.
(๊ณต์‹ ๋ฌธ์„œ์—๋„ dispose() ์ง์ ‘ํ˜ธ์ถœ ๋ณด๋‹ค DisposeBag์„ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ์จ์žˆ์Œ)

์ด๋ณด๋‹ค ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ๋ฐ”๋กœ, DisposeBag์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
DisposeBag์„ ๋งŒ๋“ค์–ด์„œ Disposable์„ ๋‹ด์•„๋‘์—ˆ๋‹ค๊ฐ€ ํ•œ ๋ฒˆ์— ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

let disposeBag = DisposeBag()

์ด๋ ‡๊ฒŒ disposeBag์„ ๋งŒ๋“ค์–ด ๋†“๊ณ , ํ•ด์ œ๊ฐ€ ํ•„์š”ํ•œ ์‹œ์ ์—

.disposed(by: disposeBag)

์ด๋ ‡๊ฒŒ ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค. (์ด๋ฏธ just, of ,from, create ์˜ˆ์‹œ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Œ)

์ด๋ ‡๊ฒŒ DisposeBag์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด, ํ•„์š”ํ•œ ์‹œ์ ์—์„œ DisposeBag์˜ ์ธ์Šคํ„ด์Šค ์ดˆ๊ธฐํ™” ๊ณผ์ •์„ ํ†ตํ•ด์„œ ํ•œ ๋ฒˆ์— ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.





728x90

'RxSwift' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[RxSwift] BehaviorSubject, PublishSubject, ReplaySubject, AsyncSubject  (0) 2024.06.26