RxSwift

1. RxSwift ๊ฐœ๋…

1) Reactive Programming์ด ๋ฌด์—‡์ธ์ง€ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.

  • Reactive Programming ์€ ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„์— ๋ฐ˜์‘ํ•˜๋ฉฐ ๋กœ์ง์„ ๊ตฌ์„ฑํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„์ž…๋‹ˆ๋‹ค.

  • ๋ฐ์ดํ„ฐ์˜ ์ƒํƒœ๋ณ€ํ™”๋‚˜, ์ด๋ฒคํŠธ์— ๋”ฐ๋ฅธ ๋กœ์ง์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • ์ด ๋•Œ, ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ์ข‹์Šต๋‹ˆ๋‹ค.

  • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๊ฒฐํ•ฉํ•ด ๊ฐ€๋…์„ฑ ์ข‹๊ณ  ์œ ์ง€๋ณด์ˆ˜ ์ข‹์€ ์ฝ”๋“œ๋ฅผ ์งœ๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

2) RxSwift ๋ฅผ ์™œ ์ผ๊ณ  ์žฅ๋‹จ์ ์ด ๋ญ๊ฐ€ ์žˆ๋‚˜์š”?

  1. ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์— ์˜ํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ž‘์—…์„ Observable ์— ๋‹ด์•„์„œ ์ž‘์„ฑํ•œ๋‹ค๋ฉด, Observable ์ด ๋ฑ‰์–ด๋‚ด๋Š” onNext, onCompleted ๋“ฑ์˜ ์ด๋ฒคํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Data Binding ์„ ํŽธํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  2. ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. map ์ด๋‚˜ filter ๋“ฑ์˜ Operator ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•˜๊ธฐ ์ข‹์Šต๋‹ˆ๋‹ค.

  3. ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๋‹ค๋ฃฐ ๋•Œ ์œ ์šฉํ•œ ํด๋ž˜์Šค๋“ค์ด ๋งŽ์Šต๋‹ˆ๋‹ค. Observable, Subject ๋“ฑ์˜ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ํšจ๊ณผ์ ์œผ๋กœ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3) RxSwift ์™€ Combine ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.

  1. RxSwift ๋Š” ์• ํ”Œ์ด ๋งŒ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. Rx๋Š” Swift ๋ฟ ์•„๋‹ˆ๋ผ Java, Python ์—์„œ๋„ ์‚ฌ์šฉ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์— Combine ์€ ์• ํ”Œ์ด ๋งŒ๋“  ๊ณต์‹ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ํŒŒ์ƒ๋˜๋Š” ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  2. RxSwift ๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ์‹œ, Rx ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค๊ณผ ์†Œํ†ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋กœ์ง์„ ํ†ต์ผ ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  3. Combine ์„ ์‚ฌ์šฉํ–ˆ์„ ์‹œ, ์ข€ ๋” ์•ˆ์ •์ ์ธ ํšจ๊ณผ๋ฅผ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋А๋‚  ๊ฐ‘์ž๊ธฐ Rx ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค๋ฉด ๊ทธ๊ฑด ์• ํ”Œ์˜ ์ฑ…์ž„์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

4) RxCocoa ๋ฅผ ์“ธ ๋•Œ ์žฅ์ ? ์–ด๋–ค ๊ฒฝํ—˜์„ ํ–ˆ๋‚˜์š”

  1. RxCocoa ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด rx.tap ์„ ํ†ตํ•ด ๋ฒ„ํŠผ ํƒญ ์ด๋ฒคํŠธ๋ฅผ Observable ๋กœ ๊ฐ„์ฃผํ•ด์„œ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  throttle ์ด๋‚˜ debounce ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// ์œ ์ € ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
