android,

Cold Observable vs Hot Observable

Ella Ella Follow Dec 13, 2021 ยท 3 mins read
Cold Observable vs Hot Observable
Share this

๐Ÿค–

๊ฐœ๋… 6๏ธโƒฃ Cold Observable vs Hot Observable

RxJava์—์„œ๋Š” Observable์„ subscribeํ•˜๋Š” Observer๊ฐ€ ์กด์žฌํ•œ๋‹ค. Observer๋Š” Observable์ด ์ˆœ์ฐจ์ ์œผ๋กœ ๋ฐœํ–‰ํ•˜๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด์„œ ๋ฐ˜์‘ํ•œ๋‹ค. Observable์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์‹์—์„œ Observable๊ณผ Observer ์‚ฌ์ด์— ๋™์ž‘ ์ฐจ์ด๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด๋ฅผ Cold Observable๊ณผ Hot Observable์ด๋ผ๊ณ  ํ•œ๋‹ค.

1๏ธโƒฃ Cold Observable

Cold Observable์€ Observable์— ๊ตฌ๋…์„ ์š”์ฒญํ•˜๋ฉด ์•„์ดํ…œ์„ ๋ฐœํ–‰ํ•˜๊ธฐ ์‹œ์ž‘ํ•œ๋‹ค. ์•„์ดํ…œ์€ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ๋ฐœํ–‰๋˜๊ณ , ์ž„์˜๋กœ ์ข…๋ฃŒ์‹œํ‚ค์ง€ ์•Š๋Š” ์ด์ƒ ์—ฌ๋Ÿฌ ๋ฒˆ ์š”์ฒญํ•ด๋„ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ๋ฐœํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•œ๋‹ค. interval ์—ฐ์‚ฐ์ž๋ฅผ ์ด์šฉํ•˜์—ฌ 1์ดˆ๋งˆ๋‹ค ์•„์ดํ…œ์„ ๋ฐœํ–‰ํ•˜๋Š” Cold Observable ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•ด๋ณด์ž.

 val src = Observable.interval(1, TimeUnit.SECONDS)
        src.subscribe{
                value -> println("#1: $value")
        }
        Thread.sleep(3000)
        src.subscribe {
                value -> println("#2: $value")
        }
        Thread.sleep(3000)
#1: 0
#1: 1
#1: 2
#1: 3
#2: 0
#1: 4
#2: 1
#1: 5
#2: 2

Observable์„ ๊ตฌ๋…ํ•˜๊ณ  3์ดˆ ๋’ค์— ์ƒˆ๋กœ์šด ๊ตฌ๋…์ž๋กœ ๋‹ค์‹œ ๊ตฌ๋…ํ–ˆ์„ ๋•Œ๋„ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์•„์ดํ…œ์„ ๋ฐœํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

2๏ธโƒฃ Hot Observable

๋ฐ˜๋ฉด์— Hot Observable์€ ์•„์ดํ…œ ๋ฐœํ–‰์ด ์‹œ์ž‘๋œ ์ดํ›„๋กœ ๋ชจ๋“  ๊ตฌ๋…์ž์—๊ฒŒ ๋™์‹œ์— ๊ฐ™์€ ์•„์ดํ…œ์„ ๋ฐœํ–‰ํ•œ๋‹ค. ๋งŒ์•ฝ์— ์ฒซ ๋ฒˆ์งธ ๊ตฌ๋…์ž๊ฐ€ ์•„์ดํ…œ์„ ๋ฐœํ–‰ํ•˜๋Š” Observable๋ฅผ ๊ตฌ๋…ํ•˜๊ณ , ๋ช‡ ์ดˆ ๋’ค์— ๋‘ ๋ฒˆ์งธ ๊ตฌ๋…์ž๊ฐ€ ๋˜‘๊ฐ™์€ Observable์„ ๊ตฌํ•œ๋‹ค๋ฉด, ๋‘˜์€ ๊ฐ™์€ ์•„์ดํ…œ์„ ๋™์‹œ์— ์ˆ˜์‹ ํ•˜์ง€๋งŒ, ๋‘ ๋ฒˆ์งธ ๊ตฌ๋…์ž๋Š” ๊ตฌ๋…ํ•˜๊ธฐ ์ „์— ๋ฐœํ–‰๋œ ์•„์ดํ…œ์„ ๋†“์น  ์ˆ˜ ์žˆ๋‹ค.

Subject

Subject๋Š” Observable๊ณผ Observer๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•œ ์ถ”์ƒ ํƒ€์ž…์ด๋ฉฐ, ํ•˜๋‚˜์˜ ์†Œ์Šค์—์„œ ์—ฌ๋Ÿฌ ๊ตฌ๋…์ž์—๊ฒŒ ๋ฉ€ํ‹ฐ์บ์ŠคํŒ…์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. Subject๋Š” Observer๋ฅผ ๊ตฌํ˜„ํ•˜๋ฏ€๋กœ, onNext(), onError(), onComplete() ๋ฉ”์†Œ๋“œ๋ฅผ ์ˆ˜๋™์œผ๋กœ ํ˜ธ์ถœํ•˜์—ฌ ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…์ž๋“ค์—๊ฒŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. Subject๋ฅผ ๊ตฌํ˜„ํ•œ ํƒ€์ž… ์ค‘์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์“ฐ์ด๋Š” (1) PublishSubject์™€ (2) BehaviorSubject์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

1๏ธโƒฃ PublishSubject

PublishSubject๋Š” Subject๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ํƒ€์ž… ์ค‘ ํ•˜๋‚˜์ด๋‹ค. PublishSubject ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ฐ„๋‹จํžˆ ์ด๋ฒคํŠธ๋ฅผ ๋ธŒ๋กœ๋“œ์บ์ŠคํŒ…ํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ํ™•์ธํ•ด๋ณด์ž.

