Sharing

๐Ÿ”ฅ Sharing Operators โ€” share, replay, multicast

โ€œHot์œผ๋กœ ๋งŒ๋“ค๊ณ , ๊ตฌ๋…์ž๋ฅผ ์ค„์„ธ์›Œ๋ผ.โ€

Sharing ๊ณ„์—ด ์˜คํผ๋ ˆ์ดํ„ฐ๋Š” Cold Observable์„ Hot์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜, ์ด๋ฏธ Hot ์ŠคํŠธ๋ฆผ์„ ๊ตฌ๋…์ž ๊ฐ„ ํšจ์œจ์ ์œผ๋กœ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ ์ค‘๋ณต ํ˜ธ์ถœ ๋ฐฉ์ง€, โ€‘UI ์ค‘๋ณต ์—…๋ฐ์ดํŠธ ๋“ฑ์—์„œ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.


1๏ธโƒฃ share() โ€” ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ Multicasting

let shared = api.fetchItems()
    .share()

shared.subscribe(...)
shared.subscribe(...)
  • share() = multicast(subject: PublishSubject()).refCount().

  • ์ฒซ ๊ตฌ๋… ์‹œ ์†Œ์Šค Observable ๊ตฌ๋…, ๋ชจ๋“  ๊ตฌ๋… ํ•ด์ œ๋˜๋ฉด ์ž๋™ dispose.

  • Default replay:0, scope:.whileConnected.

ํŒŒ๋ผ๋ฏธํ„ฐ

ํŒŒ๋ผ๋ฏธํ„ฐ
๊ธฐ๋ณธ๊ฐ’
์„ค๋ช…

replay

0

์บ์‹œํ•  ์ตœ์‹  ์ด๋ฒคํŠธ ๊ฐœ์ˆ˜

scope

.whileConnected

.forever ์„ค์ • ์‹œ ์ฒซ ์—ฐ๊ฒฐ ํ›„ ๊ณ„์† Hot ์œ ์ง€

.share(replay:1, scope:.forever) // Behavior-like Hot Cache

2๏ธโƒฃ replay(_:) โ€” ์ง€์ • ๊ฐœ์ˆ˜ Replay ํ›„ ์ž๋™ Connect

let hot = coldObservable
    .replay(1) // ์ตœ์‹  1๊ฐœ ์บ์‹œ

hot.connect() // ์ˆ˜๋™ ์—ฐ๊ฒฐ
  • publish().refCount() ํŒจํ„ด๊ณผ ๋‹ฌ๋ฆฌ ๋ฒ„ํผ ์ง€์›.

  • .connect() ์ˆ˜๋™ ํ˜ธ์ถœ or .autoconnect().


3๏ธโƒฃ multicast(subject:) โ€” ์™„์ „ ์ˆ˜๋™ ์ œ์–ด

let subject = PublishSubject<Int>()
let multicasted = coldObservable.multicast(subject: subject)

multicasted.subscribe(...)
multicasted.connect()
  • ์›ํ•˜๋Š” Subject ํƒ€์ž… ์ง€์ • (e.g., ReplaySubject, BehaviorSubject).

  • connect/dispose๋ฅผ ์™ธ๋ถ€์—์„œ ์ œ์–ดํ•ด์•ผ ํ•จ.


4๏ธโƒฃ Hot ๋ณ€ํ™˜ Flowchart

Cold
 โ”‚  share()       (auto connect)
 โ–ผ
Hot (PublishSubject)
 โ”‚  replay(โ€ฆ)     (auto connect)
 โ–ผ
Hot + Cache
 โ”‚  multicast()   (manual connect)
 โ–ผ
Custom Hot (Behavior/Reโ€ฆ)

5๏ธโƒฃ ์‹ค์ „ ํŒจํ„ด

A. ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ ์บ์‹ฑ

func loadImage(url: URL) -> Observable<UIImage> {
    URLSession.shared.rx.data(request: URLRequest(url: url))
        .map(UIImage.init)
        .share(replay: 1, scope: .forever)
}

B. BLE ์„ผ์„œ ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆผ ๊ณต์œ 

bleManager.rx.sensorData()
    .share()
    .bind(to: chart, logger, fileWriter)

C. Splash ๋ณ‘๋ ฌ API ํ˜ธ์ถœ โ†’ merge

Observable.merge(api.a().share(), api.b().share())

6๏ธโƒฃ Pitfalls & Tips

  1. share()์˜ scope:.whileConnected๋Š” ๋ชจ๋“  ๊ตฌ๋… ์ข…๋ฃŒ ์‹œ ์žฌ์‹œ์ž‘ โ†’ ๊ธฐ์–ตํ•˜์ž.

  2. memory: replay ๊ฐ’์ด ํฌ๋ฉด ์บ์‹œ ๋ฉ”๋ชจ๋ฆฌ ์ฆ๊ฐ€ โ€” ํ•„์š” ์š”์†Œ๋งŒ.

  3. Driver/Signal(RxCocoa) ๋‚ด๋ถ€๋„ share(replay:1) ์‚ฌ์šฉ.


7๏ธโƒฃ Mini Quiz

  1. share(replay:1, scope:.whileConnected)๊ณผ replay(1).refCount() ์ฐจ์ด?

  2. Hot Observable์„ ๋‹ค์‹œ Cold๋กœ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์€?

  3. Subject๋ฅผ ์™ธ๋ถ€์— ๋…ธ์ถœํ•˜์ง€ ์•Š๊ณ  multicast๋ฅผ ์“ฐ๋Š” ์žฅ์ ?

Answesrs
  1. ๊ธฐ๋Šฅ ์œ ์‚ฌํ•˜์ง€๋งŒ share๋Š” Operator ์ฒด์ธ ๋‚ด ๊ฐ„๋‹จ ๊ตฌ๋ฌธ, replay(...).refCount()๋กœ ๋™์ผ ๊ตฌํ˜„; share๊ฐ€ concise.

  2. ๋ถˆ๊ฐ€๋Šฅ โ€” Hot์€ ์ด๋ฏธ ์—ฐ๊ฒฐ; ํ•„์š”ํ•˜๋ฉด ์ƒˆ Cold Observable์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ .takeUntil(deallocated)๋กœ ๊ตฌ๋… ๋ฒ”์œ„๋ฅผ ํ•œ์ •.

  3. ์บก์Аํ™”: Subject๋ฅผ private๋กœ ์ˆจ๊ฒจ ์™ธ๋ถ€์—์„œ ์ž„์˜ onNext ๋ฐฉ์ง€ํ•˜๊ณ  connect ์ œ์–ด๋งŒ ๋…ธ์ถœ.


๋‹ค์Œ โ–ถ๏ธ memoryManagement.md ๋กœ ์ด๋™ํ•ด DisposeBagยทleak ์˜ˆ๋ฐฉ ์ „๋žต์„ ์‹ฌํ™”ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿš€

Last updated