searchUserButton.rx.tap
	// throttle ์ฒ˜๋ฆฌ
    .throttle(.seconds(3), latest: false, scheduler: MainScheduler.instance)
    .bind(onNext: { [weak self] in
        let searchUserViewController = SearchUserViewController()
        self?.navigationController?.pushViewController(searchUserViewController, animated: true)
  1. UITableView ์˜ delegate ๋ฉ”์„œ๋“œ๋ฅผ RxCocoa ๋ฅผ ํ†ตํ•ด ๊น”๋”ํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด tableView ์˜ willDisplay ๋ฅผ rxcocoa ๋ฅผ ํ†ตํ•ด tableView.rx.willDisplayCell { cell, index .. } ๋กœ ๊น”๋”ํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// ํ”ผ๋“œ ๋ฌดํ•œ์Šคํฌ๋กค
feedTableView.rx.willDisplayCell
	.subscribe(on: MainScheduler.instance)
	.bind { [weak self] cell, index in
		guard let self = self else { return }
        
        // ...
        
        // ํ…Œ์ด๋ธ” ๋ทฐ์˜ ๋งˆ์ง€๋ง‰ cell ์ด ๋‹ค๊ฐ€์™”์„ ๋•Œ ์ƒˆ๋กœ์šด ํ”ผ๋“œ ํŒจ์น˜
        if index.row == currentListLen - 1 {
        	self.viewModel.fetchFeedList()
       	}
}               

2. Observable

1) RxSwift ์˜ Observable ์ด๋ž€ ๋ฌด์—‡์ธ์ง€ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.

  • RxSwift ์˜ Observable ์€ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์ด๋ฉฐ, ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์˜ต์ €๋ฒ„ ํŒจํ„ด์˜ Publisher ์™€ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Observable ์„ ๊ตฌ๋…ํ•˜๊ฒŒ๋˜๋ฉด, ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ• ๋•Œ๋งˆ๋‹ค ๊ทธ์— ๊ฑธ๋งž๋Š” ํ–‰๋™์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  • next : ์ผ๋ฐ˜์ ์ธ ๋ฐ์ดํ„ฐ or ์ด๋ฒคํŠธ ๋ฐฉ์ถœ

  • error : ์—๋Ÿฌ ๋ฐฉ์ถœ, ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ

  • complete : ์„ฑ๊ณต์ ์ธ ์ด๋ฒคํŠธ ๋ฐฉ์ถœ + ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ

  • Observable ์€ Disposable ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

let observable = Observable<Int>.create { observer in
    observer.onNext(1)
    observer.onNext(2)
    observer.onNext(3)
    observer.onCompleted()
    return Disposables.create()
}

observable.subscribe(onNext: { value in
    print(value)
})

2) RxSwift์—์„œ Hot Observable๊ณผ Cold Observable์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•˜์‹œ์˜ค.

  • Hot Observable ์€ ์ด๋ฒคํŠธ๊ฐ€ ๊ตฌ๋…์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ๋ฐœ์ƒํ•˜๊ณ  ์žˆ๋‹ค๊ฐ€, ๊ตฌ๋…์„ ํ•œ ์‹œ์ ๋ถ€ํ„ฐ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„๋ณผ ์ˆ˜ ์žˆ๋Š” Observable ์ž…๋‹ˆ๋‹ค.

  • Cold Observable ์€ ๊ตฌ๋…์„ ์‹œ์ž‘ํ–ˆ์„ ๋•Œ ๋น„๋กœ์†Œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ•˜๋Š” Observable ์ž…๋‹ˆ๋‹ค. RxSwift์˜ ๊ธฐ๋ณธ Observable ์€ Cold Observable ์ž…๋‹ˆ๋‹ค.

  • Hot Observable ์€ TV ์ง€์ƒํŒŒ ๋ฐฉ์†ก, Cold Observable ์€ ๋„ทํ”Œ๋ฆญ์Šค์— ๋น„์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3) Single, Completable, Maybe์˜ ์ฐจ์ด์ ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๊ณ , ์–ธ์ œ ์ ์šฉํ•˜๋ฉด ์ข‹์„์ง€ ์„ค๋ช…ํ•˜์‹œ์˜ค.

  • ๋จผ์ € Single, Completable, Maybe ๋Š” ๋ชจ๋‘ Observable ์ž…๋‹ˆ๋‹ค.

  • Single ์€ Success / Error ๋‘˜ ์ค‘ ํ•˜๋‚˜๋งŒ์„ ์˜ค์ง ํ•œ๋ฒˆ๋งŒ ๋ฐฉ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ •ํ™•ํžˆ ํ•œ ๊ฐ€์ง€ ์š”์†Œ๋ฅผ ํ•œ ๋ฒˆ๋งŒ ๋ฐฉ์ถœํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต ํ•œ๋ฒˆ ๋ฐ›์•„์•ผํ•  ๊ฒฝ์šฐ Single ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

