RxSwift를 적용하여 과제를 구현해보았는데, 한 가지 의문점이 생겼다.
extension Reactive where Base: NetworkManager {
func fetchRates() -> Single<ExchangeRateResponse> {
Single.create { [base] observer in
base.fetchRates {
observer($0)
}
return Disposables.create()
}
}
}
위는 RxSwift를 확장한 코드이다.
확장한 코드를 사용할 때는 아래와 같다.
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case .fetchData:
let fetchRates = NetworkManager.shared.rx
.fetchRates()
.map { response in
response.rates
.map { key, value in
SimpleRate(
currencyCode: key,
rate: value,
isFavorite: false,
upDown: ""
)
}
.sorted { $0.currencyCode < $1.currencyCode }
}
.asObservable()
return fetchRates
}
}
fetchRates()의 호출부에서 다시 SimpleRate 타입으로 변환하여 .asObservable를 통해 다시 Observable 타입을 생성해주고 있다.
그렇다면, Single<ExchangeRateResponse> 타입이 아니라 ExchangeRateResponse 타입으로 바로 받아서 사용부에서만 Observable 타입으로 생성해주면 안되는걸까?
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case .fetchData:
let fetchRates = Single.create { observer in
let response = fetchRates()
response.map {
SimpleRate(
currencyCode: key,
rate: value,
isFavorite: false,
upDown: ""
)
}
observer(.onSuccess(response))
observer(.failure(error))
}
return fetchRates
}
}
위와 같은 코드로 구현하면 안될까 궁금해서 고민해보다 튜터님께 여쭤보았다.
우선, 위 예시 코드에서는 NetworkManager의 fetchRates 함수가 클로저를 사용하고 있기 때문에 현재 방식을 사용해야한다.
그렇다면 async await 방식을 통한 경우라면 ExchangeRateResponse로 받을 수 있지 않을까?
-> 가능은 하다!
하지만 ExchangeRateResponse 타입으로 반환받는다면, 호출부에서는 매번 Task를 통해 결과물을 전달받고 Observable을 매번 생성해주어야하는 번거로움이 발생한다.
어디에 어떤 걸 사용하겠다는 관점의 차이이기 때문에 내가 NetworkManager 계층에는 RxSwift를 사용하지 않겠다! 라고 결심했다면 문제가 되진 않겠지만, RxSwift를 확장하여 사용함으로써 중복되는 코드를 줄일 수 있다는 장점이 있는데 굳이 사용하지 않을 필요가 있을까 싶다.
final class MusicViewModel: ViewModel {
struct Input {
let fetchData: Observable<Void>
}
struct Output {
let musics: Single<[[Item]]>
}
func transform(_ input: Input) -> Output {
let musics = Single<[[Item]]>.create { ... }
return Output(musics: musics)
}
}
기존에 musics의 타입을 Single타입으로 사용하고 있었는데, 해당 타입은 결과물을 한번 보내고 나면 바인딩이 풀린다는 사실을 알게 되었다...
그렇다면 다시 구독을 해주어야 다시 바인딩이 될텐데, 그럼 VC에서 bind함수를 다시 호출해야하는 불상사가 발생한다.
한 번만 데이터를 받고 말 것이 아니라면 Observable로 사용하는 것이 좋을 것 같다.
위 코드는 변경 예정이다.