API를 이용할 때, 요청에 대한 응답은 성공이든 실패든 반드시 돌아옵니다
이러한 응답을 보다 명확하게 처리하기 위해, 결과를 세분화하여 처리하는 것이 좋습니다
API 응답을 다룰 때는 응답의 유형을 명확히 구분하고, 각각에 대한 적절한 처리를 설계하는 것이 중요합니다
이는 시스템의 안정성을 높이고, 예기치 않은 상황에 대한 대응력을 강화합니다
API 호출 후 응답은 크게 두 가지로 나눌 수 있습니다: 성공 응답과 실패 응답
성공적인 API 호출은 서버가 요청을 정상적으로 처리했음을 의미합니다
일반적으로 성공 응답에는 다음과 같은 요소가 포함됩니다
- HTTP 상태 코드: 200번대 (예: 200 OK, 201 Created 등)
- 응답 본문: 요청한 데이터 또는 작업 결과를 포함 (JSON, XML 등)
실패한 API 호출은 여러 가지 원인으로 발생할 수 있으며, 이를 적절히 처리하는 것이 중요합니다
실패 응답에는 다음과 같은 요소가 포함될 수 있습니다
- HTTP 상태 코드: 400번대 (클라이언트 오류) 또는 500번대 (서버 오류)
- 오류 메시지: 오류 원인에 대한 설명 또는 코드
class LoginRemoteDataSource @Inject constructor() {
private val loginApiService = LoginRetrofitClient.loginApi
suspend fun loginApi(
provider: String,
accessToken: LoginRequest,
): LoginResponse? {
try {
val loginGetResponse = loginApiService.getAccessToken(
provider,
accessToken,
)
if (loginGetResponse.code() != 200) {
return null
}
return loginGetResponse.body()
} catch (e: Exception) {
Log.e("LoginGetException", e.toString())
return null
}
}
}
현재 코드는 API 호출의 응답 코드를 확인하여, 200이 아닌 경우 null
을 반환합니다
이는 성공 응답만 처리하고 실패 응답은 무시하는 간단한 로직입니다
sealed class ApiResult<out T> {
data class Success<out T>(val data: T) : ApiResult<T>()
data class Error(val errorCode: String, val description: String) : ApiResult<Nothing>()
data class Exception(val e: Throwable) : ApiResult<Nothing>()
}
- API Result 클래스를 도입함으로써 여러 에러 코드를 포함한 응답 상태에 따른 세부적인 분류 및 처리가 가능해졌습니다
viewModelScope.launch {
val response = profileGetUsecase.invoke()
when(response) {
is ApiResult.Error -> {
val code = response.errorCode
val responseDsscription = response.description
when(code) {
"400" -> ...
"401" -> ...
"402" -> ...
"403" -> ...
"404" -> ...
else -> ...
}
}
is ApiResult.Exception -> {
Log.d(
"recommended Exception",
response.e.message ?: "No message available"
)
}
is ApiResult.Success -> {
setUserInfo(response.data)
}
}
}
응답 코드 처리의 세분화
응답 코드가 200이 아닌 경우 모두 null
로 처리하는 것이 아닌,
다양한 응답 코드를 세분화 하여 별도로 처리하면 사용자에게 더 명확한 피드백을 제공할 수 있습니다
로깅 개선
현재 예외 발생 시 로그를 출력하고 있지만, 추가적인 정보를 포함하면 로그를 더 상세하게 기록하면 문제를 파악하기 더 용이해집니다
결과 래핑
좋지 않은 예시에서 사용한 LoginRespose?
를 반환하여 성공/실패를 구분했지만, APIResult
클래스와 같은 래퍼 클래스를 사용하여 성공/실패와 함께 관련 메세지나 데이터를 포함하는 방법도 고려 가능해집니다