func fetchData() -> Single<Data> {
    return Single.create { single in
        // ... ๋„คํŠธ์›Œํฌ ์š”์ฒญ ์ฒ˜๋ฆฌ ...
        if let data = responseData {
            single(.success(data))
        } else {
            single(.error(NetworkError.failed))
        }
        return Disposables.create()
    }
}
  • Completable ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐœํ–‰ํ•˜์ง€ ์•Š์œผ๋ฉฐ, ์ž‘์—…์ด ์™„๋ฃŒ ๋˜์—ˆ์Œ์„ ๋‚˜ํƒ€๋‚ผ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ์š”์ฒญ์„ ํ•˜๊ณ , "์ „์†ก ์™„๋ฃŒ" or "์ „์†ก ์‹คํŒจ"๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

func sendData() -> Completable {
    return Completable.create { completable in
        // ... ๋ฐ์ดํ„ฐ ์ „์†ก ์ฒ˜๋ฆฌ ...
        if success {
            completable(.completed)
        } else {
            completable(.error(NetworkError.failed))
        }
        return Disposables.create()
    }
}
  • Maybe ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐœํ–‰ํ• ์ˆ˜๋„ ์žˆ๊ณ  ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฃผ๋กœ "๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€"๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ž‘์—…์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์œผ๋ฉด ๊ทธ ๊ฐ’์„ ๋ฐ˜ํ™˜, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด completed ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

func readData() -> Maybe<Data> {
    return Maybe.create { maybe in
        // ... ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ ์ฒ˜๋ฆฌ ...
        if let data = readData {
            maybe(.success(data))
        } else {
            maybe(.completed)
        }
        return Disposables.create()
    }
}

3.Disposable

1) Disposable ์˜ ๊ฐœ๋…์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”

  • RxSwift ์˜ Disposable ์€ Observable ์˜ ๊ตฌ๋…์„ ํ•ด์ œํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.

  • Observable ์€ subscribe() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ๊ตฌ๋…์„ ์‹œ์ž‘ํ•˜๊ณ , ์ด subscribe ๋ฉ”์„œ๋“œ๋Š” Disposable ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  • Disposable.dispose() ๋ฅผ ํ•˜๋ฉด ๊ตฌ๋…์ด ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.

let disposable = observable.subscribe(onNext: { value in
    print("Received value: \(value)")
})

disposable.dispose() // ๊ตฌ๋… ์ทจ์†Œ
  • ์˜ˆ๋ฅผ ๋“ค์–ด Observable ์ด UI ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•˜๋Š”๋ฐ, ์œ ์ €๊ฐ€ ๊ทธ ํ™”๋ฉด์—์„œ ๋‚˜๊ฐ„๋‹ค๋ฉด ๋” ์ด์ƒ ๊ทธ Observable ์€ ํ•„์š”๊ฐ€ ์—†์–ด์งˆ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— dispose() ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

