RxSwift #5 — 예시와 함께 보는 Error Handling

Kanghoon
7 min readJan 23, 2019

--

이번에는 RxSwift에서 어떻게 Error Handling 을 하는지 앱에서 흔히 발생하는 에러 예제들을 통해 알아보려고 한다.

예제를 살펴보기에 앞서 RxSwift에서 기본적으로 Error Handling 을 하기 위해 사용하는 방법들을 먼저 알아보자.

ErrorHandling

RxSwift에서는 크게 세가지 방법으로 Error Handling 을 할 수 있다.

1. catch : 특정 값으로 Error 복구

2. retry : 재시도 하기

3. materialize / dematerialize : Sequence 를 제어해서 처리

설명과 함께 하나씩 살펴보자 .

1. catch

  • Swift 에서 사용하던 do / try / catch 문과 유사하다
  • 에러가 발생했을 때 Error 이벤트로 종료되지 않게 한다.
  • Error 이벤트 대신 특정 값의 이벤트를 발생시키고 complete 시킨다.
ReactiveX — Catch

Rxswift 에는 catch 계열에 두가지 연산자가 있다.

1) catchError(_ handler: (Swift.Error)-> Observable<E>)

  • Error를 다른 타입의 Observable 로 반환하는 클로저를 parameter로 받는다.
  • Error가 발생했을 때 Error를 무시하고 클로저의 반환값(Observable<E>)을 반환한다.
  • 1, 2, 3 이 정상적으로 출력되는걸 확인할 수 있다.
  • code: 100 Error가 발생하고 catchError에서 Error 가 .just(100)로 바뀌어 에러코드가 print 되고 complete 된걸 확인할 수 있다.

2) catchErrorJustReturn(_ element: E)

  • Error 가 발생했을 때 Error 를 무시하고 element를 반환한다.
  • 모든 에러에 동일한 값이 반환되기 때문에 catchError 에 비해 제한적이다.
  • 1, 2, 3 이 정상적으로 print 되는걸 확인할 수 있다.
  • code: 100 Error가 catchErrorJustReturn 에서 999 로 바뀌어 print 되고 complete 되는걸 확인할 수 있다.

2. retry

  • 말 그대로 에러가 발생 했을 때 다시 시도할 수 있게 해준다.
  • 에러가 발생했을 때 Observable 을 다시 시도한다(Observable 내의 전체작업을 반복)
ReactiveX — Retry
  • 아래의 사진처럼 네트워킹 요청에서 에러가 발생할 경우 retry 를 사용해 다시 시도할 수 있다.
Network Request (RxSwift — Retry)

Rxswift 에는 retry 계열에 세가지 연산자가 있다.

1) retry()

  • 일반적인 재시도에 사용하는 연산자이다. 에러가 발생했을 때 성공할 때까지 Observable을 다시 시도한다.
  • 아래의 코드는 네트워킹을 통해 repositories를 가져오는 코드이다. 인터넷 연결을 끊고 reload를 하면 콘솔에 실패 메세지가 계속 찍히는 것을 확인할 수 있다.

2) retry(_ maxAttemptCount: Int)

  • 몇 번에 걸쳐서 재시도 할지 지정할 수 있는 연산자이다.
  • maxAttemptCount 가 3 이라면 총 3번의 요청을 보낸다. (재시도는 2번)
  • 재시도 횟수가 넘어가면 그대로 Error를 이벤트로 전달한다.

3) retryWhen

  • 재시도 하는 시점을 지정할 수 있고, 한번만 수행한다.
  • retry 와 다르게 마지막 Error를 이벤트로 전달하지 않는다.

3. Materialize / Dematerialize

  • RxSwift 에서 쓰이는 Event Sequence를 제어할 수 있게 해준다.
  • 보통 Materialize / Dematerialize 는 함께 사용한다.
  • Observable을 분해할 수 있기 때문에 신중하게 사용해야 한다.

Materialize

  • Sequence 를 Event<Element> Sequence로 변환한다.
ReactiveX — Materialize

Dematerialize

  • Event<Element> Sequence 를 다시 Sequence로 변환한다.
ReactiveX — Dematerialize
  • 위의 예제에서는 materialize 를 사용해 event로 변환한 후 error 일 경우 next 로 교체해주었다.

Example

이제 앱에서 흔히 발생하는 에러들을 보면서 어떻게 처리하는지 알아보자

1. 인터넷 연결 없음

  • 인터넷 연결이 끊겨 있을 경우 (No Wifi / No LTE)
  • 구현하고자 하는 방향 : 인터넷 연결이 끊겨 있다가 연결되면 다시 Request 를 보낸다.

위의 에러를 처리하기 위해서 RxSwift Repo Example 에 있는 Rechability.swiftReachabilityService.swift 를 사용하려고 한다.

위의 두 파일을 사용하여 ReachabilityManager를 만들어서 인터넷 상태를 체크한다.

isReachable() : 현재 인터넷 상태를 체크하는 Observable

isOnline() : Rechable 상태일 때 한 번 Event를 보내는 Observable

네트워킹 요청을 하기 전에 ReachabilityManager isOnline 을 거치면 인터넷 연결이 되어 있을 때 요청을 보내게 된다.

2. HTTP 통신 에러

  • 네트워킹에 실패하여 onError 로 빠지게 되면 dispose 되기 때문에 catchError 로 해결해야 한다.
  • 서버에서 보내주는 error code 나 message 혹은 Status code 를 사용하여 각 네트워킹 마다 상황에 맞는 에러 처리를 해야한다.
  1. Result 타입으로 네트워킹 결과를 변형한다.
  2. subscribe 부분에서 success / failure 에 맞는 처리를 해주기

--

--