[RxSwift] Observable์˜ ์ƒ๋ช… ์ฃผ๊ธฐ, ์ˆœํ™˜ ์ฐธ์กฐ์™€ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ, subscribeOn, observeOn
iOS/Swift

[RxSwift] Observable์˜ ์ƒ๋ช… ์ฃผ๊ธฐ, ์ˆœํ™˜ ์ฐธ์กฐ์™€ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ, subscribeOn, observeOn

์ •๋ง ์ƒ์ดˆ๋ณด,, ์•„๋ฌด๊ฒƒ๋„ ๋ชจ๋ฅด๋Š” ์ž…์žฅ์—์„œ ๊ฐ•์˜ ์˜์ƒ์„ ๋ณด๊ณ  ์˜์‹์˜ ํ๋ฆ„๋Œ€๋กœ ์ž‘์„ฑํ•œ ๊ธ€์ด๋‹ˆ ๋น„ํŒ์˜ ๋ˆˆ์œผ๋กœ ๊ธ€์„ ์ฝ์–ด ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค~~ ์˜ค๋ฅ˜ ์ง€์  ๋Œ€ํ™˜์˜!

Observable Life-Cycle


1. Create

  • Observable ์ƒ์„ฑ
  • ๋ฐ์ดํ„ฐ๊ฐ€ ์ƒ์„ฑ๋˜๊ฑฐ๋‚˜, ์–ด๋–ค ๋ช…๋ น์ด ๋™์ž‘ํ•˜์ง€ ์•Š์Œ → 2. Subscribe์—์„œ ๋™์ž‘!

2. Subscribe

  • ์–ด๋– ํ•œ Observable์ด ๋™์ž‘ํ•จ

3. Next

  • ๋ฐ์ดํ„ฐ ์ „๋‹ฌ

4. Completed

  • ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ ๋

4-1. Error

  • ๋น„์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ ๋

5. Disposed

  • Dispose๋˜๋ฉด ๊ทธ Observable์€ ๋” ์ด์ƒ ์žฌ์‚ฌ์šฉ ๋ถˆ๊ฐ€

.debug() ๋กœ Observable ์ƒํƒœ ํ™•์ธ ๊ฐ€๋Šฅ

์ˆœํ™˜ ์ฐธ์กฐ์™€ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ


.subscribe(onNext: { i in
    self.countLabel.text = "\(i)"
})
.disposed(by: disposeBag)

์ด ์ฝ”๋“œ์—์„œ subscribe ๋‚ด์—์„œ UI ์ž‘์—…์„ ํ•˜๋Š๋ผ self(ViewController)๋ฅผ ์ฐธ์กฐ. ์ด๋ฏธ VC ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋ฉด์„œ ํ•œ ๋ฒˆ ์ฐธ์กฐ๋œ ๊ฒƒ์ž„. VC๊ฐ€ pop ๋˜๋”๋ผ๋„ ์œ„ ํด๋กœ์ €์—์„œ ํ•œ ๋ฒˆ ์ฐธ์กฐ๋œ ๊ฒŒ ๋‚จ์•„ ์žˆ์Œ! (4๋ฒˆ์˜ RC=1) ์ด VC ์ธ์Šคํ„ด์Šค๋Š” ๋” ์ด์ƒ ์•ˆ ์“ฐ๋Š”๋ฐ...→ ์ˆœํ™˜ ์ฐธ์กฐ์— ์˜ํ•œ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜(Memory Leak)

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ์•ฝํ•œ ์ฐธ์กฐ(weak self)๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, onCompleted()๋ฅผ ํ†ตํ•ด Subscribe ํด๋กœ์ € ์ž์ฒด๋ฅผ ์ข…๋ฃŒ์‹œํ‚จ๋‹ค.

  • ์•ฝํ•œ ์ฐธ์กฐ(weak self)
.subscribe(onNext: { [weak self] i in
    self.countLabel.text = "\(i)"
})
.disposed(by: disposeBag)

