IOS

[iOS] Alamofire 네트워크 레이어 설계1. 에러처리 (feat. Rx)

clamp 2024. 1. 25. 15:12

https://ios-development.tistory.com/731

 

[iOS - swift] 1. Alamofire 사용 방법 - Network Layer 구현 (Moya 프레임워크처럼 사용하는 방법)

1. Alamofire 사용 방법 - Network Layer 구현 (Moya 프레임워크처럼 사용하는 방법) 2. Alamofire 사용 방법 - 토큰 갱신 방법1 (Interceptor, adapt, retry) 3. Alamofire 사용 방법 - 토큰 갱신 방법2 (AuthenticationCredential,

ios-development.tistory.com

 

해당 게시글을 토대로 구현해본 네트워크 레이어를 기록해봅니다.

 

부족한 점이 있다면 알려주시면 감사합니다.

 

1. 에러 처리

 

* HTTP통신은 비연결성 통신으로 통신의 응답, 오류만을 방출하면 되도록 Single로 구현하였습니다.
* Loading은 액티비티 인디케이터 관련 클래스입니다. 나중에 기록해보도록 하겠습니다.

 


public func request<T: Decodable>(_ urlConvertible: URLRequestConvertible) -> Single<T> {
        return Single.create { single in
            
            Loading.start()

            let request = self.session
                .request(urlConvertible,
                         interceptor: self.authInterceptor)
                .validate(statusCode: 200 ..< 300)
                .responseDecodable(of: T.self) { response in
                    switch response.result {
                    case let .success(data):
                        single(.success(data))
                    case let .failure(error):
                        if let errorData = response.data {
                            do {
                            // 백엔드와 통신하고 에러가 발생했다면 ErrorEntity와 같은 구조로 response가 내려옵니다.
                            // 이 error response를 ErrorEntity로 디코딩합니다.
                                let networkError = try JSONDecoder().decode(ErrorEntity.self, from: errorData)
                                // 이 ErrorEntity를 활용해 APIError라는 Error를 만듭니다.
                                let apiError = APIError(error: networkError)
                                single(.failure(apiError))
                            } catch {
                            // 디코딩 과정에 에러가 발생한 경우 디코딩 에러를 리턴합니다
                                single(.failure(APIError.decodingError)
                            }
                        } else {
                        // 기본 에러를 방출합니다.
                            single(.failure(error))
                        }
                    }
                    Loading.stop()
                }
            return Disposables.create {
                request.cancel()
            }
        }
    }

 

ErrorEntity

 

APIError

 

대부분의 경우 API에러의 network로 생성되어 statusCode(ex: 401 400 409)를 갖게되고,

errorMessage를 연관값으로 갖고있게됩니다.

 

에러가 발생한 경우 사용자가 무슨에러인지 알아야 하기 때문에 이렇게 처리했습니다.

 

만약 에러가 발생한다면?

 

 

flatMap에서 네트워크 통신을 하고 통신의 결과를 리턴할 때 만약 에러가 발생되어서 onError(failure)가 방출된다면 더이상 이벤트를 방출할 수 없게 됩니다. 그래서 catch블록에서 에러를 다른 서브젝트(릴레이)로 넘기고 .empty()를 리턴합니다.

 

self?.error는 다음과 같습니다

뷰 모델

 

Error를 방출하는 서브젝트 또는 릴레이입니다.

 

어떤 행위의 결과로 에러를 방출해야할 때 해당 서브젝트로 에러를 전달합니다. 

 

onError가 아닌 onNext로 에러를 방출합니다.

 

그럼 뷰 컨트롤러에서는 다음 에러를 받아서 처리하게됩니다.

 

뷰 컨트롤러

여기서 presentErrorAlert라는 메서드를 띄우게 되는데 해당 부분에서 에러를 구분해 에러에 따른 알럿을 띄웁니다.

 

errorDescription은 APIError의 선언부에 나와있습니다.

 

케이스에 default로 작성해줘도 되지만 에러가 추가될 것 같아서 합치진 않았습니다.

 

다음엔 토큰관리 부분을 기록해보겠습니다.