Skip to content

Error Handling #43

@zzangzzangguy

Description

@zzangzzangguy

RxSwift에서 에러 처리하기

에러가 발생했을 때

  • 에러는 Observable 체인 통과 과정 에서 발생.
  • 별도의 처리 없이 에러가 발생하면, 그 에러는 그대로 구독자에게 전달
    • observable 이 에러를 발생할때 에러 구독이 확인 → 모든 구독이 dispose
  • 에러를 받은 Observable은 완전히 종료되고, 이후 이벤트는 무시됩니다.
let request = URLRequest(url: URL(string: "http://api.openweathermap.org/data/2.5/weather?q=invalidCity&appid=[API-KEY]")!)

_ = URLSession.shared.rx.response(request: request)
    .subscribe(onNext: { response in
        print(response)// 호출되지 않음
    }, onError: { error in
        print("에러: \(error.localizedDescription)")
    })
// 404 에러로 인해 검색 기능이 중단.

에러 잡아내기

앱이 에러로 인해 중단되지 않도록, 에러를 잡아내어 복구할 수 있어야 한다.

  1. 에러 발생 시 캐시된 데이터를 반환.
  2. 캐시된 데이터가 없으면 기본값 반환.
  3. 그래도 실패하면 재시도(retry).

catch 연산자

  • catchError는 이전에 에러가 발생하지 않았던 값을 반환한다.
  • catchErrorJustReturn은 주어진 유형에 대한 기본값을 반환한다.
let textSearch = searchInput.flatMap { text in
    return ApiController.shared.currentWeather(city: text ?? "Error")
        .catchErrorJustReturn(ApiController.Weather.empty)
}
  • 캐시된 결과를 재사용하려면 catchError 연산자를 활용한다.
let textSearch = searchInput.flatMap { text in
    return ApiController.shared.currentWeather(city: text ?? "Error")
        .catchError { error in
            if let cachedData = self.cache[text] {
                return .just(cachedData)
            } else {
                return .just(ApiController.Weather.empty)
            }
        }
}

retry 연산자

  • retry 연산자는 Observable의 전체 작업을 반복한다.
  • 사용자의 직접 재시도로 인한 UI 변경 부작용을 막을 수 있다.
return ApiController.shared.currentWeather(city: text ?? "Error")
    .retry(3)// 최대 3번 재시도
    .catchError {/* 에러 처리 로직 */ }

retryWhen 연산자

  • retryWhen은 TriggerObservable을 통해 retry 시점을 제어한다.
  • TriggerObservable은 Observable 또는 Subject일 수 있다.

에러 사용자화

  • 커스텀 에러를 정의하여 API 응답 상태 코드에 따른 에러 처리가 가능하다.
enum ApiError: Error {
    case cityNotFound
    case serverFailure
}

return session.rx.response(request: request).map { response, data in
    if 200 ..< 300 ~= response.statusCode {
        return try JSONDecoder().decode(WeatherResult.self, from: data)
    } else if 400 ..< 500 ~= response.statusCode {
        throw ApiError.cityNotFound
    } else {
        throw ApiError.serverFailure
    }
}

materialize / dematerialize

  • materialize 연산자는 Observable 시퀀스를 Observable의 이벤트로 변환한다.
  • dematerialize는 materialize로 변환된 Observable을 원래 모양으로 되돌린다.
  • 이 두 연산자를 함께 사용하면 Observable을 완전히 분해하여 특정 상황을 처리할 수 있다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions