Android

Hilt로 Context 사용하기 (feat. OkHttpClient cache)

깨비도 2024. 8. 29. 10:17

0️⃣ Context를 사용 못 해

Singleton 패턴에서는 context를 사용할 수가 없다.

  • 생명 주기 불일치
  • 단위 테스트의 어려움
  • 의존성 주입 어려움

대표적으로 이러한 이유가 있지만 그럼에도 Context가 필요한 상황은 반드시 온다.

더군다나, 나는 Hilt로 DI를 구성해놓은 코드였기 때문에 context를 불러와야할지 잘 몰랐었지만 오히려 Hilt를 사용하고 있어서 Context를 사용하기 더 쉬웠다.

@Module
@InstallIn(SingletonComponent::class)
object YoutubeApiModule {
    private const val cacheSize = 100 * 1024 * 1024 // 100 MB
    private const val YOUTUBE_BASE_URL = "https://www.googleapis.com/youtube/v3/"

    @Singleton
    @Provides
    fun provideOkHttpClient(): OkHttpClient {
        val interceptor = HttpLoggingInterceptor()
        val mCache = Cache(context.cacheDir, cacheSize.toLong()) // 여기서 context 필요!
        
        interceptor.level = HttpLoggingInterceptor.Level.BODY
        return OkHttpClient.Builder()
            .cache(mCache)
            .addInterceptor(AuthorizationInterceptor())
            .addNetworkInterceptor(interceptor)
            .build()
    }

    @Singleton
    @Provides
    fun provideRetrofit(client: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl(YOUTUBE_BASE_URL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    @Singleton
    @Provides
    fun provideYoutubeApi(retrofit: Retrofit): YoutubeApi {
        return retrofit.create(YoutubeApi::class.java)
    }
}

 위 코드에서 provideOkHttpClient 함수 내에서 OkHttpClient에서 cache를 사용하고 싶었는데 object로 구성되어있어 context를 사용할 수 없었다.

 

1️⃣ @ApplicationContext context: Context

@Singleton
@Provides
fun provideOkHttpClient(@ApplicationContext context: Context): OkHttpClient {
    val interceptor = HttpLoggingInterceptor()
    val mCache = Cache(context.cacheDir, cacheSize.toLong())
    interceptor.level = HttpLoggingInterceptor.Level.BODY
    return OkHttpClient.Builder()
        .cache(mCache)
        .addInterceptor(AuthorizationInterceptor())
        .addNetworkInterceptor(interceptor)
        .build()
}

 해결 방법은 이토록 간단한데, provideOkHttpClient 함수의 파라미터로 context를 명시만 해주면 된다! 

@HiltAndroidApp
class PungsunTagoApplication : Application()

 그럼, Hilt를 세팅할 때 최상단에 만들어둔 Application에서 context를 알아서 불러와주기 때문에 파라미터로 context를 명시만 해두면 자동으로 context가 주입되어 쉽게 이용이 가능한 것이다.

 

2️⃣ OkHttp에서 cache는 왜 사용하는가?

 그렇다면 내가 OkHttp에서 cache를 굳이 사용하려고 했던 이유는 무엇일까? 변경되지 않아도 되는 데이터를 동일한 api가 화면을 이동할 때마다 매번 호출하는 현상을 없애고 싶었기 때문이다. 실제로 cache를 사용하는 경우는 아래와 같다.

  • 동일한 데이터를 반복적으로 요청하는 경우
  • 변경되지 않거나 자주 변경되지 않는 데이터를 요청하는 경우
  • 네트워크 연결이 불안정하거나 제한된 대역폭이 있는 경우
  • 서버 부하를 최소화하고자 하는 경우

 실제로 Cache를 통해 서버 부하, 네트워크의 불안정한 연결과 같은 문제점을 해결하기 위해 많이 사용한다고 한다! 좀 더 친근하게 이용해야겠다.

❗ 출처

참고 사이트1 : https://velog.io/@heetaeheo/OkHttp-Cache

 

OkHttp - Cache

Cache (캐시) OkHttp에서의 캐시란 API 호출의 응답을 로컬 저장소에 저장하여 이후 동일한 요청이 발생할 때 서버에서 데이터를 가져오지 않고 로컬 저장소에서 불러오게 하여 성능을 향상시키는

velog.io