๋๋ค์์ ๊ท๋ชจ๊ฐ ์๋ ์ดํ๋ฆฌ์ผ์ด์
๋ค์ ์์ฒด ์๋ฒ๋ฅผ ์ด์ํ๋ฉฐ REST API๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ ์๋ฒ ํต์ ๋ค์ ๋ฐ์ดํฐ๋ฅผ JSON์ ํํ๋ก ์ฃผ๊ณ ๋ฐ์ต๋๋ค. ์๋๋ก์ด๋์ ๊ฐ๋ฐ์๋ผ๋ฉด ์ด๋ฐ ์๋ฒ๋ค๊ณผ REST API๋ฅผ ์ด์ฉํ ํต์ ์ ํ๊ธฐ ์ํด์ Retrofit
, OkHttp
, Gson
๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ ๋ฒ์ฏค ๋ค์ด๋ณด์๊ฑฐ๋ ์ฌ์ฉํด๋ณด์์ ๊ฒ์
๋๋ค.
์ด ํฌ์คํ
์ ์ด๋ฌํ ํต์ ์ฝ๋๋ฅผ ์์ฑํ๋ ์ํฉ์์ ์๋ฒ์ JSON ์๋ต ์ค, OkHttp
์ Interceptor
๋ฅผ ์ด์ฉํ์ฌ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋ฐ์ดํฐ ๋ถ๋ถ๋ง ๋ฝ์์ ๋ณ๋์ ํ์ฑ ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ ์ฝ๋๋ฅผ ์งค ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํด์ ๋ค๋ฃน๋๋ค. ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด Retrofit
์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๋ ๊ณผ์ ๊ณผ ์ฌ์ฉํ๋ ๊ณผ์ ์ด ๋งค์ฐ ํธ๋ฆฌํด์ง๋๋ค!๐
Problem : Boilerplate code๐ซ
๋ค์๊ณผ ๊ฐ์ ์๋ฒ์ ์๋ต์ ์๊ฐํด๋ณด๊ฒ ์ต๋๋ค. ์๋ฒ์์ ์ ์์ ์ธ ์๋ต์ด ์ฑ๊ณตํ ์ํฉ์ ๋๋ค.
{
"status": 200,
"success": true,
"message": "ํ๋ฉ ์ ๋ณด ์กฐํ ์ฑ๊ณต",
"data": [
{
"funding_idx": 95,
"user_idx": 12,
"store_idx": 1,
"funding_money": 2400,
"reward_percent": 0,
"funding_time": "2019-12-30T04:44:55.000Z",
"reward_money": 0
},
{
"funding_idx": 87,
"user_idx": 12,
"store_idx": 6,
"funding_money": 2400,
"reward_percent": 0,
"funding_time": "2019-12-29T11:57:39.000Z",
"reward_money": 0
},
....
]
}
๋ค์์ ์๋ฒ์์ ์ ์์ ์ธ ์๋ต์ด ์คํจํ ๊ฒฝ์ฐ์ ๋๋ค.
{
"status": 400,
"success": false,
"message": "ํด๋นํ์ง ์๋ userIdx๊ฐ์
๋๋ค."
}
์ฐ๋ฆฌ๊ฐ ์ด๋ฌํ ์๋ฒ์ ์๋ต์ Retrofit
์ GsonConverterFactory
๋ฅผ ์ด์ฉํด์ ๋ฐ์ผ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์? ์ด์์ ์ธ ์ํฉ์ด๋ผ๋ฉด ์ฐ๋ฆฌ๋ ๋ณดํต data
์ ํด๋นํ๋ ๊ฐ์ฒด๋ค์ ๋ฆฌ์คํธ๋ง ๋ฐ์์์ UI์ ๋ณด์ฌ์ฃผ๊ณ ์ถ์ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฝํ๋ฆฐ์ ๋ฐ์ดํฐ ํด๋์ค๋ฅผ ๋จผ์ ์ ์ํฉ๋๋ค. ์ด๋ฅผ Funding
์ด๋ผ๋ ๋ฐ์ดํฐ ํด๋์ค๋ก ์ ์ํ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ฌ์ค์ ํ์ ์์ง๋ง status
, success
, message
๊ณผ ์๋ต์ด ์คํจํ ์์ data
๊ฐ ์ค์ง ์์ผ๋ฏ๋ก data
๋ฅผ nullable๋ก ์ ์ํ ResponseWrapper
๋ฐ์ดํฐ ํด๋์ค๋ฅผ ํ๋ ์ ์ํฉ๋๋ค. ์ด๋ ์๋ฒ์ ์๋ต์ด ๋ชจ๋ ์์ ๊ฐ์ ํ์์ด๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ์์ฒญ์ ์๋ต์ ๊ณ์ ์ฐ์ด๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ด Retrofit
์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
@GET("mypage/fundlist")
fun listFundingHistories() : Call<ResponseWrapper<List<Funding>>>
๊ทธ๋ฆฌ๊ณ ๋ค์๊ณผ ๊ฐ์ด ์ฝ๋์์์ ์ธ ์ ์์ต๋๋ค.
์๋ฒ๋ ํต์ ํ๋ฒ ํ๊ฒ ๋ค๋๋ฐ ๊ณจ ๋๋ฆฌ๋ ์ฝ๋๊ฐ ์๋ ์ ์์ต๋๋ค๐ซ. ์ค์ ๋ก ์กฐ๊ธ ๊ณผ์ฅํ๊ธฐ ์ํด์ ์ฝ๋๋ฅผ ์์ ๊ฐ์ด ๋ง๋ค์์ง๋ง, ์์ ํ ๋นํฉ๋ฆฌ์ ์ธ ์ฝ๋๋ ์๋๋๋ค. ์ฌ๊ธฐ์ ์ฃผ์์ผ๋ก ์ซ์๋ฅผ ๋ฌ์๋ ๋คํธ์ํฌ ์์ฒญ์ ์คํจ ์ผ์ด์ค์ ๋ํด์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
- ์๋ฒ์ ํต์ ์ด ์์ ์คํจํ ์ํฉ์
๋๋ค. ์๋ฒ๊ฐ ๋ซํ์์ ์๋ ์๊ณ ,
404 Not Found
์๋ฌ๊ฐ ๋ฌ์ ์๋ ์๊ณTimeOut
์ผ ์๋ ์์ต๋๋ค. Response
์์Code
๊ฐ200
์ด์300
๋ฏธ๋ง์ด ์๋ ๊ฒฝ์ฐ์ ๋๋ค.REST API
์์ ๋ ผ๋ฆฌ์ ์ผ๋ก ์ฑ๊ณต ์๋ต์ผ๋ก ๊ฐ์ฃผ๋๋Code
์ ๋ฒ์ฃผ ์ธ์ง๋ก ์๋ต์ด ์ฑ๊ณตํ๋์ง๋ฅผ ๊ฒ์ฌํฉ๋๋ค.- ์๋ฒ ๊ฐ๋ฐ์๊ฐ ๊ฐ๋ฐํ ๋ก์ง์์์ ์คํจํ์ ๋์ ๋๋ค. ๋ณดํต 2๋ฒ์ด ์ฑ๊ณตํ๋๋ฐ 3๋ฒ์ด ์คํจํ๋ ๊ฒฝ์ฐ๋ ์๋ฒ ๊ฐ๋ฐ์์ ์ค์๊ฐ ์๋๋ผ๋ฉด ๋๋ญ ๋๋ค.
- ์๋ฒ์์๋ ์ฑ๊ณตํ๋๋ฐ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ์
๋๋ค. ๋ณดํต ์๋ต์์๋ ๋ฐ์ดํฐ๊ฐ ํ์ํ์ง๋ง ์๋ต ๋ฐ์ดํฐ๊ฐ ํ์ ์์ด ์ฝ๋๋ง
200~300
์ผ๋ก ์ค๋ ์๋ต๋ ์ข ์ข ์๊ธฐ ๋๋ฌธ์ ์ ํ์ ์ธ ๊ฒ์ฌ ์ฌํญ์ ๋๋ค. ๋ณดํต 2๋ฒ์ด ์ฑ๊ณตํ์ ๋ 4๋ฒ์ด ์คํจํ๋ ๊ฒฝ์ฐ๋ ๋๋ญ ๋๋ค.
์ฌ๊ธฐ์ 1,2๋ฒ์ Retrofit
๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๊ฒฐ์ ํด์ฃผ๋ ์คํจ ์ํฉ์ด๊ณ , 3,4๋ฒ์ ์๋ฒ ํ๋กํ ์ฝ์ด status
, success
, message
๊ทธ๋ฆฌ๊ณ data
๋ก ํ๋ฒ ์ธ์ฌ์๊ธฐ ๋๋ฌธ์ ์ด์ฉ ์ ์์ด ํ ๋ฒ ๋ ๊ฒ์ฌํด์ผ ํ๋ ์คํจ ์ํฉ์
๋๋ค. ๋ฌผ๋ก ์ด๋ฅผ RxJava
๋ Kotlin
Coroutine
๊ทธ๋ฆฌ๊ณ ResponseWrapper
์ ๋ํ ํ์ฅ ํจ์๋ฅผ ์ด์ฉํ๋ฉด ์ข ๋ ๊ฐํธํ๊ฒ ์๋ต์ ์ฒ๋ฆฌํ ์ ์๊ฒ ์ง๋ง, ์ด์ฐ ๋์๋ ์ฐ๋ฆฌ๊ฐ ์๋ฒ์ ๊ท๊ฒฉ์ ๋ง์ถฐ์ง ์๋ต ๋๋ฌธ์ ResponseWrapper
๋ ๋
์์ ํ ๊บผํ ๋ฒ๊ฒจ๋ด์ผ ํ๋ค๋ ๊ฒ์ ๋ค๋ฆ์์ต๋๋ค.
์ ๋ ๋ณดํต ์๋ฒ ๊ฐ๋ฐ์๊ฐ ์์ ๊ฐ์ด ์๋ต์ ๋ณด๋ด์ฃผ๋ ๊ฒ์ ์ ํธํ์ง ์์ต๋๋ค. status
์ success
๋ผ๋ ์๋ต ๊ฐ์ ์๋ต์ ์ฝ๋๋ก ํ๋จ์ํ๋ฉด ๋๋ ์ผ์ด๊ณ message
๋ ๊ฐ๋จํ ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ์ฌ์ฉ์์๊ฒ ๋์ฐ๋ ๋ฐ ๋น์ฅ์ ์ ์ฉํ๊ฒ ์ง๋ง, ์ฑ์ด ํ์ฅ๋๊ณ ์ฌ๋ฌ ์ธ์ด๋ฅผ ์ง์ํ๊ฒ ๋๋ ์๊ฐ ์ธ๋ชจ์๋ ํน๋ฉ์ด๋ฆฌ๊ฐ ๋ ๋ฟ์
๋๋ค. ์กฐ๊ธ์ด์ง๋ง ํธ๋ํฝ๋ ๋ ๋ฐ์ํ ๊ฒ์ด๊ณ ์๋ฒ ๊ฐ๋ฐ์๋ณด๋จ ํด๋ผ์ด์ธํธ ๊ฐ๋ฐ์๊ฐ ํ๋ค์ด์ง๋ ์ํฉ์ด ๋ฐ์ํฉ๋๋ค. ๋จํธ์ ์ธ ์๋ก Github์ API๋ ์๋ต์ Body
์ ๋ฐ์ดํฐ๋ง ๋ด์์ ๋ณด๋ด์ฃผ๋ ํ์์ผ๋ก ์ด๋ฃจ์ด์ ธ ์์ต๋๋ค.
Solution : OkHttp Custom Interceptor๐
ํ์ง๋ง ์ฐ๋ฆฌ๋ ํญ์ ๊ฐ๋ฐ์ ์ด๊ธฐ ๋จ๊ณ๋ถํฐ ๊ด์ฌํ ์ ์์ง ์๊ณ , ์ด๋ฏธ ๊ฐ๋ฐ๋ ์๋ฒ์ ๋ง์ถฐ์ ์๋๋ก์ด๋ ์ดํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐํด์ผ ํ ์๋ ์์ต๋๋ค. ์ด๋ด ๋ ์ฐ๋ฆฌ๋ OkHttp
์ Interceptor
๋ฅผ ์ด์ฉํด์ Retrofit
์ ์ด์ฉํ ์๋ฒ ์์ฒญ๊ณผ ์๋ต์ ์ค๊ฐ์์ ๊ฐ๋ก์ฑ ์ํ๋ ๊ฐ์ ๋ผ์์ ์์ฒญํ๊ฑฐ๋ ์๋ต์ ์ํ๋ ํํ๋ก ์กฐ๊ธ ๋ณํํ ์ ์์ต๋๋ค.
Retrofit
์ ๋ด๋ถ์ ์ผ๋ก OkHttp
๋ผ๋ Http
ํต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๋ค์ ๊ทธ๋ฆผ์ OkHttp
์์ Interceptor
์ ๊ฐ๋
์ด ๋ฌด์์ธ์ง ๋จํธ์ ์ผ๋ก ์ค๋ช
ํด์ค๋๋ค.
์๋ถ๋ถ์ด ์ฐ๋ฆฌ์ ์ดํ๋ฆฌ์ผ์ด์
, ์๋ซ๋ถ๋ถ์ด ์๋ฒ๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค. ๊ทธ๋ฅ Interceptor
๋ ์ดํ๋ฆฌ์ผ์ด์
๋ด์์ OkHttp
์ฝ์ด ์ฌ์ด์์ ์์ฒญ/์๋ต์ ๊ฐ๋ก์ฑ๋ ์ญํ ์ ํ๊ณ , NetworkInterceptor
๋ ์ค์ ํต์ ์์ ์๋ฒ์ OkHttp
์ฝ์ด ์ฌ์ด์์ ์์ฒญ/์๋ต์ ๊ฐ๋ก์ฑ๋ ์ญํ ์ ํฉ๋๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก Interceptor
๋ฅผ ์ฅ์ฐฉํด์ ์ด๋ป๊ฒ Retrofit
๊ฐ์ฒด๋ฅผ ์ป์ด๋๋์ง ์ฝ๋๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
private val client = OkHttpClient.Builder()
.addNetworkInterceptor(commonNetworkInterceptor)
.build()
private val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
Retrofit.Builder
๋ฅผ ์ด์ฉํ์ฌ Retrofit
๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋, ๊ทธ๋ฅ ๋ง๋ ๊ฒ์ด ์๋๋ผ OkHttpClient
๊ฐ์ฒด๋ฅผ .clinet()
๋ฉ์๋๋ก ํ์ฌํด์ ์์ฑํด์ฃผ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ OkHttpClient
๊ฐ์ฒด๋ addNetworkInterceptor
๋ฉ์๋๋ฅผ ์ด์ฉํด ์ด๋ค Interceptor
๊ฐ์ฒด๋ฅผ ์ ๋ฌํด์ ์์ฑํด์ฃผ์์ต๋๋ค.
commonNetworkInterceptor
๊ฐ์ฒด๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑ๋ฉ๋๋ค.
private val commonNetworkInterceptor = object : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
.......
}
}
Interceptor
๋ผ๋ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด์ intercept
๋ผ๋ ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํด์ฃผ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ์ด์ ์ด ์์์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๋์ง ์ฐจ๊ทผ์ฐจ๊ทผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
/**
* 1) Common Header with API Access Token
*/
val newRequest = chain.request().newBuilder()
.addHeader("token", SPUtil.accessToken).build()
- ๊ณตํต ํค๋ ์ฅ์ฐฉ(์ ํ) : ์ฐ์ , ์ฐ๋ฆฌ๋ ์๋ต์ผ๋ก ์จ
chain
๊ฐ์ฒด๋ฅผ ์ด์ฉํด์ ๊ณตํต์ ์ธ ํค๋๋ฅผ ๋ฌ์์ค ์ ์์ต๋๋ค. ์ด๋ ์๋ต์ ํ์ฑํ๋ ๊ฒ๊ณผ๋ ๊ด๋ จ์์ง๋ง, ์๋ฒ์ ํญ์ ๊ณตํต์ ์ธAccess Token
์Header
์ ๋ฌ์์ค ๋ ์ ์ฉํฉ๋๋ค. ์ฆ,Retrofit API
์ธํฐํ์ด์ค๋ฅผ ์ ์ํ ๋,@Header
์ด๋ ธํ ์ด์ ์ ๋ฌ์์ค ํ์๊ฐ ์์ด์ง๋๋ค.
/**
* 2) General Response from Server (Unwrapping data)
*/
val response = chain.proceed(newRequest)
2. ์๋ฒ๋ก๋ถํฐ ์๋ต๋ฐ๊ธฐ : chain
์ proceed
๋ฉ์๋๋ฅผ ์ด์ฉํ๋ฉด ์๋ฒ๋ก ํต์ ์ ํ๊ณ ์๋ต์ ๋ฐ์์ฌ ์ ์๊ฒ ๋ฉ๋๋ค. return
๊ฐ์ผ๋ก ๋ฐ์ response
๊ฐ์ฒด๊ฐ ๋ฐ๋ก ๊ทธ ์๋ต์ ์๋ฏธํ๋ ๊ฐ์ฒด์
๋๋ค.
/**
* 3) Parse body to json
*/
val rawJson = response.body?.string() ?: "{}"
3. ์๋ต์ body
๋ฅผ JSON
๋ฌธ์์ด๋ก ๋ง๋ค๊ธฐ: body
๋ฅผ toString()
๋ฉ์๋๋ฅผ ์ด์ฉํด์ ์ผ๋ฐ ๋ฌธ์์ด๋ก ๋ณํํ์ต๋๋ค.
/**
* 4) Wrap body with gson
*/
val type = object : TypeToken<ResponseWrapper<*>>() {}.type
val res = try {
val r = gson.fromJson<ResponseWrapper<*>>(rawJson, type) ?: throw JsonSyntaxException("Parse Fail")
if(!r.success)
ResponseWrapper<Any>(-999, false, "Server Logic Fail : ${r.message}", null) //1
else
r
} catch (e: JsonSyntaxException) {
ResponseWrapper<Any>(-999, false, "json parsing fail : $e", null) //2
} catch (t: Throwable) {
ResponseWrapper<Any>(-999, false, "unknown error : $t", null) //3
}
4. JSON
๋ฌธ์์ด์ ResponseWrapper
ํ์์ ๊ฐ์ฒด๋ก Gson
์ ์ด์ฉํด์ ๋ณํํ๊ธฐ : Gson
์ JSON
๋ฌธ์์ด์ POJO(Plain-Old-Java-Object)
๋ ์ฝํ๋ฆฐ ๋ฐ์ดํฐ ํด๋์ค๋ก ์ฝ๊ฒ ๋ณํํ ์ ์๊ฒ ๋์์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค. fromJson<T>(String, Type)
๋ฉ์๋๋ฅผ ์ด์ฉํ๋ฉด ์ฐ๋ฆฌ๊ฐ ๊ฐ๊ณ ์๋ JSON
๋ฌธ์์ด ๊ฐ์ฒด๋ฅผ ResponseWrapper
๊ฐ์ฒด๋ก ๋ฐ๊ฟ ์ ์์ต๋๋ค. ์ด ๊ณผ์ ์์ ๋ 3 ๊ฐ์ง์ ๋ฌธ์ ์ํฉ์ ์ ์ํ ์ ์์ต๋๋ค. ์ฃผ์์ผ๋ก ์ฒ๋ฆฌํด๋ ์ซ์๋ฅผ ๋ณด๋ฉด,
1- JSON
๋ฌธ์์ด์ด ์ฐ๋ฆฌ์ ResponseWrapper
๊ฐ์ฒด๋ก ํ๋ฐ๊ฟ์ ์ฑ๊ณตํ์ง๋ง, success ํ๋๊ฐ false
๋ผ์ ์๋ฒ๋จ์์ ์ ์์ ์ธ ์์ฒญ์ด ์คํจํ ๊ฒฝ์ฐ์
๋๋ค.
2- ์์ ResponseWrapper
๋ก ํ๋ฐ๊ฟ๋ ์คํจํ ๊ฒฝ์ฐ์
๋๋ค.
3- ์์์๋ ์๋ฌ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ์ ๋๋ค.
๊ณตํต์ ์ผ๋ก ์๋ฌ๊ฐ ๋ฐ์ํ๋ ๋ง๋ ResponseWrapper
๋ผ๋ ๊ฐ์ฒด๋ก ์ฝํ๋ฆฐ ๋ฌธ๋ฒ์ ์ด์ฉํด์ ๋ง๋ค์์ต๋๋ค. ์ด๋ ๊ฒ ๋ง๋ ์ด์ ๋ ๋ค์ ๋จ๊ณ์์ ๋ณผ ์ ์์ต๋๋ค. res
๋ผ๋ ๊ฐ์ฒด์ ResponseWrapper
๊ฐ์ฒด๋ฅผ ๊ฐ๊ณ ์๊ฒ ๋์์ต๋๋ค.
/**
* 5) get data json from data
*/
val dataJson = gson.toJson(res.data)
5. ์ํ๋ ๋ฐ์ดํฐ๋ฅผ JSON
๋ฌธ์์ด๋ก ๋ณํ : ์ด์ res
๊ฐ์ฒด์์ ๋ฐ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ค์ JSON
๋ฌธ์์ด๋ก Gson
์ toJson
๋ฉ์๋๋ฅผ ์ด์ฉํด์ ๋ง๋ญ๋๋ค.
/**
* 6) return unwrapped response with body
*/
return response.newBuilder()
.message(res.message)
.body(dataJson.toResponseBody())
.build()
6. ๊ธฐ์กด ์๋ต์ Message
์ Body
๋ง ๊ต์ฒดํด์ ์๋ต ์ ๋ฌ : ๊ธฐ์กด ๊ฐ๊ณ ์๋ ์๋ต์ธ response
๊ฐ์ฒด์ newBuilder()
๋ฉ์๋๋ฅผ ์ด์ฉํด์ ์๋ต์ ๋ณต์ฌํ๊ณ , message
์ ์ค๋นํด๋ message
(์ฑ๊ณต์ผ ๋ ์๋ฒ์์์ message
๊ทธ๋๋ก, ์คํจ์ผ ๋ ๊ณผ์ 4์ ์๋ฌ ๋ฉ์ธ์ง)๋ฅผ, data
์ ์ฐ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ์๋ฏธํ๋ JSON
๋ฌธ์์ด์ RequestBody
๊ฐ์ฒด๋ก ๋ณํํ์ฌ ๋ฃ์ด์ค๋๋ค.
๋ค์์ Interceptor
์ ์ฒด ์ฝ๋์
๋๋ค.
Result๐
์ฐ๋ฆฌ์ ์ฝ๋๊ฐ ์ด๋ป๊ฒ ๋ณํ๋์๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ฐ์ Retrofit
์ API Interface์ ๋ฉ์๋์
๋๋ค. ResponseWrapper
๊ฐ ์ค๊ฐ์์ ๋ชจ์ต์ ๊ฐ์ถ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์๋์ ๊ฐ์ด Network
์์ฒญ ์ฝ๋๋ฅผ ์งค ์ ์๊ฒ ๋์์ต๋๋ค.
์ฌ์ ํ ๋คํธ์ํฌ ํต์ ์ฝ๋๊ฐ ๊น๋ํ์ง ์์ง๋ง ๊ทธ๋ญ์ ๋ญ ์ฌ์ฉํด์ง๋งํด์ก์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋ฐ์ดํฐ : [Funding(nickname=null, fundingIdx=167, userIdx=113, storeIdx=30, fundingMoney=4500, rewardPercent=0, fundingTime=2020-01-03T15:22:02.000Z, rewardMoney=9000)]
๋คํธ์ํฌ ์์ฒญ๋ ๊น๋ํ๊ฒ ์ฑ๊ณตํ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์์ ๊ฐ์ด Interceptor
๋ฅผ ์ฅ์ฐฉํ๋ ๊ฒฝ์ฐ,
{
"status": 200,
"success": true,
"message": "์ฌ์ฉ ๊ฐ๋ฅํ ๋๋ค์์
๋๋ค."
}
์์ ๊ฐ์ด data
๊ฐ ์๋ ์๋ต๋ ์๋์ผ๋ก Code
๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฑ๊ณต์ผ๋ก ์ฒ๋ฆฌํด์ค๋๋ค.
Bonus : Coroutineโค๏ธ
์ต๊ทผ ํ๋ก์ ํธ์์ ์ฌ์ฉํ Coroutine
์ ์์ ๊ฐ์ ์ฝ๋๋ฅผ ํ์ ์๊ฒ ํด์ค๋๋ค. Retrofit
2.6.0๋ถํฐ suspend
ํจ์๋ฅผ ์ด์ฉํ ์ฝ๋ฃจํด ์๋ต ์ง์์ด ์๊ฒผ๋๋ฐ, ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๊ฒ ํฉ๋๋ค.
@GET("mypage/fundlist")
suspend fun getMyFundingHistories() : List<Funding>
์์ ๊ฐ์ด Call
๋ ์์ด suspend
ํจ์๋ก API Interface ๋ฉ์๋๋ฅผ ์ ์ํ๊ณ ,
lifecycleScope.launchWhenCreated {
kotlin.runCatching {
NetworkClient.fundingService.listFundingHistories()
}.onSuccess {
Timber.e("๋ฐ์ดํฐ : $it")
}.onFailure {
Timber.e(it)
}
}
Structured Concurrency์ CoroutineScope
๋ฅผ ์ด์ฉํด ์ํ๋ ๋คํธ์ํฌ ํต์ ์ ๊ฐ๊ฒฐํ๊ฒ ๊ฐ๋ฅํ๊ฒ ํ๊ณ , ์กํฐ๋นํฐ๊ฐ ํ๊ดด๋ ๋ ์๋์ผ๋ก ํต์ ์ด ์ทจ์๋๋๋ก ๋ง๋ค์ด์ค๋๋ค.
Conclusionโ๏ธ
์ฌ๊ธฐ๊น์ง ํด์ OkHttp
์ Interceptor
๋ฅผ ์ด์ฉํด ์๋ฒ์ JSON ์๋ต ์ค, ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋ฐ์ดํฐ ๋ถ๋ถ๋ง ๋ฝ์์ ๋ณ๋์ ํ์ฑ ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ ์ฝ๋๋ฅผ ์งค ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด์์ต๋๋ค.
Retrofit
๊ณผ Gson
์ ๊ณต๋ถํ๋ฉด ๊ณต๋ถํ๋ ๋งํผ Enum
์ ์์ฒญ/์๋ต์ ์ฌ์ฉํ๊ณ ๋คํธ์ํฌ ํต์ ์ ์ฌ๋ฌ ์ํฉ์ ๋ํด ๊น์ด ์ดํดํ๊ณ ๋ค๋ฃจ๋ ๋ฒ์ ๋ฅ์ํด์ง๊ฒ ๋ฉ๋๋ค. ํผ๋๋ฐฑ์ ์ธ์ ๋ ํ์์
๋๋ค.
- Github
- Website
- Medium Blog, Dev Blog, Naver Blog
- Contact: mym0404@gmail.com