로그인이 있는 프로젝트 진행시 Authorization Header는 API 호출에서 사용자 인증을 위한 핵심 요소입니다. 하지만 각 요청마다 이를 반복적으로 추가하는 코드는 중복적이고 유지보수가 어렵습니다.
이를 해결하기 위해 OkHttp Interceptor를 활용하여 Authorization Header를 공통적으로 처리하는 방법을 소개합니다.
Interceptor는 okHttp의 요청(Request) 또는 응답(Response)를 가로채서 중간에 로직을 추가할 수 있는 도구입니다.
이를 활용하면 모든 네트워크 요청에 대해 일관된 처리가 가능합니다.
// 예시 코드
interface RecipeApi {
@GET("recipes")
suspend fun getAllRecipeFeeds(
@Header("Authorization") authorization: String,
@Query("page") page: Int,
@Query("size") size: Int,
@Query("sort") sort: String,
): Response<PagingResponse<RecipeFeedContent>>
@GET("recipes")
suspend fun getRecipeFeedByType(
@Header("Authorization") authorization: String,
@Query("vegetarianType") vegetarianType: String,
@Query("page") page: Int,
@Query("size") size: Int,
@Query("sort") sort: String,
): Response<PagingResponse<RecipeFeedContent>>
@GET("recipes/{id}")
suspend fun getRecipeDetailContent(
@Header("Authorization") authorization: String,
@Path("id") id: Long
): Response<RecipeDetailContent>
...
}
RecipeApi 말고도 많은 Api에서 Authorization Header를 가지고 통신하기 때문에 이것보다 더 많은 코드가 중복되고 있다는 것을 알 수 있습니다
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
@Module
@InstallIn(SingletonComponent::class)
class AppModule {
@Provides
@Singleton
fun provideRetrofit(
okHttpClient: OkHttpClient,
gsonConverterFactory: GsonConverterFactory
): Retrofit {
return Retrofit.Builder()
.baseUrl(BuildConfig.BASEURL)
.client(okHttpClient)
.addConverterFactory(gsonConverterFactory)
.build()
}
@Provides
@Singleton
fun provideOkHttpClient(
authorizationInterceptor: Interceptor,
): OkHttpClient {
val builder = OkHttpClient.Builder()
val loggingInterceptor = HttpLoggingInterceptor()
loggingInterceptor.level = HttpLoggingInterceptor.Level.BASIC
builder.apply {
addInterceptor(loggingInterceptor)
addInterceptor(authorizationInterceptor)
return builder.build()
}
@Singleton
@Provides
fun providesAuthorizationInterceptor(
tokenManager: TokenManager,
) = Interceptor { chain ->
val accessToken = tokenManager.getAccessToken()
val request = chain.request().newBuilder()
.header("Authorization", "$accessToken")
.build()
chain.proceed(request)
}
}
provideRetrofit: Retrofit 인스턴스를 생성합니다.
provideOkHttpClient: Interceptor를 OkHttpClient에 추가합니다.
providesAuthorizationInterceptor: 토큰을 가져와 Header를 추가합니다.
중복 코드 제거: Authorization Header 추가 코드가 모든 API 호출에서 제거됩니다.
유지 보수성 향상: 토큰 관리 로직을 Interceptor에서 중앙 집중화하여 수정이 용이합니다.
일관성 보장: 모든 요청에 일관되게 Authorization Header를 추가할 수 있습니다.
코드 가독성 향상: API 호출부의 코드가 간결해져 비즈니스 로직에만 집중할 수 있습니다.
구현 복잡성: Interceptor를 처음 설정할 때 동적으로 토큰을 가져오는 로직이 필요해질 수 있습니다.
동기화 문제: 만약 토큰이 만료되거나 갱신이 필요한 경우, Interceptor 내에서 이를 처리해야 하는 추가 로직이 필요합니다.
디버깅의 어려움: 요청이 Interceptor를 거쳐 변형되므로, 디버깅 시 Interceptor 단계를 고려해야 합니다.
Authorization Header를 모든 요청에서 반복적으로 추가하는 것은 비효율적이며, 유지 보수를 어렵게 만듭니다. 이를 해결하기 위해 OkHttp의 Interceptor를 활용하면 효율적인 코드 관리와 일관된 인증 처리가 가능합니다. Interceptor는 초기 설정 과정에서 약간의 복잡성이 있을 수 있지만, 프로젝트의 규모가 커질수록 그 진가를 발휘한다고 생각합니다.