weak self๋ฅผ ์•ˆ ์ผ์„ ๋•Œ๋Š” ์ž๋™์œผ๋กœ ๊ฐ•ํ•œ ์ฐธ์กฐ(strong)๋กœ ์‚ฌ์šฉ๋จ. weak self๋Š” ์œ„์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉฐ, ์ฐธ์กฐ๋  ๋•Œ RC๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค! ์ƒ์œ„ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•ด์ œ๋˜๋ฉด(RC- -) ์–˜๋Š” ๋ฐ”๋กœ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋‚ ์•„๊ฐ(RC=0).

  • subscribe์˜ ํด๋กœ์ €๋ฅผ ์ข…๋ฃŒ์‹œํ‚ค๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•: Observable์„ ๋งŒ๋“ค ๋•Œ onCompleted() ๋ช…์‹œ
emitter.onNext(image)
emitter.onCompleted()
return Disposables.create()

๋ญ ์ด๋Ÿฐ ์‹์œผ๋กœ... onCompleted๊ฐ€ ๊ผญ ์‹คํ–‰๋˜๋„๋ก ๋ช…์‹œํ•˜๋ฉด Observable ๋™์ž‘ ์ž์ฒด๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด์„œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ๋จ.

์Šค๋ ˆ๋“œ ๋ถ„๊ธฐ


  • DispatchQueue, OperationQueue๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  observeOn, subscribeOn์„ ์‚ฌ์šฉํ•จ! (DispatchQueue, OperationQueue๋ฅผ observeOn, subscribeOn๊ฐ€ ๊ฐ์‹ผ(wrapping) ๊ฐœ๋…)

subscribeOn

  • ํ•œ ๋ฒˆ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ, ๊ตฌ๋… ์‹œ ์‹œ์ž‘ํ•  ์Šค๋ ˆ๋“œ ์ง€์ •
  • subscribeOn์ด ์ง€์ •๋œ ์œ„์น˜์— ์ƒ๊ด€์—†์ด ์ฒซ ์Šค๋ ˆ๋“œ๋ฅผ ์ง€์ •ํ•จ!
  • ์œ„์— ์žˆ๋Š” Stream์— ์˜ํ–ฅ์„ ์คŒ → ์—…์ŠคํŠธ๋ฆผ(Up Stream)

observeOn

  • ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉ ๊ฐ€๋Šฅ, observeOn์—์„œ ์Šค๋ ˆ๋“œ๋ฅผ ์ง€์ •ํ•œ ํ›„ ๊ทธ ์•„๋ž˜๋ถ€ํ„ฐ์˜ Stream์— ์ž‘๋™ → ๋‹ค์šด์ŠคํŠธ๋ฆผ(Down Stream)

Stream์˜ ๋ถ„๋ฆฌ ๋ฐ ๋ณ‘ํ•ฉ


merge

  • Observable 2๊ฐœ๋ฅผ 1๊ฐœ๋กœ merge
  • ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ํ†ต์ผํ•ด์•ผ ํ•จ!

zip

  • ์Œ์œผ๋กœ ๋งŒ๋“ค์–ด ์ „๋‹ฌ → ๋ฐ์ดํ„ฐ ํƒ€์ž… ๋‹ฌ๋ผ๋„ ์ƒ๊ด€ X
1----2--------3---------4---->
B----------C---A------------->
########### zip ############
1B---------2C--3A------------>
  • ๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜๋Š” ๊ฐ€์žฅ ์ž‘์€ ์ŠคํŠธ๋ฆผ์˜ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜์™€ ๋™์ผ!

combineLatest

  • zip๊ณผ์˜ ์ฐจ์ด์ : ๊ฐ€์žฅ ์ตœ๊ทผ์˜ ๋ฐ์ดํ„ฐ์™€ ์Œ์„ ์ด๋ค„ ์ „๋‹ฌ
1----2--------3---------4---->
B----------C---A------------->
######### combineLatest #########
1B---2B----C2-3C--A3----4A--->

Reference