์ง๋ Retrofit๊ด๋ จ ํฌ์คํ ์ดํ์, ๊ณฐ๊ณฐ์ด ์๊ฐํด ๋ณด๋๊น ๋นผ๋จน์ ๋ด์ฉ์ด ์๋๋ผ๊ณ ์. ๊ทธ๋์ ์ถ๊ฐ๋ก ํฌ์คํ ์ ๋จ๊ฒจ๋ด ๋๋ค.

๋ณดํต ๊ฐ์ด ์ผํ๋ ๋ฐฑ์๋ ๊ฐ๋ฐ์ ๋ถ์ ๋ฐ๋ผ, ํ์ฌ ์ ์ฑ
์ ๋ฐ๋ผ, ๋ง์ด ๋ณํ๋๋ ๋ถ๋ถ์ธ๋ฐ์.
์ด๋ค ๊ฒฐ๊ณผ๊ฐ์ API์์ ๋๊ฒจ์ฃผ๋๋์ ๋ฐ๋ผ์ ์ด ๋ด์ฉ์ด ๋์์ด ๋ ์๋ ์๋ ์๋ ์๊ฒ ์ต๋๋ค.
ํ ์คํธ API์์๋ ๋ฑํ ํ์ ์๋ ๋ด์ฉ์ด๊ณ , ์ ํฌ ์ฌ๋ด API ๊ท์น์๋ ํ์ํ ๋ด์ฉ์ธ๋ฐ์.
API๊ฒฐ๊ณผ ๋ฐ์ดํฐ ์ค, RESULT ๋ฐ์ดํฐ๊ฐ ์๋ Response ๊ตฌ์กฐ๊ฐ ์ค๋ณต์ฒ๋ฆฌ๋ ๋, ์ฌ์ฉํฉ๋๋ค.
์ง๋ ํฌ์คํ ์์ inteceptor๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ๋ฐ๊ธฐ ์ ์ ์ฌ๋ฌ ์ฒ๋ฆฌ๋ค์ ํ๋ ์ฝ๋๋ฅผ ๋ฃ์ด๋ณด์๋๋ฐ์
- ๋ก๊ทธ ํ์ธ์ฉ
- ํค๋ ์ฝ์ ์ฉ
์ด๋ฒ์๋ ๊ณตํต response ๊ฐ๋ค์ ๋ฌถ์ด์ ํ๋์ ๋ฐ์ดํฐ ํด๋์ค๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ๋๋ค.
์ฌ์ค ๊ผญ ํด์ค์ผ ํ๋ ๋ด์ฉ์ ์๋์ฃ , data class๋ฅผ ๊ทธ๋ฅ ์ฌ๋ฌ ๊ฐ ๋ง๋ค๊ณ ๊ณ์ ์ฌ์ฉํด๋ ๋๊ธฐ๋ ํฉ๋๋ค.

