Android์์ Hilt๋ฅผ ํ์ฉํ ์์กด์ฑ ์ฃผ์ (DI)์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํ ์ด๋ ธํ ์ด์ ์ ์ ๋ฆฌํ์ต๋๋ค.
Hilt๋ Dagger 2 ๊ธฐ๋ฐ์ ์์กด์ฑ ์ฃผ์
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, Android์์ DI๋ฅผ ๋ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋์์ค๋๋ค.
๋ค์์ Hilt์์ ์ฌ์ฉ๋๋ ์ฃผ์ ์ด๋
ธํ
์ด์
๊ณผ ์ญํ ์ ์ ๋ฆฌํ ๋ด์ฉ์
๋๋ค.
์ด ์ด๋ ธํ ์ด์ ๋ค์ Hilt๊ฐ ๊ด๋ฆฌํ๋ ์ปดํฌ๋ํธ ๋ฐ ์์กด์ฑ์ ๋ฒ์๋ฅผ ์ค์ ํ๋ ์ญํ ์ ํฉ๋๋ค.
@HiltAndroidAppApplication ํด๋์ค์ ์ ์ธํด์ผ ํ๋ฉฐ, Hilt์ ์ง์
์ ์ญํ ์ ํฉ๋๋ค.@HiltAndroidApp
class MyApplication : Application()
@AndroidEntryPointActivity์์ Hilt๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ด ์ด๋
ธํ
์ด์
์ ์ถ๊ฐํด์ผ ํฉ๋๋ค.@AndroidEntryPoint
class MainActivity : AppCompatActivity()
@HiltViewModel@HiltViewModel
class MyViewModel @Inject constructor(private val repository: MyRepository) : ViewModel()
@EntryPoint@EntryPoint
@InstallIn(SingletonComponent::class)
interface WorkerEntryPoint {
fun getRepository(): MyRepository
}
Hilt์์ ์์กด์ฑ์ ์ ๊ณตํ๋ ๋ฐฉ๋ฒ์ ์ ์ํ๋ ์ด๋ ธํ ์ด์ ์ ๋๋ค.
@Module@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
fun provideString(): String = "Hello, Dagger Hilt!"
}
@InstallIn@Module
@InstallIn(SingletonComponent::class)
object NetworkModule
@Provides@Provides
fun provideApiService(): ApiService = ApiServiceImpl()
@Bindsabstract ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
@Binds
abstract fun bindRepository(impl: RepositoryImpl): Repository
}
@BindsInstance@BindsInstance
fun bindBaseUrl(@Named("BASE_URL") baseUrl: String): Builder
์ค์ ๊ฐ์ฒด๊ฐ ์ฃผ์ ๋๋ ๋ฐฉ์๊ณผ ๊ด๋ จ๋ ์ด๋ ธํ ์ด์ ์ ๋๋ค.
@Injectclass Repository @Inject constructor(private val apiService: ApiService)
@Named@Provides
@Named("API_URL")
fun provideApiUrl(): String = "https://example.com"
class ApiService @Inject constructor(@Named("API_URL") private val apiUrl: String)
@Qualifier@Named์ ์ ์ฌํ์ง๋ง, ์ฌ์ฉ์ ์ง์ ์ด๋
ธํ
์ด์
์ ๋ง๋ค ๋ ์ฌ์ฉ๋ฉ๋๋ค.@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class LocalDataSource
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class RemoteDataSource
Hilt์์ ํน์ ๋ฒ์์ ๋ง๊ฒ ๊ฐ์ฒด๋ฅผ ๊ด๋ฆฌํ ์ ์๋๋ก ์ค์ ํ๋ ์ด๋ ธํ ์ด์ ์ ๋๋ค.
@Singleton@Provides
@Singleton
fun provideDatabase(): AppDatabase = Room.databaseBuilder(...)
@ViewScoped@ViewScoped
@Provides
fun provideViewScopedRepository(): ViewScopedRepository
| ์ด๋ ธํ ์ด์ | ์ค๋ช |
|---|---|
@HiltWorker | WorkManager์์ Hilt๋ฅผ ์ฌ์ฉํ ๋ ์ฌ์ฉ |
@EntryPoint | Hilt์์ ๊ด๋ฆฌ๋์ง ์๋ ํด๋์ค์์ DI๋ฅผ ์ฌ์ฉํ ๋ ์ฌ์ฉ |
@ViewScoped | View์ ์๋ช ์ฃผ๊ธฐ์ ๋ง์ถฐ ๊ฐ์ฒด๋ฅผ ๊ด๋ฆฌ |
| ์ด๋ ธํ ์ด์ | ์ญํ |
|---|---|
| ์ ํ๋ฆฌ์ผ์ด์ & ์ํธ๋ฆฌ ํฌ์ธํธ | |
@HiltAndroidApp | Application์์ Hilt ์ค์ |
@AndroidEntryPoint | Activity, Fragment ๋ฑ์์ DI ํ์ฑํ |
@HiltViewModel | ViewModel์์ Hilt ์ฌ์ฉ |
@EntryPoint | Hilt์์ ๊ด๋ฆฌ๋์ง ์๋ ํด๋์ค์์ DI ์ฌ์ฉ |
| ๋ชจ๋ & ๋ฐ์ธ๋ฉ | |
@Module | ์์กด์ฑ์ ์ ๊ณตํ๋ ํด๋์ค |
@InstallIn | ๋ชจ๋์ด ์ฃผ์ ๋ ์ปดํฌ๋ํธ ์ง์ |
@Provides | ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ์ฌ ์ ๊ณต |
@Binds | ์ธํฐํ์ด์ค - ๊ตฌํ์ฒด ์ฐ๊ฒฐ |
@BindsInstance | ๋ฐํ์์ ๊ฐ์ ์ฃผ์ |
| ์์กด์ฑ ์ฃผ์ & ์ค์ฝํ | |
@Inject | ์์ฑ์ ์ฃผ์ ์ฌ์ฉ |
@Named | ๊ฐ์ ํ์ ์ ์ฌ๋ฌ ๊ฐ์ฒด ์ฃผ์ |
@Qualifier | ์ปค์คํ ์ฃผ์ ์ด๋ ธํ ์ด์ |
@Singleton | ์ฑ๊ธํค ๋ฒ์ ์ง์ |
@HiltWorker | WorkManager์์ Hilt ์ฌ์ฉ |
๊ณต๋ถํ๋ฉด์ ๋ฌธ๋ ๊ทธ๋ฐ ์๊ฐ์ด ๋ค์๋ค.
๋๋ ์ง๊ธ๊น์ง ์ธํฐํ์ด์ค - ๊ตฌํ์ฒด ์ฐ๊ฒฐํ ๋ @Provides๋ก ์ฒ๋ฆฌํ๊ณ ์์๋๋ฐ,
@Binds๊ฐ ํด๋น ์ญํ ์ ํ ๋ ์ฌ์ฉํ๋ ์ด๋
ธํ
์ด์
์ด๋ผ๋! ๊ทธ๋์ ๋น๊ต๋ฅผ ํ๋ คํ๋ค.
@Provides๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ@Module
@InstallIn(SingletonComponent::class)
object RepositoryModule {
@Provides
fun provideRepository(apiService: ApiService): Repository {
return RepositoryImpl(apiService)
}
}
@Binds๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
@Binds
abstract fun bindRepository(impl: RepositoryImpl): Repository
}
@Provides vs @Binds ์ฐจ์ด์ | ๋น๊ต ํญ๋ชฉ | @Provides | @Binds |
|---|---|---|
| ๋ฐํ ๋ฐฉ์ | ์ง์ ๊ฐ์ฒด๋ฅผ ์์ฑํด ๋ฐํ | ์ด๋ฏธ ์์ฑ๋ ๊ฐ์ฒด๋ฅผ ๋ฐ์ธ๋ฉ |
| ์ฌ์ฉ ๊ฐ๋ฅ ์กฐ๊ฑด | ์์ฑ์๊ฐ @Inject ์์ด๋ ๊ฐ๋ฅ | ์์ฑ์ ์ฃผ์
(@Inject constructor) ํ์ |
| ์ฝ๋ ์คํ์ผ | ์ผ๋ฐ์ ์ธ ํฉํ ๋ฆฌ ๋ฉ์๋ ๋ฐฉ์ | ์ถ์ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ธ์ ์คํ์ผ ์ ์ง |
| ํ์ํ ํค์๋ | ์ผ๋ฐ fun ๋ฉ์๋ ์ฌ์ฉ | abstract fun ๋ฉ์๋ ์ฌ์ฉ |
| ์ฌ์ฉ ๊ถ์ฅ ์์ | ๋ณต์กํ ๋ก์ง์ด ํ์ํ ๊ฒฝ์ฐ | ๋จ์ํ ์ธํฐํ์ด์ค - ๊ตฌํ์ฒด ์ฐ๊ฒฐํ ๋ |
@Provides๋ง ์จ๋ ๋๋ ๊ฑธ๊น?์๋๋ค. @Provides๋ง ์จ๋ ๋์์ ํ์ง๋ง, ์ต์ ํธ๋ ๋์์๋ @Binds๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฉด @Binds๋ฅผ ์ฐ๋ ๊ฒ์ด ๋ ๊ถ์ฅ๋๋ ๋ฐฉ์.
@Binds๋ฅผ ์ ํธํ๋ ์ด์ ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋ ๊ฐ์
@Provides๋ ์ง์ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํด์ ์ฝ๋๊ฐ ๊ธธ์ด์ง ์ ์์.@Binds๋ ๋จ์ํ "์ด ๊ตฌํ์ฒด๋ฅผ ์ธํฐํ์ด์ค๋ก ์ฌ์ฉํ ๊ฒ!" ๋ผ๊ณ ์ ์ธํ๋ ๋ฐฉ์์ด๋ฏ๋ก ๋ ๊น๋ํจ.Dagger๊ฐ ์ต์ ํ๋ ๊ทธ๋ํ๋ฅผ ๊ตฌ์ฑํ ์ ์์
@Binds๋ ๋ถํ์ํ ๊ฐ์ฒด ์์ฑ์ ๋ฐฉ์งํ๊ณ , ์์กด์ฑ ๊ทธ๋ํ๊ฐ ๋ ํจ์จ์ ์ผ๋ก ๋์ํ๊ฒ ํจ.์ ์ง๋ณด์์ฑ ์ฆ๊ฐ
@Binds๋ฅผ ์ฌ์ฉํ๋ฉด ์์ฑ์ ์ฃผ์
์ ๊ฐ์ ํ ์ ์์ด์ ์ ์ง๋ณด์๊ฐ ํธ๋ฆฌํจ.@Provides๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ๊ธฐ ๋๋ฌธ์, ์์กด์ฑ ๋ณ๊ฒฝ ์ @Provides ๋ฉ์๋๋ฅผ ์์ ํด์ผ ํ ์๋ ์์.@Provides๋ฅผ ์จ์ผ ํ๋ ๊ฒฝ์ฐ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์๋ @Provides๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ํ์์ ์ด๊ฑฐ๋ ๋ ์ ์ .
์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ์ฒด๋ฅผ ์ ๊ณตํด์ผ ํ ๋
Retrofit, OkHttpClient, Room Database ๊ฐ์ ๊ฐ์ฒด๋ค์ ์ฐ๋ฆฌ๊ฐ ์์ฑ์๋ฅผ ์์ ํ ์ ์์ผ๋ฏ๋ก @Provides๋ฅผ ์ฌ์ฉํด์ผ ํจ.@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com")
.build()
}
}
๊ฐ์ฒด ์์ฑ ์ ๋ณต์กํ ๋ก์ง์ด ํ์ํ ๋
@Provides๊ฐ ๋ ์ ์ ํจ.@Provides
fun provideRepository(apiService: ApiService): Repository {
return RepositoryImpl(apiService, enableLogging = true)
}
@Binds๋ ๋จ์ํ ์ธํฐํ์ด์ค-๊ตฌํ์ฒด ์ฐ๊ฒฐ์ ์ํด ์ฌ์ฉ๋๋ฏ๋ก, ์ด๋ฐ ๊ฒฝ์ฐ @Provides๊ฐ ํ์ํจ.์์ฑ์ ์ฃผ์ ์ด ๋ถ๊ฐ๋ฅํ ๊ฒฝ์ฐ
@Binds๋ ์์ฑ์ ์ฃผ์
(@Inject constructor)์ด ๊ฐ๋ฅํด์ผ๋ง ์ฌ์ฉํ ์ ์์.private์ด๊ฑฐ๋, object, sealed class ๋ฑ์ ๊ฒฝ์ฐ @Binds๋ฅผ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ @Provides๊ฐ ํ์ํจ.@Binds๋ฅผ ์ฐ์ ์ฌ์ฉํ๊ณ , ํ์ํ ๋๋ง @Provides ์ฌ์ฉโ
์ธํฐํ์ด์ค - ๊ตฌํ์ฒด ์ฐ๊ฒฐ์ @Binds๋ฅผ ์ฌ์ฉ!
โ
์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ณต์กํ ๊ฐ์ฒด ์์ฑ์ด ํ์ํ๋ฉด @Provides๋ฅผ ์ฌ์ฉ!
// โ
๊ถ์ฅ๋๋ ๋ฐฉ์: @Binds ์ฌ์ฉ
@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
@Binds
abstract fun bindRepository(impl: RepositoryImpl): Repository
}
// โ
์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ณต์กํ ๋ก์ง์ด ํ์ํ ๊ฒฝ์ฐ @Provides ์ฌ์ฉ
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com")
.build()
}
}
๐ ๋ ์์ธํ ๋ด์ฉ์ด ๊ถ๊ธํ๋ค๋ฉด ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์!
๐ ๊ณต์ ๋ฌธ์