EOFException 발생시키는 empty body 대응 방법 # Retrofit
Retrofit 을 이용해서 정상적으로 서버의 데이터를 요청하였을 때,
200 OK를 받았는데도,
서버에서 empty body를 주어서,
EOFException 이 발생하는 경우가 있습니다.
오늘은 이것의 대응 방법에 대해서 정리해 보겠습니다.
1. 서버 200 과 EOFException
위에서 언급한 것처럼,
서버에서 200 OK 를 주었는데도,
body가 비워져 있어서,
EOFException 이 발생할 수 있습니다.
서버에서는 데이터 없으니 "" 를 보내버린 것이구요.
아래와 같이 body는 0-byte가 되어 있습니다.
보통은 서버에 데이터를 받을 때,
Retrofit 과 JSON 컨버터인 moshi(혹은 Gson)를 붙여서 사용하게 되는데요.
JSON으로 파싱하려고 하는데, body에 아무것도 없으니,
IOException 을 상속받은 EOFException 을 throw 합니다.
이것을 정상적인 경우라고 하기는 어려운데요.
서버와 클라이언트가 잘 협의하여 설계되었다면,
이런일이 발생하지 안았을테니 말이지요.
2. 대응방법
이런 상황이 발생하면, 어떻게 대응해 주어야 할까요?
서버와 잘 협의해서 empty body 말고, Parsing하는 데이터 구조에 맞추어서 보내주도록 할 수도 있을 것이구요.
moshi 같은 Converter를 위해서, body length가 0 일경우에 대응하는,
Custom Converter 를 작성해서 처리하는 방법도 있을 수 있습니다.
이 글에서는,
OKHttp 에 Interceptor 를 붙여서,
Custom한 Exception을 throw 한 다음,
해당 Exception을 catch 해서 대응하는 방법에 대해서 정리해 보겠습니다.
2-1. Custom Exception
아래와 같이 EmptyBody에 대한 Custom 한 Exception을 먼저 생성해 줍니다.
class EmptyBodyException: IOException("Response body is empty")
2-2. Interceptor
이제 OkHttp 에 붙일 Interceptor를 아래와 같이 작성해 줍니다.
class EmptyBodyInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val response = chain.proceed(chain.request())
if (response.body?.contentLength() == 0L && response.isSuccessful) {
throw EmptyBodyException()
}
return response
}
}
OkHttpClient 를 빌드할 때 아래와 같이 interceptor를 추가해주면 됩니다.
val client = OkHttpClient.Builder()
.addInterceptor(EmptyBodyInterceptor())
.build()
2-3. try...catch
이제 networkRequest 를 할 때 아래와 같이,
emptyList 를 반환해 주도록 catch 블록에서 처리해 주면 됩니다.
try {
testApi.fetchTestNetwork(id)
} catch (e: EmptyBodyException) {
emptyList<TestObject>()
}