ํ์ง๋ง ์ฐ๋ฆฌ ๋ชจ๋ ์ค๋ณต๋ ๋ฐ์ดํฐ ์ข์ํ์ง ์์์์? ๋๊ฐ์ ์ฝ๋๊ฐ ๋ฐ๋ณต๋๋๊ฑฐ ์ญ์ ์ข์ํ์ง ์์ต๋๋ค.
๊ทธ๋์ response ๋ด์ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ ์ฃผ์ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ๋ง ์์๊ฒ ์ ๋ฆฌํ ์ ์๋๋ก ์ฒ๋ฆฌํด ์ฃผ๋๋ก ํ๋ ค๊ณ ํ๋ ๊ฒ์
๋๋ค.
๋ณด๊ธฐ์ ์์๊ฒ ์ ๋ฆฌํ๋ ๊ฒ์ด,,,์ ๋ ๊ฐ์ธ์ ์ผ๋ก ์ข์ต๋๋ค.
์ฌ์ค ์ค๋ณต data class๊ฐ ๋ง์ผ๋ฉด ํ์ฐ์ ์ผ๋ก ์ฃผ์์ ๋ง์ด ๋ฌ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ฉด ์ ์ง๋ณด์ํ๊ธฐ ๋๋ฌด ํ๋ค์ด์์. ๊ทธ๋ฅ ํ๋๋ก ์๋นกํ๊ณ ์์๊ฒ ์ ๋ฆฌํ๋ ๊ฒ์ด ๋์ค์๋ ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
์ด ๋ถ๋ถ์ ์ ๋ฒ๊ณผ ๋์ผํ interceptor ์ฝ๋์
๋๋ค.
์ด ์ฝ๋ ๋ด์ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ๋ฅผ ๊ณตํต wrapper response ํด๋์ค์ ๋ฌถ๊ณ ์ ํจํ ๋ฐ์ดํฐ๋ค๋ง ๋๊ฒจ์ฃผ๋ ค๊ณ ํฉ๋๋ค.
interceptor ํด๋์ค ๋ด์์, responseBody ๋ด๋ถํจ์๋ฅผ ์ด์ฉํ์ฌ, responsebody๋ฅผ ์ฌ๊ตฌ์ฑํ์์ต๋๋ค.
responseWrapper์ result๋ฐ์ดํฐ๋ฅผ responsebody ๋ฐ์ดํฐ๋ก ์นํํ๋ ๋ด์ฉ์
๋๋ค.
๊ทธ๋ฌ๋ฉด ๋ก๊ทธ ์์ผ๋ก๋ ๋ฐ๋ณต์ ์ผ๋ก ๋ด๋ ค์ค๋ ๋ฐ์ดํฐ๊ฐ ์๋ result์ ๋ฐ์ดํฐ๊ฐ responsebody๋ฐ์ดํฐ๋ก ๋์ด์ค๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
(์ด ๋ถ๋ถ์ ๋ฐ๋ก ์ฌ๋ด ๋ฐ์ดํฐ ๋ก๊ทธ์ด๊ธฐ ๋๋ฌธ์ ๋ก๊ทธ ์ ๊ณต์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.)
class NetworkInterceptor: Interceptor {
private companion object {
private const val SERVER_ERROR_CODE = 500
}
override fun intercept(chain: Interceptor.Chain): Response {
try {
val newRequest = chain.request().newBuilder().build()
val response = chain.proceed(newRequest)
val rawData = responseBody(response)
return response.newBuilder()
.message(response.message)
.body(rawData?.toResponseBody())
.build()
} catch (e: Exception) {
val message: String = when(e) {
is SocketTimeoutException -> "SocketTimeoutException"
else -> "Exception"
}
return Response.Builder()
.request(chain.request())
.protocol(Protocol.HTTP_2)
.code(SERVER_ERROR_CODE)
.message(message)
.body("{$e}".toResponseBody(null))
.build()
}
}
private fun responseBody(response: Response): String? {
val responseBody = response.body ?: return "{}"
val contentLength = responseBody.contentLength()
if (contentLength == 0L) {
return "{}"
}
val res = Gson().fromJson<ResponseWrapper<*>>(
response.body?.string() ?: "{}",
object : TypeToken<ResponseWrapper<*>>() {}.type
)
return if (res.result == null) "{}" else Gson().toJson(res.result)
}
}
ResponseWrapper ๋ด๋ถ์ ๋ฌถ์ธ code, message, description์ ๋ชจ๋ API์์ ๊ณตํต์ ์ผ๋ก ๋ด๋ ค์ฃผ๋ ๋ฐ์ดํฐ์
๋๋ค.
๊ทธ ํ์์ result๊ฐ ์ค์ ์ ์ผ๋ก ํ์ํ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ์ด์ง์.
์๋ง ์ด ์ ๋๊ฐ ๊ฐ์ฅ ๋ฒ ์ด์งํ ๊ตฌ์กฐ์ด๊ณ ์๋ฒ ๊ตฌ์กฐ ๋ฐ ์๋น์ค ๊ตฌ์ฑ์ ๋ฐ๋ผ ํ ํฐ์ด ์ด๊ณณ์ ์ค๊ณ ๊ฐ ์๋ ์๊ฒ ๊ณ
๋ค๋ฅธ ํ์
๋ฐ์ดํฐ๋ค์ด ๋์ด์ฌ ์๋ ์๊ฒ ์ต๋๋ค.
๊ณตํต์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ ๊ฒ๋ค์ ResponsoeWrapper๋ด์ ๋ฃ์ด์ ํ๋๋ก ๊ด๋ฆฌ ๋ ์ ์๋๋ก ํ๋ฉด ๋ฉ๋๋ค.
@Parcelize
data class ResponseWrapper<T>(
@SerializedName("code")
val code: String,
@SerializedName("message")
val message: String,
@SerializedName("description")
val description: String,
@SerializedName("result")
val result: @RawValue T? = null
)
์ด๋ฌ๋ฉด ์ค๋ณต์ ์ธ data class๋ ํ๋๋ก ์ฒ๋ฆฌํ๊ณ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ๋ค์ data class๋ง ์ ๊ด๋ฆฌํด์ ์ฐ๊ฒฐํด ์ฃผ๋ฉด
๊ทธ๋ญ์ ๋ญ ๊น๋ํ ์ฝ๋ ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
