-
Notifications
You must be signed in to change notification settings - Fork 0
헤더를 동적으로 넣는 방법
현재 앱은 소셜 기반의 캘린더 앱이기 때문에 서버에서 요청하는 API 수가 상당히 많고 많은 리소스를 가져오고 올려야 한다.
리소스를 사용하는 서버 API는 인증을 위해 헤더에 Access Token을 사용하고 있다. 수많은 API를 요청할 때 어떻게 헤더에 AccessToken을 넣을 수 있을까???
이를 위해 안드로이드 팀원들이 모여 함께 공부하고 해결책을 찾는 과정을 가졌다.
첫 번째로 사용한 가장 간단한 방법은 바로 API 요청 시에 Header를 인자로 넣어주자는 의견이다.
@GET("user/info")
suspend fun getUserProfile(@Header("Authorization") accessToken: String): UserProfile
위의 코드와 같이 간단하게 인자로 AccessToken을 넣을 수 있다.
하지만, 이렇게 모든 API 요청에 Header를 넣어주면 코드가 번거로워지고 Data Store에서 매번 요청을 할 때마다 AccessToken을 가져오는 코드를 모든 Repository의 함수에 포함해야 한다. 코드의 양이 비대해져서 좋은 방법이 아니라는 판단을 내렸다.
두 번째 방법은 OkHttp의 Interceptor를 통해 힐트에서 retrofit을 생성할 때 Interceptor를 함께 넣어서 생성하는 방법이다.
Interceptor의 intercept 함수를 override 하게 되면 api request 전에 요 동적으로 access token을 헤더에 넣어줄 수 있다고 판단하였다.
override fun intercept(chain: Interceptor.Chain): Response {
val token = runBlocking {
dataStoreHelper.getAccessToken()
}
val tokenAddedRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer $token")
.build()
return chain.proceed(tokenAddedRequest)
}
위의 코드와 같이 API 요청에서 request를 보낼 때 인터셉터에서 DataStore에서 accessToken을 가져와서 헤더를 넣어준다. 여기서 하나의 의문점이 생긴다. 만약 AccessToken이 만료되면 어떻게 동작을 할까??? 이에 대해서, accessToken이 만료된다면 refreshToken을 이용하여 accessToken을 갱신해주면 된다. 하지만, 예외가 발생했을 때 repository에서 이 예외에 대해 refreshToken을 이용하여 accessToken을 다시 받아온다면 모든 repository에서 이와 같은 동일한 코드를 작성해야한다.
마지막으로 추가한 방법은 Interceptor에서 돌아온 response를 먼저 확인해서 accessToken이 만료되면 refreshToken을 이용하여 다시 한번 accessToken을 서버로부터 갱신받고 다시 한번 api 요청을 보내는 방법이다.
이에 따라, accessToken이 만료가 되지 않았다면 바로 response를 뿌려주고 만료가 되었을 때 accessToken을 refreshToken로 갱신에 실패한다면 로그인 화면으로 이동하는 방법을 사용하였다.
override fun intercept(chain: Interceptor.Chain): Response {
val token = runBlocking {
tokenRepository.getAccessToken()
}
val tokenAddedRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer $token")
.build()
val response = chain.proceed(tokenAddedRequest)
if (response.code == 401) {
val accessToken = runBlocking {
tokenRepository.refreshAccessToken()
}
val refreshedRequest = chain.request().putTokenHeader(accessToken)
return chain.proceed(refreshedRequest)
}
return response
}
private fun Request.putTokenHeader(accessToken: String): Request {
return this.newBuilder()
.addHeader("Authorization", "Bearer $accessToken")
.build()
}
위와 같은 방법을 이용하여 한 곳에서 동적으로 모든 api 요청에 대해 header를 넣고 accessToken 만료에 대해 대응을 할 수있는 장점을 얻었다.
- Week1 - Day01
- Week1 - Day02
- Week1 - Day03
- Week1 - Day04
- Week2 - Day01
- Week2 - Day02
- Week2 - Day03
- Week2 - Day04
- Week3 - Day01
- Week3 - Day02
- Week3 - Day03
- Week3 - Day04
- Week4 - Day01
- Week4 - Day02
- Week4 - Day03
- Week4 - Day04
- Week4 - Day05
- Week5 - Day01
- Week5 - Day02
- Week5 - Day03
- Week5 - Day04
- Week6 - Day01
- Week6 - Day02