์๋ฒ์์ OAuth2.0 ์ธ์ฆ ๋์ ์ผ๋ก ์๋๋ก์ด๋ ์ฑ์ ์ฌ์ธ์ธ ๋ฐ api ํต์ ๋ฐ ์๋ฌ์ฒ๋ฆฌ์ ์์ ์ฌํญ์ด ์๊ฒผ๋ค.
OAuth2.0
** OAuth2.0 ๋ฌธ์๋ฅผ ์ฝ๊ณ ์ถ๊ฐํ ์์
Retrofit ์์์ ์ฒ๋ฆฌ
API ํต์ ์, Access Token์ Header์ ๋ฃ์ด์ฃผ๊ณ ์๊ณ , ์ด ์ฒ๋ฆฌ๋ OkHttp์ interceptor๋ฅผ ์ฌ์ฉํด ์ฒ๋ฆฌํ๋ค.
์ฌ์ธ์ธ ํ๋ฉด์ ๋ฐ๋ ํ ํฐ ์ ๋ณด์ ํ ํฐ์ ์ ํจ ๊ธฐ๊ฐ ์ ๋ณด๋ ์๋ ค์ฃผ๋, ์ด๋ฅผ ํ์ฉํ๊ธฐ ๋ณด๋ค๋ API ํต์ ์์ ๋ฐ๋ access token ๋ง๋ฃ ์๋ฌ์ฝ๋๋ฅผ ๋ฐ์ access token์ ๊ฐฑ์ ํ ๋ค์ ํด๋น API ํต์ ์ ์งํํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๊ตฌํํ๊ธฐ๋ก ํ๋ค.
OkHttpClient์ addํ๋ ๊ธฐ์กด interceptor๋ ํค๋์ access token์ ์ฝ์ ํ๋ ์ญํ ์ ํ๊ณ ์์๋ค. ์ด interceptor์์ reponse์ ์๋ฌ์ฝ๋๋ฅผ ํ์ฑํด ๋ค์๊ณผ ๋ก์ง์ ํ๋๋ก ์์ ํ๋ค.
A) access token ๋ง๋ฃ ์๋ฌ์ฝ๋๊ฐ ๋ด๋ ค์ค์ง ์์ผ๋ฉด ๋ฐ์ reponse๋ฅผ ๋ฆฌํดํด์ฃผ๊ธฐ
B) access token ๋ง๋ฃ ์๋ฌ์ฝ๋๊ฐ ๋ด๋ ค์ค๋ฉด access token์ ๊ฐฑ์ ํด์ ํด๋น API ํต์ ์ response๋ฅผ ๋ฆฌํดํด์ฃผ๊ธฐ
C) access token ๋ง๋ฃ ์๋ฌ์ฝ๋๊ฐ ๋ด๋ ค์ค๋ฉด access token์ ๊ฐฑ์ ํ์ง๋ง refresh token ๋ง๋ฃ ์๋ฌ๋ก ์คํจํ ๊ฒฝ์ฐ
C-1) ์ด๋ฉ์ผ ๊ณ์ ์ ๊ฒฝ์ฐ ๋ก๊ทธ์์ํด์ ๋ก๊ทธ์ธ ํ๋ฉด์ผ๋ก ์ง์ ํ๊ธฐ
C-2) SNS ๊ณ์ ์ ๊ฒฝ์ฐ SNS ์๋น์ค์ refresh token์ ๋ฐ์ ๋ค์ ๋ก๊ทธ์ธํ๊ณ ํด๋น API ํต์ ์ response๋ฅผ ๋ฆฌํดํด์ฃผ๊ธฐ
๊ตฌํ ๊ณผ์ ์์ ๋ง์ฃผํ ๋ฌธ์ ๋ค์ ๋ค์๊ณผ ๊ฐ๋ค.
Q1. ์๋ฌ์๋ต ํ์ฑ์ ์ํด ํ ๋ฒ ์๋นํ body๋ ์ฌ์ฌ์ฉ์ด ๋ถ๊ฐํ๋ค. ์๋ฌ์๋ต ํ์ฑ์ด ๋๋ ํ response๋ฅผ ๋ฆฌํดํด์ค์ผ ํ๋๋ฐ ๋ฌธ์ ๋ด์ฐฉ.
A1. ์๋ฌ ์๋ต ํ์ฑ์ ์ํด body๋ฅผ ํ๋ฒ ์๋นํ๊ธฐ ๋๋ฌธ์ ์๋ก ๋ง๋ค์ด์ฃผ์ง ์์ผ๋ฉด ๋ค๋ฅธ ์ธํฐ์ ํฐ์์ body ์ ๊ทผ ์ ํฌ๋์ ๋๋ค. ๊ฐ์ ์ฝํ ์ธ ์ body๋ฅผ ๊ฐ์ง ์ response๋ฅผ ๋ง๋ค์ด ๋ฆฌํดํด์ค๋ค.
class MyInterceptor : Interceptor {
override fun intercept(chain : Interceptor.Chain): Response {
val request = chain.request().newBuilder().addHeader("key",accessToken).build()
val originalResponse = chain.proceed(request)
val body = originalResponse.body ?: return originalResponse
val bodyString = body.string()
val newResponse = originalResponse.newBuilder().body(bodyString.toResponseBody(body.contentType())).build()
....
//์๋ฌํ์ฑ ํ ๋ฌธ์ ์๋ ๊ฒฝ์ฐ
return newResponse
}
}
Q2. ์๋ฌ์ฝ๋ ํ์ฑ์ ์ด๋ป๊ฒ ํ๋. ์ธํฐ๋ท์ ์์ ๋ค์ ๋ณด๋ฉด repsonse์ code ๊ฐ์ผ๋ก 200 ์ธ์ ๊ฐ๋ค์ ํ์ธํด์ ๊ฐ๋จํ๊ฒ ์ํ๋ฅผ ํ์ธํด์ ์งํํ๋๋ฐ. ์ฐ๋ฆฌ ์๋ฒ๋ code๋ฅผ 200์ผ๋ก ๋ด๋ ค์ฃผ๊ณ response body ์์ status์ error code ๊ฐ์ ๋ฐ๋ก ์ ๊ณตํด์ค์ ์์ ๋ค์ฒ๋ผ ๊ตฌํํ ์๊ฐ ์๋ค. ์ด๊ฑฐ ๊ฐ์ฅ ๊ฐ๋จํ๊ฒ ํ์ฑํ ๋ฐฉ๋ฒ์ ์๋?
A2. Gson์ ์ด์ฉํ๋ค.
//Data : ์๋ฒ์์ ๋ฐ๋ response body์ form.
val type = object : TypeToken<Data<*>>() {}.type
val errorCode : Int = try {
val data = Gson().fromJson<Data<*>>(bodyString, type) ?: throw JsonSyntaxException()
if(data.status == 200) return newResponse else data.errorCode
} catch (e: JsonSyntaxException) {
return newResponse
} catch (t: Throwable) {
return newResponse
}
Q3. ์ด๋ฉ์ผ ๊ณ์ ์ด refresh token ๋ง๋ฃ๋ก access token ๊ฐฑ์ ์ ์คํจํ๋ฉด ๋ก๊ทธ์์ํ๊ณ ๋ก๊ทธ์ธ ํ๋ฉด์ผ๋ก ์ด๋ํด์ผ ํ๋๋ฐ, ์ด ์ฒ๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ๊ตฌํํ์ง? API ํต์ ์ ์ด interceptor ์ธ์ ๋ค๋ฅธ interceptor๋ค๋ ์กด์ฌํ๊ณ , ์๋ง์ ๊ฐ๋ฐ์๋ค์ด ๊ฑฐ์ณ๊ฐ ํ๋ก์ ํธ๋ผ์ API ํต์ ์๋น์ค ๊ธฐ๋ฅ์ด ํต์ผ๋์ง ์๊ณ ๋ค์ํ ์ํ์ด๋ค. ์๋ฌ ๊ณตํต์ฒ๋ฆฌ๊ฐ ์ ์ด๋ฃจ์ด์ง์ง ์์ ์ํ์์ ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ๋ฌด์์ด ์์๊น?
A3. ์ด๋ฉ์ผ ๊ณ์ ์ด refresh token ๋ง๋ฃ ์๋ฌ ์ฝ๋๋ฅผ ๋ฐ์ผ๋ฉด custom exception๋ฅผ throw ์ํค์. custom exception์ ๋ฐ์ผ๋ฉด ๋ก๊ทธ์์์ํค๊ณ ๋ก๊ทธ์ธ ํ๋ฉด์ผ๋ก ๋์๊ฐ๋๋ก, Throwable์ ํ์ฅํจ์๋ฅผ ๋ง๋ค์ด์ API ํต์ ์ exception ์ฒ๋ฆฌ๋ก ์ ๊ทผํ์. ๋ชจ๋ API ํต์ ๋ถ๋ถ๋ค์ ์ดํด์ผ๋ ํ๊ฒ ์ง๋ง, throwable์ ํ์ฅํจ์๋ฅผ ์ฐ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
Q4. SNS ๊ณ์ ์ด refresh token ๋ง๋ฃ ์์๋ SNS ๋ก๊ทธ์ธ์ ์๋ํด์ผ ํ๋ค. kakao๋ facebook ๊ฐ์ SNS library์์๋ callback์ผ๋ก token ๊ฐ์ ธ์ค๊ธฐ ๋ฐ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ณ ์์ด์ ๋น๋๊ธฐ๋ก ๋์ํ๋ค. ๊ทธ๋ฌ๋ ๋๊ธฐ๋ก token ๊ฐ์ ธ์ค๊ธฐ, ์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์งํํด์ผ ํ๋ ์ํฉ์ด๋ค. callback์ด ์คํ๋ ์ดํ์ ๋ค์ ์์ ์ ์งํํ๋๋ก ๋๊ธฐ๋ก ์คํํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ธ๊ฐ?
A4. CountDownLatch๋ฅผ ์ฌ์ฉํ๋ค.
//์นด์นด์ค์ชฝ
val latch = CountDownLatch(1)
UserApiClient.instance.me { user: User?, error: Thrawable? ->
if (error != null) {
...
latch.countDown()
} else if (user != null) {
...
latch.countDown()
}
}
latch.await()
'๋น ๊ตฌ๋ฉ ์ฑ์ฐ๊ธฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] ViewGroup.LayoutParams ๋ฌธ์ ์ฝ๊ธฐ (0) | 2022.10.12 |
---|---|
[Android] View ๋ฌธ์ ์ฝ๊ธฐ (1) | 2022.10.07 |
[Android] androidx.fragment.app.FragmentContainerView (0) | 2022.08.22 |
[Android] API vs SKD ์ฐจ์ด (0) | 2022.08.19 |
[Android] ๋คํธ์ํฌ ์์ ์ค ๊ฐํ์ java.io.IOException: unexpected end of stream on (0) | 2022.08.18 |