api 통신을 할 때 retrofit 설정을 해줘야 합니다
규모가 작을 땐 개별적으로 retrofit 인스턴스를 생성해서 사용할 수도 있지만 규모가 커졌을 때를 생각하면 부적절한 방법일 수 있습니다
코드 중복, 유지 보수 등등 여러 단점들이 생길 수 있기 때문입니다
이러한 단점들을 보완하는 방법은 Hilt라고 생각합니다
간단하게 Hilt에 대해서 설명하면
What is Hilt ?
- Android 애플리케이션을 위한 의존성 주입(DI) 라이브러리입니다
Dagger를 기반으로 하여 보다 간편하고 효율적인 의존성 주입을 제공합니다
Hilt는 애플리케이션의 생명 주기를 고려한 의존성 관리와 자동 주입 기능을 통해 코드의 간결성과 테스트 용이성을 높여줍니다👍
그래서 retrofit 인스턴스의 사용에서 hilt로 변환 후 사용법까지 한 번 보시죠 ~ 🙋
object LoginRetrofitClient {
private const val BASE_URL = "API URL"
private val logging =
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
// cURL을 확인 하기 위해 사용
private val okHttpClient =
OkHttpClient.Builder()
.addInterceptor(logging)
.build()
private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
val loginApi: LoginApi = getRetrofit().create(LoginApi::class.java)
}
하지만 프로젝트 규모가 커질수록 api 통신하는 부분이 많아지게 된다면
retrofit 설정 코드를 중복하여 작성하게 됩니다
이러한 단점들은 아래와 같습니다
- retrofit을 사용하는 곳 마다 코드 중복이 발생합니다
- retrofit 설정을 변경했을 시에, 모든 코드를 찾아서 수정해야함으로 유지보수가 어려워 집니다
- 여러 곳에서 개별적으로 retrofit 인스턴스를 생성하여 사용하게 된다면 설정이 일관되지 않을 수 있습니다
코드 중복과 여러 단점들을 개선시켜줄 수 있는 것이 Hilt 입니다
// Hilt
implementation("com.google.dagger:hilt-android:2.46")
kapt("com.google.dagger:hilt-android-compiler:2.46")
@Module
@InstallIn(SingletonComponent::class)
class AppModule {
@Provides
fun provideOkHttpClient(): OkHttpClient {
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
return OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build()
}
@Provides
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl("API URL")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
}
retrofit 셋팅을 했으면 사용할 api를 연결하면 됩니다
interface ProfileInfoGetApi {
@GET("members/profile")
suspend fun getInformation(
@Header("Authorization") accessToken: String?,
): Response<ProfileResponse>
}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@Provides
fun provideHomeProfileApi(retrofit: Retrofit): ProfileInfoGetApi {
return retrofit.create(ProfileInfoGetApi::class.java)
}
retrofit 설정과 사용할 api를 hilt에 주입시킨 상태입니다
class ProfileGetDataSourceImpl @Inject constructor(
private val profileInfoGetApi: ProfileInfoGetApi,
private val accessToken: SharedPreferences,
): ProfileGetDataSource{
override suspend fun getInformation(): ApiResult<ProfileResponse> {
return try {
val profileInfoGetResponse = profileInfoGetApi.getInformation(
accessToken.getString("ApiAccessToken", null),
)
...
} else {
...
}
} catch (e: Exception) {
...
}
}
}
@Inject constructor()
로 사용할 api를 주입해서 사용합니다
- 의존성을 주입받는 방식이므로, 다른 설정이나 객체로 쉽게 교체 가능합니다
- 테스트 환경에 맞는 객체를 쉽게 주입할 수 있습니다
- 의존성의 생성과 주입이 명확히 관리되고, 코드의 가독성과 유지보수성이 향상됩니다
- Hilt는 Android의 생명주기와 통합되어 있어, 의존성을 적절한 시점에 생성하고 소멸시킵니다