[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

🍎 Apple/Combine & Rx

[RxSwift] Trait (Single, Completable, Maybe)

inu 2022. 2. 24. 15:14

이번엔 RxSwift의 Trait들에 대해 알아보았습니다.


Trait

Trait은 Observable을 좀 더 안정성있고 의미있게 표현하기 위한 일종의 Syntax Sugar입니다. 그 종류로는 Single, Completable, Maybe가 있습니다. Observable을 좀 더 좁은 범위로 제한하여 제공함으로써 코드를 더 명시적으로 표현하는 것이죠.

 

일반적으로 Trait은 아래와 같이 단순히 read-only Observable의 wrapper 형태로 구성되어 있습니다. 이렇게 Observable에 대한 접근을 제한해놓고 내부에 존재하는 Observable를 조정하여 일부 기능에 특화된 형태로 사용자에게 제공합니다.

struct Single<Element> { ​​​​let source: Observable<Element> ​​​​... }

Single

  • .success(value) 혹은 .error 이벤트만을 방출합니다. .success(value)는 .next와 .completed가 합쳐져 있는 형태라고 생각하시면 됩니다. 성공 또는 실패로 한번에 확인할 수 있는 1회성 프로세스에 적절합니다. (ex. 데이터 다운로드, 디스크 데이터로딩)
  • asSingle() 메서드를 통해 아무 Observable을 Single로 변환시켜서 확인할 수 있습니다.
  • 생성과 사용은 Observable과 유사합니다. 아래 예제를 봅시다.
func getRepo(_ repo: String) -> Single<[String: Any]> { ​​​​return Single<[String: Any]>.create { single in ​​​​​​​​let task = URLSession.shared.dataTask(with: URL(string: "https://api.github.com/repos/\(repo)")!) { data, _, error in ​​​​​​​​​​​​if let error = error { ​​​​​​​​​​​​​​​​single(.error(error)) ​​​​​​​​​​​​​​​​return ​​​​​​​​​​​​} ​​​​​​​​​​​​guard let data = data, ​​​​​​​​​​​​​​​​​​let json = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves), ​​​​​​​​​​​​​​​​​​let result = json as? [String: Any] else { ​​​​​​​​​​​​​​​​single(.error(DataError.cantParseJSON)) ​​​​​​​​​​​​​​​​return ​​​​​​​​​​​​} ​​​​​​​​​​​​single(.success(result)) ​​​​​​​​} ​​​​​​​​task.resume() ​​​​​​​​return Disposables.create { task.cancel() } ​​​​} }
  • subscribe로 이를 활용할 수 있습니다.
  • SingleEvent는 .success 혹은 .error만을 제공합니다.
getRepo("ReactiveX/RxSwift") ​​​​.subscribe { event in ​​​​​​​​switch event { ​​​​​​​​​​​​case .success(let json): ​​​​​​​​​​​​​​​​print("JSON: ", json) ​​​​​​​​​​​​case .error(let error): ​​​​​​​​​​​​​​​​print("Error: ", error) ​​​​​​​​} ​​​​} ​​​​.disposed(by: disposeBag)

 

Completable

  • .completed 혹은 .error만을 방출하며 그 외에 어떠한 값도 방출하지 않습니다. 특정 처리가 제대로 완료되었는지만 확인하고 싶을 때 많이 사용합니다. (ex. 파일 쓰기)
  • observable이 값요소를 방출한 이상, 이를 Completable로 변환시킬 수는 없습니다.
  • 이 역시 생성과 사용은 Observable과 유사합니다. 아래 예제를 봅시다.
func cacheLocally() -> Completable { ​​​​return Completable.create { completable in ​​​​​​​// Store some data locally ​​​​​​​... ​​​​​​​... ​​​​​​​guard success else { ​​​​​​​​​​​completable(.error(CacheError.failedCaching)) ​​​​​​​​​​​return Disposables.create {} ​​​​​​​} ​​​​​​​completable(.completed) ​​​​​​​return Disposables.create {} ​​​​} }
  • subscribe로 이를 활용할 수 있습니다.
  • CompletableEvent는 .completed 혹은 .error만을 제공합니다.
cacheLocally() ​​​​.subscribe { completable in ​​​​​​​​switch completable { ​​​​​​​​​​​​case .completed: ​​​​​​​​​​​​​​​​print("Completed with no error") ​​​​​​​​​​​​case .error(let error): ​​​​​​​​​​​​​​​​print("Completed with an error: \(error.localizedDescription)") ​​​​​​​​} ​​​​} ​​​​.disposed(by: disposeBag)

 

Maybe

  • Single과 Completable이 섞인 버전입니다. .success(value), .completed, .error 모두 방출될 수 있습니다. 프로세스가 성공 실패여부와 더불어 특정 값을 뱉을 수 있을 때 사용합니다.
  • asMaybe() 메서드를 통해 아무 Observable을 Maybe로 변환시켜서 확인할 수 있습니다.
  • 이 또한 생성과 사용은 Observable과 유사합니다. 아래 예제를 봅시다.
func generateString() -> Maybe<String> { ​​​​return Maybe<String>.create { maybe in ​​​​​​​​maybe(.success("RxSwift")) ​​​​​​​​// OR ​​​​​​​​maybe(.completed) ​​​​​​​​// OR ​​​​​​​​maybe(.error(error)) ​​​​​​​​return Disposables.create {} ​​​​} }
  • subscribe로 이를 활용할 수 있습니다.
generateString() ​​​​.subscribe { maybe in ​​​​​​​​switch maybe { ​​​​​​​​​​​​case .success(let element): ​​​​​​​​​​​​​​​​print("Completed with element \(element)") ​​​​​​​​​​​​case .completed: ​​​​​​​​​​​​​​​​print("Completed with no element") ​​​​​​​​​​​​case .error(let error): ​​​​​​​​​​​​​​​​print("Completed with an error \(error.localizedDescription)") ​​​​​​​​} ​​​​} ​​​​.disposed(by: disposeBag)

참고

'🍎 Apple > Combine & Rx' 카테고리의 다른 글

[RxSwift] Driver, Signal  (0) 2022.02.24
[RxSwift] ControlProperty, ControlEvent  (0) 2022.02.24
[RxSwift] Scheduler  (2) 2022.02.24
[RxSwift] Subject  (0) 2022.02.16
[RxSwift] Observable & Operator  (0) 2022.02.14