val src: Subject<String> = PublishSubject.create()
        src.subscribe({item -> println("A: $item")},
            {t -> Timber.e(t)},
            { -> println("A: onComplete")})
        src.subscribe({item -> println("B: $item")},
            {t -> Timber.e(t)},
            { -> println("B: onComplete")})
        src.onNext("Hello")
        src.onNext("World")
        src.onNext("!!!")
        src.onComplete()
A: Hello
B: Hello
A: World
B: World
A: !!!
B: !!!
A: onComplete
B: onComplete

create() ๋ฉ”์†Œ๋“œ๋กœ Subject ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ–ˆ๋‹ค. Subject๋Š” Observable์ด๋ฉด์„œ, Observer์ด๋ฏ€๋กœ ๋ฐœํ–‰๊ณผ ๊ตฌ๋…์„ ๋ชจ๋‘ Subject ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค(onNext, subscribe). Subject๋ฅผ ์ด์šฉํ•  ๋•Œ ์ฃผ์˜ํ•  ์ ์€ Subject๊ฐ€ Hot Observable์ด๋ผ๋Š” ๊ฒƒ์ด๋‹ค.
์•„๋ž˜์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ์•„์ดํ…œ์„ ๋ฐœํ–‰ํ•œ ๋’ค ๊ตฌ๋…ํ•˜๋ฉด ์•„์ดํ…œ์„ 1๋„ ์†Œ๋น„ํ•  ์ˆ˜ ์—†๋‹ค.

 val src: Subject<String> = PublishSubject.create()
        src.onNext("Hello")
        src.onNext("World")
        src.onNext("!!!")
        src.onComplete()
        src.subscribe({item -> println("A: $item")},
            {t -> Timber.e(t)},
            { -> println("A: onComplete")})
        src.subscribe({item -> println("B: $item")},
            {t -> Timber.e(t)},
            { -> println("B: onComplete")})
A: onComplete
B: onComplete

Subject๋Š” Observer์ด๊ธฐ๋„ ํ•˜๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ Observable์˜ ๊ตฌ๋…์ž๋กœ์„œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์†Œ๋น„ํ•˜๋Š” ์•„์ดํ…œ์€ ๋‹ค์‹œ Observable๋กœ ๊ตฌ๋…ํ•˜์—ฌ ๋‹ค๋ฅธ ๊ตฌ๋…์ž์—๊ฒŒ ์ „๋‹ฌํ•˜๋Š” ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•ด๋ณด์ž.

val src1 = Observable.interval(1, TimeUnit.SECONDS)
        val src2 = Observable.interval(500, TimeUnit.MILLISECONDS)
        val subject: Subject<String> = PublishSubject.create()

        src1.map{item -> "A: $item"}.subscribe(subject)
        src2.map{item -> "B: $item"}.subscribe(subject)
        subject.subscribe(System.out::println)
        Thread.sleep(5000)
B: 0
B: 1
A: 0
B: 2
B: 3
A: 1
B: 4
B: 5
A: 2
B: 6
A: 3
B: 7
B: 8
B: 9
A: 4

์œ„์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด PublishSubject์ธ subject๋ฅผ ํ†ตํ•ด ๊ตฌ๋…ํ•˜๊ณ  ์•„์ดํ…œ์„ ์žฌ๋ฐœํ–‰ํ•˜๋ฉฐ, ๋‘ Observable ์†Œ์Šค๋ฅผ ๋ฌถ์–ด์„œ ์ด๋ฒคํŠธ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค(System.out::println์œผ๋กœ src1+src2 ์•„์ดํ…œ์ด ๊ฐ™์ด ๋‚˜์˜ด!).

2๏ธโƒฃ BehaviorSubject

๋˜ ๋‹ค๋ฅธ Subject์˜ ์„œ๋ธŒ ํด๋ž˜์Šค๋กœ BehaviorSubject๊ฐ€ ์žˆ๋‹ค. BehaviorSubject๋Š” PublishSubject์™€ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•˜์ง€๋งŒ, ์ƒˆ๋กœ์šด Observer๋ฅผ ํ†ตํ•ด ๊ตฌ๋…ํ•  ๋•Œ, ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ์•„์ดํ…œ๋งŒ์„ ๋ฐœํ–‰ํ•œ๋‹ค๋Š” ์ฐจ์ด์ ์ด ์žˆ๋‹ค. BehaviorSubject๋Š” ๊ฐ€์žฅ ์ตœ๊ทผ ์ƒํƒœ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 val subject: Subject<Int> = BehaviorSubject.create()
        subject.subscribe{item->println("A: $item")}
        subject.onNext(1)
        subject.onNext(2)
        subject.subscribe{item->println("B: $item")}
        subject.onNext(3)
        subject.subscribe{item->println("C: $item")}
A: 1
A: 2
B: 2
A: 3
B: 3
C: 3

์œ„์—์„œ ํ™•์ธํ•œ ๊ฒƒ๊ณผ ๊ฐ™์ด BehaviorSubject๋Š” ๊ตฌ๋…์„ ์‹œ์ž‘ํ•  ๋•Œ Subject๊ฐ€ ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฐœํ–‰ํ•œ ์•„์ดํ…œ์„ ๊ฐ€์ ธ์˜ค๋ฉฐ, ์ดํ›„์— ๋ฐœํ–‰๋˜๋Š” ์•„์ดํ…œ๋“ค์€ ๋ชจ๋‘ PublishSubject์™€ ๋™์ผํ•˜๊ฒŒ ๋ชจ๋‘ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค.

Join Newsletter
Get the latest news right in your inbox. We never spam!
Ella
Written by Ella Follow
Android Developer, love to explore new ideas and write on my morning coffee!