ReplaySubject

๐Ÿ” ReplaySubject โ€” ๊ฐ’ N๊ฐœ๋ฅผ โ€˜๋˜๊ฐ๊ธฐโ€™ํ•˜๋Š” ์บ์‹œ Subject

ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ: Buffer Size ยท Hot Stream ยท Late Subscriber Catchโ€‘up

ReplaySubject<Element>๋Š” ์ง€์ •ํ•œ ๋ฒ„ํผ ํฌ๊ธฐ๋งŒํผ ๊ณผ๊ฑฐ ๊ฐ’์„ ์ €์žฅํ•˜์—ฌ, ์ƒˆ๋กœ์šด ๊ตฌ๋…์ž์—๊ฒŒ ํ•œ๊บผ๋ฒˆ์— ์žฌ์ƒ(Replay)ํ•ฉ๋‹ˆ๋‹ค. ๋™์˜์ƒ ํ”Œ๋ ˆ์ด์–ด์˜ โ€˜๋˜๊ฐ๊ธฐโ€™์ฒ˜๋Ÿผ ์ด์ „ ์ด๋ฒคํŠธ ์ปจํ…์ŠคํŠธ๊ฐ€ ์ค‘์š”ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.


1๏ธโƒฃ ํŠน์ง• ํ•œ๋ˆˆ์— ๋ณด๊ธฐ

ํ•ญ๋ชฉ
์„ค๋ช…

์ดˆ๊ธฐ๊ฐ’

โŒ (์˜ต์…˜)

๋ฒ„ํผ ํฌ๊ธฐ

1 ~ โˆž (bufferSize:)

๊ตฌ๋… ์‹œ ์ „๋‹ฌ

๋ฒ„ํผ ๋‚ด ๋ชจ๋“  ์ด๋ฒคํŠธ ์žฌ์ƒ ํ›„ ์‹ค์‹œ๊ฐ„ ์ˆ˜์‹ 

์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ

.onCompleted() / .onError() ํ›„ ๋ฒ„ํผ ํ•ด์ œ

๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ Int.max๋กœ ์„ค์ •ํ•˜๋ฉด ์ „์ฒด ๊ธฐ๋ก์„ ์žฌ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋‚˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์— ์œ ์˜ํ•˜์„ธ์š”.


2๏ธโƒฃ ๊ธฐ๋ณธ ์‚ฌ์šฉ ์˜ˆ์ œ

// ์ตœ๊ทผ 2๊ฐœ ๊ฐ’ ์บ์‹œ
let subject = ReplaySubject<String>.create(bufferSize: 2)
let bag = DisposeBag()

subject.onNext("1๏ธโƒฃ One")
subject.onNext("2๏ธโƒฃ Two")
subject.onNext("3๏ธโƒฃ Three")

// ๊ตฌ๋…์ž๋Š” Two, Three๋ถ€ํ„ฐ ์ˆ˜์‹ 
subject
    .subscribe(onNext: { print($0) })
    .disposed(by: bag)

subject.onNext("4๏ธโƒฃ Four")

์ถœ๋ ฅ

2๏ธโƒฃ Two
3๏ธโƒฃ Three
4๏ธโƒฃ Four

3๏ธโƒฃ ์‹ค์ „ ํŒจํ„ด โ€” ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€ ์บ์‹ฑ

final class ChatRoomService {
    private let messageSubject = ReplaySubject<Message>.create(bufferSize: 50)
    private let bag = DisposeBag()

    // ์™ธ๋ถ€ ๋…ธ์ถœ ์ŠคํŠธ๋ฆผ
    var messages: Observable<[Message]> {
        messageSubject
            .scan([]) { acc, new in acc + [new] }
    }

    func receive(message: Message) {
        messageSubject.onNext(message)
    }
}

// ์ƒˆ๋กœ ๋“ค์–ด์˜จ ์‚ฌ์šฉ์ž๋„ ์ตœ๊ทผ 50๊ฐœ ๋ฉ”์‹œ์ง€ ์ฆ‰์‹œ ํ‘œ์‹œ ๊ฐ€๋Šฅ

