의존성(Dependency)이란 클래스가 다른 클래스 또는 객체에 의존하는 관계를 의미한다.
예를 들어, UserRepository 클래스가 ApiService 객체를 필요로 한다면, UserRepository는 ApiService에 의존성을 갖는다고 볼 수 있다.
class UserRepository {
private val apiService = ApiService()
}
위 코드는 UserRepository가 ApiService를 직접 생성(new)하고 있어 강한 결합이 발생한다.
만약 ApiService가 없어지거나 파라미터 변경이 생기면 UserRepsitory 까지 영향이 전달된다.
의존성 주입(DI)은 객체를 직접 생성하는 것이 아니라 외부에서 주입받는 방식을 의미한다.
즉, UserRepository가 ApiService를 직접 생성하지 않고, 외부에서 제공하도록 설계하는 것이다.
class UserRepository(private val apiService: ApiService) {
fun getUser() = apiService.fetchUser()
}
이렇게 하면 UserRepository가 ApiService의 생성 방식에 대해 알 필요가 없고, 테스트할 때 Mock 객체를 쉽게 주입할 수 있어 유연성이 높아진다.

이런 식으로 의존성 주입을 설정하면, 제어의 역전이 이루어진다.
제어를 나타내는 화살표의 방향이 역전이 된 것을 확인할 수 있다.
이는 개발자가 직접 의존성을 제어하던 것을, 어떠한 매개체에게 제어권을 일임하여 더이상 제어의 주체가 개발자가 아니게 되는 것이라고 보면 된다.
Hilt는 Dagger 기반의 안드로이드 DI 라이브러리로, 구글이 공식 지원하며 의존성 관리를 단순화할 수 있도록 도와준다.
기존 Dagger보다 설정이 간단하며, @HiltAndroidApp, @Inject, @Module, @Provides, @Binds 등의 어노테이션을 활용해 의존성을 쉽게 주입할 수 있다.
build.gradle (Project)에 아래 설정을 추가한다.
plugins {
id 'com.google.dagger.hilt.android' version '2.x.x' apply false
}
build.gradle (Module)에 다음 의존성을 추가한다.
plugins {
id 'com.google.dagger.hilt.android'
}
dependencies {
implementation "com.google.dagger:hilt-android:2.x.x"
kapt "com.google.dagger:hilt-android-compiler:2.x.x"
}
@HiltAndroidApp 적용Application 클래스에 @HiltAndroidApp을 추가하면 Hilt가 앱 전체에서 의존성을 관리할 수 있도록 설정된다.
@HiltAndroidApp
class MyApplication : Application()
@Inject를 사용한 의존성 주입Hilt는 생성자 주입(Constructor Injection)을 지원한다.
즉, @Inject를 생성자에 붙이면 Hilt가 자동으로 객체를 주입해 준다.
class UserRepository @Inject constructor(private val apiService: ApiService) {
fun getUser() = apiService.fetchUser()
}
위처럼 UserRepository에 @Inject를 추가하면, ApiService 객체를 Hilt가 알아서 주입해 준다.
@Provides vs @Binds 모듈 사용법Hilt에서는 객체를 제공하는 방법으로 @Provides와 @Binds를 사용할 수 있다.
@Provides 사용 (객체 직접 생성)@Provides는 객체를 직접 생성하여 반환할 때 사용한다.
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
@Provides
@Singleton
fun provideDatabase(
@ApplicationContext context: Context,
): PassionDailyDatabase =
Room.databaseBuilder(
context,
PassionDailyDatabase::class.java,
"passion_daily.db"
).build()
@Provides
@Singleton
fun provideUserDao(database: PassionDailyDatabase): UserDao = database.userDao()
}
@Binds 사용 (인터페이스와 구현체 연결)@Binds는 인터페이스와 구현체 간의 관계를 설정할 때 사용한다.
단, @Binds를 사용하려면 구현체에 @Inject 생성자가 필요하다.
@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
@Binds
abstract fun bindLocalFavoriteRepository(
repository: LocalFavoriteRepositoryImpl
): LocalFavoriteRepository
}
@Inject로 자동 주입 가능한 경우
사진 및 참고 출처)
https://www.youtube.com/watch?v=1vdeIL2iCcM