마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

레트로핏 네트워크 끊겼을때 처리

0 추천
레트로핏+코루틴으로 네트워크 처리를 해주고있습니다만

이전 개발자분이 코루틴에 catch를 써놓은 곳이 있고 없는 곳이 있어서 네트워크 끊으면 크래시가 나더라구요

그래서 이걸 일일이 다 catch를 추가해주면 되긴하는거같은데.. 양이 너무많아서

인터셉터에서 할 방법이 없을까요?
수원통학러 (3,570 포인트) 님이 2021년 12월 24일 질문

1개의 답변

0 추천

Retrofit을 사용하는 인터페이스가 Response와 같이 쉽게 타입체크가 가능한 공통된 타입을 리턴한다면 가능할 수도 있지만,  아니라면 interceptor는 적절한 옵션이 아닐 것 같습니다.

제가 님의 코드를 알 수는 없기 때문에, 정확한 방향은 제시를 못해 드릴 것 같고 한두가지 아이디어를 드리자면,

Retrofit을 바로 쓰지말고 이걸 같은 함수이름을 가진 똑같은 클래스로 감싸서 사용하면 어떨까 싶네요. 에를 들면,

아래처럼, RetrofitApi가 있다고 하죠. (어노테이션 생략) 
먼저, 해당 인터페이스의 이름을 바꾸고 접근자도 패키지 레벨로 만들어서 컴파일 에러가 나게 만듧니다.

internal interface AuthApiEx {
    suspend fun login(): LoginResult
    suspend fun logout(): LogoutResult
}

 

같은 패키지에 AuthApi 클래스를 똑같은 함수를 가지도록 만듧니다. 이 클래스에 AuthApiEx를 주입합니다.

class AuthApi(
   private val deleagate: AuthApiEx
) {
    suspend fun login(): LoginResult {
       try {
          deleagate.login()
       } catch(e: Exception) {

       }
    }

    suspend fun logout(): LogoutResult {
       try {
          deleagate.logout()
       } catch(e: Exception) {

       }
    }
}

이렇게 하면, 아마도 기존 AuthApi를 사용하는 곳에서 코드 교체없이 기존 함수들을 그대로 사용할 수 있지 않을까 생각합니다.

 

다른 방법으로는 Kotlin extension function을 이용해서, AuthApi의 함수이름을 바꾼 다음, 기존의 함수와 동일한 이름으로 확장함수를 만들어 사용하는 겁니다. 이 경우는 해당 함수들을 사용한 곳에서 import 만 다시 해주면 될 겁니다.

interface AuthApi {
    suspend fun loginEx(): LoginResult
    suspend fun logoutEx(): LogoutResult
}

fun AuthApi.login(): LoginResult {
    try {
         this.loginEx()
    } catch (e: Exception) {

   }
}

fun AuthApi.logout(): LoginResult {
    try {
          this.logoutEx()
    } catch (e: Exception) {

   }
}

 

일단 생각나는 추가적인 옵션은 위의 두가지인데, 님의 코드 상황에 맞게 선택을 하셔야 겠죠. 그리고 인터넷 커넥션의 경우는 API 호출 전에 상태를 체크해서 연결이 끊긴 경우는 API를 호출하지 않고 에러처리를 해주면 더 좋겠죠.

class AuthDelegate(
   private val authApi: AuthApi,
   private val connectivityChecker: ConnectivityChecker
) {
    suspend fun login(): LoginResult {
       if (connectivityChecker.isNotConnected()) {
           return ...
       }

       try {
          authApi.login()
       } catch(e: Exception) {

       }
    }

    ...
}

 

그리고 Kotlin Coroutine을 사용할 때 한가지 팁은 Exception을 리턴하지 말고 Exception의 상태를 리턴하시는게 코루틴의 에러핸들링의 함정을 피할 수 있어 정신건강에 좋다는 겁니다.

sealed class LoginResult {
    data class Error(val exception: Exception): LoginResult()
    data class Success(val data: LoginInfo): LoginResult()
}

만약 새로운 코드나 함수를 만드실 경우라면, 모든 걸 수동으로 하지마시고 Android Studio 의 코드 템플릿 같은 기능을 이용하셔서 기본적인 코드는 자동생성 하도록 하시면 시간이 많이 절약될 겁니다.

spark (226,420 포인트) 님이 2021년 12월 25일 답변
spark님이 2021년 12월 25일 수정
...