Published on

๐ŸŽ Swift - RxSwift์—์„œ Combine์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ

Authors
  • avatar
    Name
    ์ด์ฐฝ์ค€
    Twitter

RxSwift์—์„œ Combine์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ

์˜ค๋Š˜์€ RxSwift์—์„œ Combine์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ณผ์ •๊ณผ, ์ฃผ์˜ํ•  ์ ๋“ค์„ ์ •๋ฆฌํ•ด๋ณด๋ฉด์„œ ํ•™์Šตํ• ๊ฒ๋‹ˆ๋‹ค!

์‚ฌ์‹ค ์ €์—๊ฒŒ๋Š” ์ „ํ™˜์ด๋ผ๊ธฐ๋ณด๋‹ค๋Š”, ๋‘˜ ๋‹ค ์•Œ์•„๋‘์ž! ๋ผ๋Š” ์‹์ด๊ธด ํ•˜์ง€๋งŒ์š”.

Observable โžก๏ธ Publisher

๊ฐ€์žฅ ๋จผ์ € ๋ˆˆ์— ๋„๋Š” ์ ์€ Observable์— ๋Œ€์‘๋˜๋Š” Publisher์ผ๊ฒ๋‹ˆ๋‹ค.

class Observable<Element>: ObservableType {
	func subscribe<Observer: ObserverType>(_ observer: Observer)
		-> Disposable where Observer.Element == Element {
		// 
	}
}
protocol Publisher<Output, Failure> {
	associatedType Output
	associatedType Failure: Error
	
	func receive<S>(subscriber: S)
		where S: Subscriber,
		Self.Failure == S.Failure,
		Self.Output == S.Input
}

๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์€ Observable์€ ํด๋ž˜์Šค ๊ตฌํ˜„์ฒด์ด๊ณ , Publisher๋Š” ํ”„๋กœํ† ์ฝœ์ด๋ผ๋Š” ์ ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— Rx์—์„œ๋Š” ์ด Observable์„ ํ•œ ๋ฒˆ ๋ž˜ํ•‘ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ์ƒ์†์„ ํ•˜๊ณ  subscribe ๋ฉ”์„œ๋“œ๋ฅผ overrideํ•ฉ๋‹ˆ๋‹ค. Combine์—์„œ๋Š” Publisher ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๊ณ  receive ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์คŒ์œผ๋กœ์จ ์ปค์Šคํ…€ Publisher๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์ฃ .

๋ณดํ†ต ์• ํ”Œ์ด ์ œ๊ณตํ•˜๋Š” Publisher ๊ตฌํ˜„์ฒด๋“ค์€ ๊ตฌ์กฐ์ฒด๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ Rx์˜ Maybe๋‚˜ Single ๊ฐ™์€ ๊ตฌํ˜„์ฒด๋“ค์€ Observable์„ ๋ž˜ํ•‘ํ•œ ํ˜•ํƒœ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.1

๋˜ํ•œ Publisher๋Š” Failure ํƒ€์ž…์„ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ๋ฅผ ํ•ญ์ƒ ์—ผ๋‘์— ๋‘๊ณ  ๋งŒ๋“ค์–ด์กŒ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

๋งŒ์•ฝ Failํ•˜์ง€ ์•Š๋Š” Publisher๋ฅผ ๋งŒ๋“ค ๋•Œ๋Š”, Never๋ฅผ Failure๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

Observer โžก๏ธ Subscriber

์ด๋ฒˆ์—๋Š” ๋ฐ˜๋Œ€์˜ ์œ„์น˜์— ์žˆ๋Š” "๊ตฌ๋…์ž" ์ž…๋‹ˆ๋‹ค.

RxSwift๋Š” Event๋ผ๋Š” enum์œผ๋กœ ๊ตฌ๋…ํ•œ Observable์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.2

@frozen
enum Event<Element> {
    /// Next element is produced.
    case next(Element)
    /// Sequence terminated with an error.
    case error(Swift.Error)
    /// Sequence completed successfully.
    case completed
}

๋ฐ˜๋Œ€๋กœ Combine์€ ์ด๋ฅผ enum์œผ๋กœ ๊ตฌ๋ถ„ํ•˜์ง€๋Š” ์•Š๊ณ , ๋ณ„๊ฐœ์˜ ๋ฉ”์„œ๋“œ๋“ค์„ ์ œ๊ณตํ•ด์„œ ๊ฐ๊ฐ์— ๋Œ€ํ•œ ํ•ธ๋“ค๋ง์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

protocol Subscriber<Input, Failure>: CustomCombineIdentifierConvertible {
	associatedType Input
	associatedType Failure: Error

	func receive(subscription: Subscription)
	func receive(_ input: Self.Input) -> Subscriber.Demand
	func receive(completion: Subscribers.Completion<Self.Failure>)
}

@frozen
enum Completion<Failure> where Failure: Error {
	case finished
	case failure(Failure)
}

๊ฐ€์žฅ ์ฐจ์ด์ ์ด๋ผ๊ณ  ํ•œ๋‹ค๋ฉด, Combine์˜ Subscriber๋Š” Publisher์˜ Failure ํƒ€์ž…๊ณผ ๋งค์นญํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

RxSwift๊ฐ€ ๋ถˆํ™•์‹คํ•œ ํƒ€์ž…์˜ Error๋ฅผ case๋กœ ์ œ๊ณตํ•ด์ค€๋‹ค๋ฉด, Combine์€ ์ •ํ™•ํ•œ ํƒ€์ž…์˜ Failure: Error๋ฅผ receive(completion:) ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Subscription

Subscription์€ Publisher์™€ Subscriber๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

1: RxSwift - PrimitiveSequence.swift 2: RxSwift - Event