Hot vs Cold Observables
Hot vs Cold Observables
๐ฅถ Observable VS. ๐ฅ Observable |
์ด ๋ด์ฉ์ ๋์ผํ ์ ๋ชฉ์ ์์ด ์๋ฌธ Medium ํฌ์คํธ๋ฅผ ๋ฒ์ญํ ๊ฒ์
COLD is when your observable creates the producer
Cold
๋ฐฉ์์ Observable
์ด producer
๋ฅผ ์์ฑํ ๋๋ฅผ ์ผ์ปซ์
// COLD ๐ฅถ
var cold = new Observable((observer) => {
var producer = new Producer();
// have observer listen to producer here
});
HOT is when your observable closes over the producer
Hot
๋ฐฉ์์ Observable
๋ฐ์์ producer
๊ฐ ์กด์ฌํ ๋๋ฅผ ์ผ์ปซ์
// HOT ๐ฅ
var producer = new Producer();
var hot = new Observable((observer) => {
// have observer listen to producer here
});
Getting deeper into whatโs going onโฆ
Hot
๊ณผ Cold
? ์ด๊ฒ์ด ๋ฌด์จ ์๋ฏธ์ธ์ง ์์ธํ ์์๋ณด์โฆ
Observable ๋ง๋ค๋ฉด์ Observable ๋ฐฐ์ฐ๊ธฐ ๋ผ๋ ํฌ์คํธ์์ Observable
์ด ๋จ์ํ function
์์ ์ค๋ช
ํ๋ค. ๊ทธ ํฌ์คํธ์์์ ๋ชฉํ๋ Observable
์์ฒด์ ๋ํ ์ค๋ช
์ด์๋๋ฐ, ๋๋ถ๋ถ์ ์ฌ๋๋ค์ด Observable
์ ๋ํด ํผ๋ํ๊ณ ์๋ Hot
๊ณผ Cold
์ ๊ฐ๋
์ ๋ํด์๋ ์ค๋ช
ํ์ง ์์๋ค.
Observables are just functions!
Observable
์ ๊ทธ๋ฅ ํจ์์ผ ๋ฟ์ด๋ค.
Observable
์ producer
์ observer
๋ฅผ ์๋ก ์ฎ์ด์ฃผ๋ ํจ์์ผ ๋ฟ์ด๋ค. ๊ทธ๊ฒ ๋ค๋ค. Observable
๋ด๋ถ์์ ํ์์ ์ผ๋ก producer
๋ฅผ ์์ฑํ ํ์๋ ์๊ณ , ๋จ์ง producer
๋ฅผ ์์ ํ๋ observer
๋ฅผ ์ค์ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋์ ์ผ๋ฐ์ ์ผ๋ก๋, listenr
๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ํ ๋ถํด ๋ฉ์ปค๋์ฆ์ ๋ฐํํ๋ค. (์ญ์ ์ฃผ : ์๋ง complete
๋ฅผ ์๋ฏธํ๋ ๊ฒ ๊ฐ๋ค) subscription
ํ๋ ํ์๋ Observable
์ ํจ์์ฒ๋ผ ํธ์ถํ๊ณ , ๊ตฌ๋
๊ฐ๋ค์ Observer
์๊ฒ ์ ๋ฌํ๋ ๊ฒ์ด๋ค.
Whatโs a โProducerโ?
Producer
๊ฐ ๋ฌด์์ธ๊ฐ?
Producer
๋ Observable
์ ๋ฐํ๋ ๊ฐ๋ค์ ์์ฒ(source)์ด๋ค. Websocket
์ด ๋ ์๋ ์๊ณ , DOM events
๊ฐ ๋ ์๋ ์์ผ๋ฉฐ, iterator
๊ฐ ๋ ์๋ ์๊ณ , ๋จ์ํ array
๋ฅผ ์ํํ๋ ๊ฒ์ผ ์๋ ์๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก, Observer.next(value)
์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ์ ๋ฌ๋๋ ๋ชจ๋ ํํ์ ๊ฐ์ ์์ฑํ๋ ๊ฒ์ ๋ปํ๋ค.
Cold Observables: Producers created inside
Cold Observable
: Producer
๊ฐ ๋ด๋ถ์ ์ผ๋ก ์์ฑ๋จ
Cold Observable
์ ๊ตฌ๋
์ค์ producer
๊ฐ ์์ฑ๋๊ณ ํ์ฑํ ๋๋ Observable
์ ๋ปํ๋ค. ์ฆ, ์์ ์ธ๊ธํ๋ฏ์ด Observable
์ function
์ ๋น์ ํ์๋ฉด ํจ์ ํธ์ถ์ ํตํด์ producer
๊ฐ ์์ฑ๋๊ณ ํ์ฑํ๋๋ ๊ฒ์ ์๋ฏธํ๋ค.
- โ creates the producer (producer๋ฅผ ์์ฑ)
- โก activates the producer (producer๋ฅผ ํ์ฑํ)
- โข starts listening to the producer (producer ์์ ์ ์์)
- โฃ unicast (๋จ์ผ ๋ฐ์ ์ <-> ๋จ์ผ ์์ ์)
Observable
์ ๊ตฌ๋
ํ๋ ์๊ฐ์์์ผ Observable
์ ์ธ ๋ด๋ถ์์ WebSocket
์ด ์์ฑ๋๊ณ ์์ ๋๋ฏ๋ก, ์๋์ ์์ ๋ cold
๋ก ์์ฑ๋ ๊ฒ์ด๋ค.
const source = new Observable((observer) => {
const socket = new WebSocket("ws://someurl");
socket.addEventListener("message", (e) => observer.next(e));
return () => socket.close();
});
์ด๋ค ๊ฒ์ด๋ ์ ์์ ์ฝ๋์ source
๋ผ๋ ๋ณ์์ Observable
์ ๊ตฌ๋
ํ๋ฉด, ๊ทธ ๊ตฌ๋
์ ๋ํ ๋
๋ฆฝ์ ์ธ WebSocket Instance
๋ฅผ ๊ฐ์ง๊ฒ ๋๋ ๊ฒ์ด๊ณ , ๊ตฌ๋
์ ํด์ง(unsubscribe)ํ๋ฉด, ์์ผ ์ฐ๊ฒฐ์ close()
ํ ๊ฒ์ด๋ค. ์ด๊ฒ ๋ฐ๋ก source
๊ฐ unicast
๋ฐฉ์์ผ๋ก ๊ตฌํ๋์ด ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค. producer
๊ฐ ์ค์ง ํ observer
์๊ฒ๋ง ๊ฐ์ ๋ฐํํด์ค ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. (Cold Observable Example Codes JSBin)
Hot Observables: Producers created outside
Hot Observable
: Producer
๊ฐ ์ธ๋ถ์์ ์์ฑ๋จ
๊ตฌ๋
์ ๋ฐ๊นฅ ๋ถ๋ถ์์ ์์ฑ๋๊ณ ํ์ฑํ๋๋ producer
๋ฅผ ์ด์ฉํ๋ Observable
์ Hot Observable
์ด๋ผ ์นญํ๋ค.
- โ shares a reference to a producer (
producer
์ ๊ฐ์share
ํ๋ ํํ) - โก starts listening to the producer (
producer
์ ๋ฐํ์ ์์ ํ๊ธฐ ์์) - โข multicast (๋ณต์์ ์์ ์)
๋ค์ ์์ ์ฝ๋์ ๊ฐ์ด, WebSocket
์ ์์ฑ์ Observable
์ ์ ์ ์ธ๋ถ์ ํ๋ค๋ฉด hot Observable
์ด ๋๋ค.
const socket = new WebSocket("ws://someurl");
const source = new Observable((observer) => {
socket.addEventListener("message", (e) => observer.next(e));
});
์ด์ source
๋ณ์์ producer
๋ฅผ ๊ตฌ๋
ํ๋ ๋ชจ๋ ๊ฒ๋ค์ ๊ฐ์ WebSocket Instance
๋ฅผ ๊ณต์ ํ๋ ๊ฒ์ด๋ค. ๋ชจ๋ ๊ตฌ๋
์๋ค์๊ฒ unicast
๋๊ณ ์๋ ๊ฒ์ด๋ค. ๊ทธ๋ฐ๋ฐ, ์ด ๋ฐฉ๋ฒ์ ๋ฌธ์ ์ ์ ๋ ์ด์ Observable
์ด WebSocket
์ ๊ดํ ์ฐ์ฐ์ ํ ์ ์๋ค. ๊ทธ๋ฌ๋๊น, Observable
๋ก๋ error
๋ complete
๋ unsubscribe
๋ฅผ ํ ์ ์๋ค. ๋ ์ด์ Observable
๋ก๋ ์์ผ์ ๋ซ์ ์ ์๋ค. ์ฐ๋ฆฌ๊ฐ ์ง์ง ์ํ๋ ๊ฒ์ ์ฐ๋ฆฌ๋ค์ cold Observable
์ hot
์ ํํ๋ก ๋ง๋๋ ๊ฒ์ด๋ค. (์ญ์ ์ฃผ : producer
๋ฅผ Observable
๋ด๋ถ์ ์ ์ธํ๋, unicast
๋ฐฉ์์ด ๋๊ธฐ๋ฅผ ์ํ๋ค๋ ์๋ฏธ๋ก ๋ณด์) (Hot Observable Example Codes JSBin)
Why Make A โHotโ Observable?
์ Hot Observable
์ ์์ฑํ๋๊ฐ?
Cold Observable
์ ์์ ์์ ๋ณด์๋ฏ์ด, ๋ชจ๋ ๋์ ๋ชจ๋ Observable
์ Cold
๋ก ๊ตฌํํ๋ ๊ฒ์ ๋ฌธ์ ๊ฐ ์์ด๋ณด์ผ ๊ฒ์ด๋ค. ํ ๊ฐ์ง ์๋ฅผ ๋ค์ด, WebSocket
์ฐ๊ฒฐ์ ํตํด ์์ ๋๋ ๊ฐ์ ํ์์ ์ง์๋ก ๊ตฌ๋ถํด์ผํ๋ค๊ณ ์๊ฐํด๋ณด์. ์ด ๊ฒฝ์ฐ 2 ๊ฐ์ Observable
์ ์์ฑํ๊ณ 2๊ฐ์ ๊ตฌ๋
์ ํด์ผํ๋ ๋ฌธ์ ๊ฐ ์๋ค. ํ ๋ฒ์ ๊ตฌ๋
์ ํตํด ๋ถ๋ฅํ๋ ๊ฒ์ด ์ปดํจํ
์์์ ํจ์จ์ ์ผ๋ก ํ์ฉํ๋ ๊ฒ์์ ์๋ช
ํ๋ค.
source.filter((x) => x % 2 === 0).subscribe((x) => console.log("even", x));
source.filter((x) => x % 2 === 1).subscribe((x) => console.log("odd", x));
// ๋ ๋ฒ์ ๊ตฌ๋
์ด ๋ฐ์ํจ
Rx Subjects
Cold Observable
์ Hot
์ผ๋ก ๋ง๋ค๊ธฐ ์ ์, (multicast
๋ก ๋์ํ๋๋ก ๋ง๋ค๊ธฐ ์ ์,) rx
์ Subject
ํ์
์ ๋ํด ์์๋ณด์. Subject
๋ ๋ค์๊ณผ ๊ฐ์ ์์ฑ์ด ์๋ค.
- โ
Observable
์ด๋ค.Observable
๊ณผ ํํ๊ฐ ์ ์ฌํ๊ณ , ์ ์ฉํ ์ ์๋Operator
๋ํ ์์ ๋์ผํ๋ค. - โก
Observer
์ด๋ค.Observer
๋ฅผduck-typing
ํ๋ค. ์ฆ,Observer
์ฒ๋ผ ๋์ํ๋ค.Observable
๋ก์ ๊ตฌ๋ ๋๋ฉด,next()
๋ก ์ ๋ฌํ๋ ๊ฐ์ ๋ฐํ ๋ฐ ์์ ์ ๋์์ ํ๋ค. - โข
multicast
ํ๋ค.subscribe()
๋ฅผ ํตํด ์ ๋ฌ๋ ๋ชจ๋Observer
๊ฐ ๋ด๋ถObserver
๋ฆฌ์คํธ์ ๋ฑ๋ก๋๋ค. - โฃ ๋๋๋ฉด ๋๋๊ฑฐ๋ค.
Subjcet
๋unsubscribe
,complete
,error
์ดํ์๋ ์ฌ์ฌ์ฉ๋ ์ ์๋ค. - โค ๋ฐ๋ก ์์ 2๋ฒ ์์ ์ธ๊ธํ๋ฏ์ด, ๊ทธ ์์ฒด๋ก ๊ฐ์ ๋ฐํํ๋ฉด์๋ ์์ ๋ ํ๋ค.
์ผ๋ฐ์ ์ผ๋ก, Subject
๋ 4๊ฐ์ Observer-Pattern ์์์ addObserver
๋ฉ์๋์ ํจ๊ป ๊ฐ์ฒด๋ก ์ ์ ๋์ด์๋ค. ์ฌ๊ธฐ์๋ addObserver
๋ฉ์๋๊ฐ subscribe
๋ก ๊ตฌํ๋์ด์๋ค. (Rx Subject Behavior JSBin)
Making A Cold Observable Hot
Cold Observable
์ Hot
์ผ๋ก ๋ง๋ค๊ธฐ
Subject
์ ๋ํ ์ดํด๋ฅผ ๋ฐํ์ผ๋ก, functional Programming
์ ๋ฐฉ๋ฒ์ ์ฝ๊ฐ ์ฌ์ฉํด์ Cold Observable
์ Hot
์ผ๋ก ๋์ํ๋๋ก ๋ง๋ค ์ ์๋ค.
function makeHot(cold) {
const subject = new Subject();
cold.subscribe(subject);
return new Observable((observer) => subject.subscribe(observer));
}
์ ์์ ์ makeHot
ํจ์๋ฅผ ํตํด์, ์ด ํจ์์ ์ด๋ค Cold Observable
์ด๋ ๊ฐ์ ์ธ์๋ก ์ ๋ฌํด์ Subject
๋ฅผ ์์ฑํ์ฌ Hot
์ผ๋ก ๋ฐ๊ฟ ์ค ์ ์๋ค. (Cold -> Hot Example Codes JSBin)
๊ทธ๋ผ์๋ ์์ง ๋ฌธ์ ์ ์ ์๋๋ฐ, ๊ตฌ๋
์ด source
๋ฅผ ํธ๋ํนํ๊ณ ์์ง ์๋ค. ์ด๋ป๊ฒ ํด๋น Observable
์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ์์ ์ ํด์ ๋ฐ ์ข
๋ฃ (tear down) ํ ์ ์์๊น? ์ด๋ฅผ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ด reference counting
์ ์ด์ฉํด ๊ตฌํํ๋ค.
function makeHotRefCounted(cold) {
const subject = new Subject();
const mainSub = cold.subscribe(subject);
let refs = 0;
return new Observable((observer) => {
refs++;
let sub = subject.subscribe(observer);
return () => {
refs--;
if (refs === 0) mainSub.unsubscribe();
sub.unsubscribe();
};
});
}
์ด์ Observable
์ hot
์ผ๋ก ๊ตฌํํ๊ณ , ์ํ ๋์ Observable
์ ์ข
๋ฃ์ํฌ ์ ์๋ค. refs๋ผ๋ ๋ณ์๊ฐ -0 ์ด๋๋ฉด Cold Observable
์ source
๊ฐ ์ ๋๋ก unsubscribe
๋ ๊ฒ์ด๋ค. (Cold -> Hot Example Codes with Reference Counting JSBin)
In RxJS, Use publish()
or share()
RxJS
์์๋ publish()
๋ share()
๋ฅผ ์ด์ฉํ๋ฉด ๋๋ค.
์์ ๊ตฌํ์ฒ๋ผ makeHot
ํจ์๋ ์๋ง๋ ์ฌ์ฉ๋์ง ์์ ๊ฒ์ด๋ค. ๊ฐ์ ๋์์ด publish()
๋ share()
๋ผ๋ operator
๋ก ๊ตฌํ๋์ด ์๊ธฐ ๋๋ฌธ์ด๋ค. Cold Observable
์ hot
์ผ๋ก ๋์ํ๊ฒ ํ๋ ๋ฐฉ๋ฒ์ ์์ฃผ ๋ง๋ค. ๊ทธ๋์ RxJS
๋ ๊ทธ๋ฌํ ๋์์ ํจ์จ์ ์ด๊ณ ๊ฐ๊ฒฐํ๊ฒ ๋์ํ๊ฒ๋ operator
๋ก ๊ตฌํํด ๋์ ๊ฒ์ด๋ค.
RxJS 5
์์ share()
์ฐ์ฐ์๋ Observable
์ hot
์ผ๋ก ๋ง๋ค์ด์ฃผ๋ฉฐ, refCounted Observable
์ด ์คํจ์์๋ ์ฌ์๋๋ฅผ, ์ฑ๊ณต์์๋ ๋ฐ๋ณตํ๋๋ก ๊ตฌํ๋์ด์๋ค. ์ด๋ Subject
๋ ์๋ฌ๊ฐ ๋ฐ์ํ๊ฑฐ๋ ์๋ฃ๋๊ฑฐ๋ ๊ตฌ๋
ํด์ง ๋๋ ๊ฒฝ์ฐ์๋ ์ฌ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. share()
์ฐ์ฐ์๋ ์ฃฝ์ Subject
๋ฅผ ์ฌํ์ฉํ๊ธฐ ์ํด์ ์ฌ๊ตฌ๋
์ ๊ฐ๋ฅํ๊ฒ๋ ๊ตฌํ๋์๋ค.
The โWarmโ Observable
๋ฐ๋ปํ Observable
ํ๋์ ๊ตฌ๋
์ผ๋ก ์ฒ๋ฆฌ ํ ์ ์๋ ๊ฒ์ ๋ ๊ฐ์ Subject
๋ฅผ ๋ง๋ค์ด์ผ ํ๋ ์ผ์ ๋์ ๋ฏธ์ ์ด๋ค.
โHotโ and โColdโ Are All About The Producer
โHotโ๊ณผ โColdโ๊ฐ producer
์ ์ ๋ถ์ด๋ค.
Observable
์์์ shared reference
๋ฅผ close
ํ๋ค๋ฉด, hot
๋ฐฉ์์ด๋ค. Observable
๋ด๋ถ์์ ์๋ก์ด producer
๋ฅผ ์์ฑํ๋ค๋ฉด cold
๋ฐฉ์์ด๋ค. ๋ง์ฝ์ ๋๋คํ๋ค๋ฉดโฆ ๋ญ ํ๋๊ฑฐ์ง? ์๋ง๋ Warm
๋ฐฉ์์ธ ๊ฒ ๊ฐ๋ค.
TL;DR
์ง์ producer
๋ฅผ ๊ณ์ํด์ ์์ฑํ ๊ฒ์ด ์๋๋ผ๋ฉด, Observable
์ HOT
๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๊ฒ ๋ ๊ฒ์ด๋ค.
References
Hot vs Cold Observables ์๋ฌธ
Observable ๋ง๋ค๋ฉด์ Observable ๋ฐฐ์ฐ๊ธฐ
Cold Observable Example Codes JSBin
Hot Observable Example Codes JSBin
Cold -> Hot Example Codes JSBin