2) DisposeBag ์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”. ์–ธ์ œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜๋‚˜์š”?

  • DisposeBag ์„ ์‚ฌ์šฉํ•˜๋ฉด, ๊ตฌ๋…์„ ํ•ด์ œํ•  ๋Œ€์ƒ๋“ค์„ ๋‹ด์•„ ํ•œ ๋ฒˆ์— dispose ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • DisposeBag ์ด Dispose() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜, DisposeBag ์ด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋  ๋•Œ, DisposeBag ์— ํฌํ•จ๋œ Disposable ๊ฐ์ฒด๋“ค์ด ํ•จ๊ป˜ ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.

  • ์ผ๋ฐ˜์ ์œผ๋กœ ViewController ๋‚˜ ViewModel ์—์„œ DisposeBag ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋  ๋•Œ DisposeBag ๋„ ํ•จ๊ป˜ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.


4. Subject, Driver, Relay

1) Observable ๊ณผ Subject ์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”

  • Observable ์€ Cold Observable ์ด๊ณ , Subject ๋Š” Hot Observable ์ž…๋‹ˆ๋‹ค.

  • Subject ๋Š” Observer ์˜ ์—ญํ• ๊ณผ Observable ์˜ ์—ญํ• ์„ ๋ชจ๋‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ฆ‰, Observable ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•  ์ˆ˜ ์žˆ๊ณ ,

  • Observer ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹  ๋ฐ›๊ณ , ๊ทธ ์ด๋ฒคํŠธ์— ๋งž๋Š” ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋‹ค์‹œ๋งํ•˜๋ฉด, Observer ๋Š” ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ์ง€ ๋ฏธ๋ฆฌ ์ •ํ•ด์ง„ ํ˜•ํƒœ์˜ ์ŠคํŠธ๋ฆผ์ด์ง€๋งŒ, Subject ๋Š” Subject ์™ธ๋ถ€์—์„œ ์ƒˆ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์ค„ ์ˆ˜๋„ ์žˆ๊ณ , ๊ตฌ๋…๋„ ํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์—ฐ์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

// ์˜ˆ์‹œ ์ฝ”๋“œ 1 : Observable ๊ณผ Subject ์˜ ๋™์ž‘ ์ฐจ์ด

// Observable
let observable = Observable<Int>.create { observer in
    observer.onNext(1)
    observer.onNext(2)
    observer.onNext(3)
    observer.onCompleted()
    return Disposables.create()
}

observable.subscribe(onNext: { value in
    print(value)
})

// Subject
let subject = PublishSubject<Int>()

subject.onNext(1)
subject.onNext(2)
subject.onNext(3)

subject.subscribe(onNext: { value in
    print(value)
})
// ์˜ˆ์‹œ ์ฝ”๋“œ 2 : ์™œ Subject ๊ฐ€ Observer ์™€ Observable ์˜ ์—ญํ• ์„ ๋ชจ๋‘ ํ•œ๋‹ค๊ณ  ํ•˜๋Š”๊ฐ€.
import RxSwift

// Observable ๋กœ์„œ "initial value" ๋ฐฉ์ถœ
let subject = BehaviorSubject(value: "initial value")

// ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ˆ˜๋™์œผ๋กœ ์‚ฝ์ž… -> Observer ๋กœ์„œ "new value" ๋ผ๋Š” ๊ฐ’์„ ์ˆ˜์‹ ํ–ˆ์Œ
subject.onNext("new value")

subject.subscribe(onNext: { value in
    print("Received value: \(value)")
})

// ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ˆ˜๋™์œผ๋กœ ์‚ฝ์ž…
subject.onNext("another value")

/* ์ถœ๋ ฅ ๊ฒฐ๊ณผ
Received value: new value
Received value: another value
*/

2) Subject์˜ ์ข…๋ฅ˜์™€ ์ฐจ์ด์ ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜์‹œ์˜ค.

  • PublishSubject ์™€ BehaviorSubject ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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

