![[안드로이드] Authenticator, Hilt dependency cycle 에러](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxZ8Mw%2FbtsMPKIFdmy%2FcSLLvetDkJJMGiO6ctNAjk%2Fimg.png)
안녕하세요 주코입니다.
최근 팀 프로젝트에서 Google OAuth를 개발하던중 RefreshToken을 갱신할때 Hilt의 dependency cycle (순환참조) 에러가 발생하였습니다. 머리를 골골 싸메다가 꽤 괘찮은 해결법을 찾게되어 이렇게 글을 올리게 되었습니다.
원인
Hilt을 통해 Network Module를 설정하고 RefreshToken을 갱신하기위해 Authenticator에서 API와 통신하고있는 DataSource를 주입하고 있었습니다.
이때, dependency cycle이 발생하였습니다.
( 원인, 예시코드 )
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
private val logging = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
@Provides
@Singleton
fun provideAuthInterceptor(tokenManager: TokenManager): AuthInterceptor {
return AuthInterceptor(tokenManager)
}
@Provides
@Singleton
fun provideTokenAuthenticator(
tokenManager: TokenManager,
authDataSource: AuthDataSource
): TokenAuthenticator {
return TokenAuthenticator(authDataSource, tokenManager)
}
@Provides
@Singleton
fun provideOkHttpClient(
authInterceptor: AuthInterceptor,
tokenAuthenticator: TokenAuthenticator
): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(authInterceptor)
.authenticator(tokenAuthenticator)
.addInterceptor(logging)
.build()
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(Constants.API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()
}
@Provides
@Singleton
fun provideAuthApiService(retrofit: Retrofit): AuthApiService {
return retrofit.create(AuthApiService::class.java)
}
}
class TokenAuthenticator @Inject constructor(
private val authDataSource: AuthDataSource,
private val tokenManager: TokenManager
) : Authenticator {
현재 AuthDataSource가 TokenAuthenticator에 주입이되고
TokenAuthenticator가 OkHttpClient에 주입이되고
OkHttpClient가 Retrofit에 주입이되고
Retrofit이 AuthApiService에 주입이되고
AuthApiService는 DataSourceImpl(구현체) 에서 주입이 되고 있었습니다.
이에 따라 dependency cycle이 발생이 하였습니다.
이 문제는 의존성 주입 과정에서 인스턴스가 동시에 생성이 되면서 발생하였습니다.
Hilt는 생성자가 호출되는 순간에 필요한 객체가 없으면, 해당 객체를 먼저 만들려고 시도합니다.
그런데 이 과정에서 또 다른 객체를 필요로 하게 되면서 무한루프에 빠지게 됩니다.
즉, "동시에 생성이 필요해지는 상황"이 발생하면서 dependency cycle이 발생하게 됩니다.
해결법
저는 Authenticator가 RefreshToken을 요청 하는 순간에 인스턴스를 생성시키면서 이 문제를 해결하게 되었습니다.
즉, dagger.Lazy를 통해 인스턴스 생성시점을 get() 을 호출하는 시점에 생성이 되도록 구현하게되었습니다.
여기서 중요한점은 get()을 사용해야만 인스턴스가 생성이 됩니다.
( 해결, 예시코드 )
@Provides
@Singleton
fun provideTokenAuthenticator(
tokenManager: TokenManager,
authDataSource: dagger.Lazy<AuthDataSource>
): TokenAuthenticator {
return TokenAuthenticator(authDataSource, tokenManager)
}
class TokenAuthenticator @Inject constructor(
private val authDataSource: dagger.Lazy<AuthDataSource>,
private val tokenManager: TokenManager
) : Authenticator {
{...}
val newTokenResult = runBlocking { authDataSource.get().refreshToken(refreshToken) }
{...}
}
저는
'Android Studio > - Honey Tip' 카테고리의 다른 글
주코딩의 개발 노트!
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!