4๏ธโƒฃ ๋ฉ”๋ชจ๋ฆฌ & ํผํฌ๋จผ์Šค ์ตœ์ ํ™”

  1. ๋ฒ„ํผ ํฌ๊ธฐ: ์‹ค์ œ UI/๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ ๋ฒ”์œ„๋กœ ์ œํ•œ โ€” ๋ฌด์ œํ•œ X.

  2. windowTime:: ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ ์บ์‹ฑ(create(bufferSize:timeScheduler:))๋กœ ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ ์ž๋™ ์ œ๊ฑฐ.

  3. ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ ์ฒ˜๋ฆฌ: ๋ฐฉ ๋‚˜๊ฐ€๊ธฐ ๋“ฑ ํ•„์š” ์‹œ .onCompleted() ํ˜ธ์ถœํ•ด ๋ฒ„ํผ ํ•ด์ œ.


5๏ธโƒฃ Subject ๊ฐ„ ๋น„๊ต ์š”์•ฝ

Subject
์บ์‹œ ํฌ๊ธฐ
์ดˆ๊ธฐ๊ฐ’
์‚ฌ์šฉ ์‚ฌ๋ก€

PublishSubject

0

โŒ

๋ฒ„ํŠผ ํƒญ, ์•Œ๋ฆผ

BehaviorSubject

1

โœ”๏ธ

ํ† ๊ธ€ ์ƒํƒœ, Form Validation

ReplaySubject

n

โŒ

์ฑ„ํŒ… ํžˆ์Šคํ† ๋ฆฌ, ๋กœ๊ทธ ์žฌ์ƒ

AsyncSubject

1 (์™„๋ฃŒ ์‹œ์ )

โŒ

ํŒŒ์ผ ์—…๋กœ๋“œ ๊ฒฐ๊ณผ, ๋‹จ์ผ ์‘๋‹ต


6๏ธโƒฃ Mini Quiz

  1. ๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ 3์œผ๋กœ ์„ค์ •ํ–ˆ๋Š”๋ฐ ์ด๋ฒคํŠธ๋ฅผ 5๊ฐœ ๋ฐœํ–‰ ํ›„ ์ƒˆ๋กœ ๊ตฌ๋…ํ•˜๋ฉด ๋ช‡ ๊ฐœ๋ฅผ ๋ฐ›๋‚˜์š”?

  2. ReplaySubject์˜ ๋ฒ„ํผ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณผ๋„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋„๋ก ๋‘ ๊ฐ€์ง€ ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์€?

  3. Combine์—์„œ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ๋‹ด๋‹นํ•˜๋Š” Subject๋Š”?

์ •๋‹ต
  1. 3๊ฐœ โ€” ๊ฐ€์žฅ ์ตœ๊ทผ 3๊ฐœ(์ด๋ฒคํŠธ #3, #4, #5)๋ฅผ ์žฌ์ƒ ํ›„ ์ดํ›„ ์‹ค์‹œ๊ฐ„ ๊ฐ’ ์ˆ˜์‹ .

  2. ์ตœ์ ํ™” ๋ฐฉ๋ฒ•

    • ๋ฒ„ํผ ํฌ๊ธฐ๋ฅผ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ์ž‘๊ฒŒ ์„ค์ • (bufferSize).

    • ์‹œ๊ฐ„ ์ œํ•œ windowTime ์ธ์ž๋ฅผ ์‚ฌ์šฉํ•ด ์˜ค๋ž˜๋œ ์ด๋ฒคํŠธ๋ฅผ ์ž๋™ ์ œ๊ฑฐ(.create(bufferSize:timeInterval:scheduler:)).

  3. Combine์˜ ReplaySubject(Swift 5.10, CombineExt) ๋˜๋Š” ์„œ๋“œํŒŒํ‹ฐ CombineExt ํŒจํ‚ค์ง€์˜ ReplaySubject๊ฐ€ ์œ ์‚ฌ ๋™์ž‘์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.


๋‹ค์Œ ๋ฌธ์„œ โ–ถ๏ธ AsyncSubject ๋กœ ์ด๋™ํ•ด ์™„๋ฃŒ ์‹œ์  ๋‹จ์ผ ๊ฐ’ ์ „๋‹ฌ ํŒจํ„ด์„ ์•Œ์•„๋ด…๋‹ˆ๋‹ค. ๐Ÿš€

Last updated