3) Subject์™€ Driver์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•˜์‹œ์˜ค.

  • Subject ์™€ Driver ๋Š” ๋ชจ๋‘ RxCocoa ์˜ Observable ์ด์ง€๋งŒ, ๋ช‡๊ฐ€์ง€ ์ฐจ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • Subject ๋Š” Observer ์™€ Observable ์˜ ์—ญํ• ์„ ๋ชจ๋‘ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

  • Observable ์ฒ˜๋Ÿผ ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์–ธ์ œ๋“ ์ง€ ์ˆ˜๋™์œผ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ƒˆ๋กœ ์ˆ˜์‹  ๋ฐ›์•„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ ์—ฐํ•ฉ๋‹ˆ๋‹ค.

  • Driver ๋Š” UI ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋œ Observable ์ž…๋‹ˆ๋‹ค. UI ์ด๋ฒคํŠธ๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์ž‘๋™ํ•ด์•ผ ํ•˜๋ฏ€๋กœ, Driver ๋Š” ์ž๋™์œผ๋กœ MainScheduler ์—์„œ ์ž‘๋™๋ฉ๋‹ˆ๋‹ค.

  • ๋˜ํ•œ Driver ๋Š” error ์ด๋ฒคํŠธ๋ฅผ ๋ฐฉ์ถœํ•˜์ง€ ์•Š์œผ๋ฉฐ, ๊ตฌ๋…์ด ํ•ด์ œ๋˜๊ธฐ ์ „๊นŒ์ง€ ํ•ญ์ƒ ๋ฉ”๋ชจ๋ฆฌ์— ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

4) Subject ์™€ Relay ์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.

  • ๊ณตํ†ต์ ์œผ๋กœ๋Š” ๋‘˜ ๋‹ค RxCocoa ์— ํฌํ•จ๋˜์—ˆ๊ณ , Observer ์˜ ์—ญํ• ๊ณผ Observable ์˜ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • ์ฆ‰, ์ด๋ฒคํŠธ์˜ ๋ฐœํ–‰๋„ ํ•  ์ˆ˜ ์žˆ๊ณ , ์ด๋ฅผ ๊ตฌ๋…ํ•ด ์ด๋ฒคํŠธ์— ๊ฑธ๋งž๋Š” ํ–‰๋™ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ฐจ์ด์  ์ฒซ๋ฒˆ์งธ๋กœ๋Š”, Subject ๋Š” RxSwift ์˜ ํด๋ž˜์Šค์ด๊ณ , Relay ๋Š” RxCocoa ์˜ ํด๋ž˜์Šค๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • ๋‘๋ฒˆ์งธ๋กœ๋Š”, Subject ๋Š” completed ๋‚˜ error ๋ฅผ ํ†ตํ•ด์„œ ์ŠคํŠธ๋ฆผ์„ ์ข…๋ฃŒ์‹œํ‚ค์ง€๋งŒ, Relay ๋Š” Dispose ๊ฐ€ ๋˜๊ธฐ ์ „๊นŒ์ง€ ๊ณ„์† ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

  • ์„ธ๋ฒˆ์งธ๋กœ๋Š”, Subject ์˜ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ ๊ฐ’ ์ถœ๋ ฅ์€ ๊ตฌ๋…์„ ํ†ตํ•ด ๊ฐ€๋Šฅํ•˜๊ณ , Relay ์˜ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ ๊ฐ’ ์ถœ๋ ฅ์€ .value ๋ฅผ ํ†ตํ•ด์„œ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

5) Driver ์™€ Relay ์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.

  • Driver ๋Š” MainScheduler ์—์„œ ํ–‰๋™ํ•˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๊ณ , Relay ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ๋”ฐ๋ผ์„œ UI ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ• ๋•Œ Driver ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข€ ๋” ์ ์ ˆํ•˜๊ณ , Relay ๋Š” ๋น„ UI ์ด๋ฒคํŠธ์—์„œ๋„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹์Šต๋‹ˆ๋‹ค.


https://velog.io/@heyksw/iOS-%EB%A9%B4%EC%A0%91-%EC%A4%80%EB%B9%84#-rxswift-%EA%B4%80%EB%A0%A8

Last updated