08
02

์š”์ฆ˜ Hilt๋ฅผ ์‚ฌ์šฉ ์ค‘์ธ๋ฐ, ์ž๊พธ ๋ฌด์˜์‹์ ์œผ๋กœ `@Provides`, `@Binds`๋ฅผ ๋ถ™์ด๋Š” ๊ฒƒ ๊ฐ™์•„ ์ด๋ฒˆ์— ์ข€ ์ž์„ธํžˆ ์ •๋ฆฌํ•˜๊ณ  ๋„˜์–ด๊ฐ€๊ฒ ๋‹ค.

 

Hilt์— ๋Œ€ํ•œ ํฌ์ŠคํŒ…์„ ์ด์ „์— ์„ธ ๊ฐœ์ •๋„ ํ–ˆ๋Š”๋ฐ, ๊ทธ๊ฑฐ๋ž‘์€ ๋ณ„๊ฐœ๋กœ ์˜ฌ๋ฆฐ๋‹ค. Hilt๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— Hilt ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ ๋‹ค. ๊ทธ๋ž˜์„œ ์–ด๋…ธํ…Œ์ด์…˜ ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์—ฌ์„œ ์ปดํŒŒ์ผ๋Ÿฌํ•œํ…Œ ์•Œ๋ฆฐ๋‹ค. ์ด๋•Œ ์˜์กด์„ฑ ์ œ๊ณต ๋ฐฉ์‹์œผ๋กœ @Provides์™€ @Binds๊ฐ€ ์žˆ๋‹ค. ์ด์™ธ์˜ ๊ฒƒ๋„ ์žˆ์ง€๋งŒ ์ด๋ฒˆ์—๋Š” ์ด ๋‘๊ฐœ๋งŒ ๋ณด๊ฒ ๋‹ค.

# `@Provides`

์–˜๋Š” ๋ฉ”์„œ๋“œ ๋ณธ๋ฌธ์—์„œ ๊ฐ์ฒด ์ƒ์„ฑ, ๋ฐ˜ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐฉ๋ฒ•์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ณณ์— ๋ถ™์ด๊ณ , ๊ทธ๋ž˜์„œ abstract๋กœ ์ •์˜ํ•œ ๋ชจ๋“ˆ์—๋Š” ๋ชป๋ถ™์ธ๋‹ค... ์ดˆ๊ธฐํ™”๋กœ์ง์ด ์ง์ ‘์ ์œผ๋กœ ํ•„์š”ํ•  ๊ฒฝ์šฐ์— @Provides๋กœ ์ง€์ •ํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
    @Provides
    @Singleton
    fun provideRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl(BuildConfig.MOCK_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
}

object๋กœ ์„ ์–ธ๋œ ๋ชจ๋“ˆ์•ˆ์— ์กด์žฌํ•˜๋ฉฐ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋ณต์žกํ•œ ์ดˆ๊ธฐํ™”๋กœ์ง์—๋„ ์‚ฌ์šฉ๋œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋กœ์ปฌ DB์ธ Room DB์— ์ ‘๊ทผํ•ด์•ผ๋œ๋‹ค๋ฉด Room Builder๋ฅผ ํ†ตํ•ด AppDatabase ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…๋ฐ›์•„์•ผ๋˜๋Š”๋ฐ, ์ด๋•Œ๊ฐ€ ์•Œ๋งž์€ @Provides ์‚ฌ์šฉ์ฒ˜๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

@Provides
@Singleton
fun provideDatabase(@ApplicationContext context: Context): AppDatabase {
    return Room.databaseBuilder(context, AppDatabase::class.java, "test_db")
        .addCallback(object : RoomDatabase.Callback() {
            override fun onCreate(db: SupportSQLiteDatabase) {
                Executors.newSingleThreadExecutor().execute {
                    val database = provideDatabase(context)
                    val initialData = listOf(/* ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค */)
                    database.dataDao().insertAll(initialData)
                }
            }
        })
        .build()
}

@Provides๊ฐ€ ๋ถ™์€ ๋ชจ๋“ˆ์„ ๋นผ๋จน๋‹ค ๋ณด๋ฉด ๋ณผ ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค ์ค‘ Factory๊ฐ€ ๋ถ™์€ ๊ฑธ ๋ณธ์ ์ด ์žˆ์„ ๊ฒƒ์ด๋‹ค. @Provides์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์–ด์žˆ์œผ๋ฉด Hilt๊ฐ€ ์ปดํŒŒ์ผํƒ€์ž„์— ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ๋ถ„์„ํ•ด์„œ ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋Ÿฐํƒ€์ž„ ๋•Œ ๊ฐ์ฒด ์ƒ์„ฑํ•  ์ค€๋น„๋ฅผ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

# `@Binds`

abstract ํด๋ž˜์Šค๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋ฐ”์ธ๋”ฉํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ์ถ”์ƒํ™” ๋˜์–ด์žˆ๋Š” ๊ณณ์— ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์„œ๋“œ์— ๋ณธ๋ฌธ์ด ์—†๊ณ  ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๊ตฌํ˜„์ฒด ํด๋ž˜์Šค๋ฅผ ๋ฐ›๊ฒŒ๋œ๋‹ค. ๋‹จ์ˆœ ์ธํ„ฐํŽ˜์ด์Šค - ๊ตฌํ˜„์ฒด๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ํ˜•ํƒœ๋‹ค.

interface TestRepository
class TestRepositoryImpl @Inject constructor() : TestRepository
// ์ธํ„ฐํŽ˜์ด์Šค๋ž‘ ๊ตฌํ˜„์ฒด๊ฐ€ ์ด๋ฏธ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ฒ ๋‹ค. ์ด๊ฑฐ๊นŒ์ง€ํ•˜๋ฉด ๋„ˆ๋ฌด ๊ธธ์–ด์ง„๋‹ค.

@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
    @Binds
    abstract fun bindTestRepository(testRepositoryImpl: TestRepositoryImpl): TestRepository
}

์ถ”์ƒํด๋ž˜์Šค๋กœ ์„ ์–ธ๋œ ๋ชจ๋“ˆ์ด๋‹ค. 

ํ•œ ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๊ตฌํ˜„์ฒด๊ฐ€ ์กด์žฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์ด๋Ÿด ๋•Œ๋Š” @Binds์™€ Qualifier๋ฅผ ๊ฐ™์ด ์จ์ฃผ๋ฉด๋œ๋‹ค. @Named๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค. Qualifier๋Š” ๋ฌผ๋ก  ๊ผญ Binds๊ฐ€ ์•„๋‹ˆ๋ผ๋„ ์•„๋ž˜์ฒ˜๋Ÿผ @Provides์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

@Singleton
@Provides
fun provideNotificationApi(
    @NormalRetrofit
    retrofit: Retrofit
): NotificationApi = retrofit.create()

@Singleton
@Provides
fun provideTmapApi(
    @TmapRetrofit
    retrofit: Retrofit
): TmapRouteApi = retrofit.create()

 

์ฐจ์ด์ ์„ ์ •๋ฆฌํ•ด๋ณด๋ฉด Provides๋Š” ๊ฐ์ฒด ์ƒ์„ฑ, ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ฃผ์ž…๊ณผ ๊ฐ™์€ ๊ตฌ์ฒด์ ์ธ ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๊ณ , Binds๋Š” ์ธํ„ฐํŽ˜์ด์Šค์™€ ๊ตฌํ˜„์ฒด์™€์˜ ๋ฐ”์ธ๋”ฉ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค. ๊ฐ์ฒด ์ง€ํ–ฅ์ , ์˜์กด์„ฑ ์—ญ์ „ ๊ฐœ๋…์—์„œ ๋ณด๋ฉด Binds๊ฐ€ ๋” ํด๋ฆฐํ•œ ํ˜•ํƒœ๋‹ค. ์ปดํŒŒ์ผ ํƒ€์ž„์— ๊ทธ๋ ค์ง„ Hilt ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„์— ๋“œ๋Ÿฌ๋‚˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ปดํŒŒ์ผํƒ€์ž„์— ๋ฐ”์ธ๋”ฉ ์ •๋ณด๋ฅผ ๋ฏธ๋ฆฌ ์•Œ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑด ๊ทธ๋งŒํผ ๋Ÿฐํƒ€์ž„ ๋•Œ ์„ฑ๋Šฅ์ด ์ข‹๋‹ค๋Š” ๋ง๊ณผ ๊ฐ™๋‹ค. Provides๋Š” ๋Ÿฐํƒ€์ž„ ๋•Œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธด ํ•ด๋„ ๊ฐ์ฒด ์ƒ์„ฑ๊ณผ์ •์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ข€ ๋” ์ž์œ ๋กญ๋‹ค.

 

๋Ÿฐํƒ€์ž„ ๋•Œ ์ •ํ™•ํžˆ ์–ด๋–ค์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

  • `@Provides`๋Š” Hilt๊ฐ€ ์ƒ์„ฑํ•ด์ค€ ํŒฉํ† ๋ฆฌ์˜ get()์œผ๋กœ ํ˜ธ์ถœ๋˜์–ด ์‹ค์ œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๊ฐ์ฒด ์ƒ์„ฑ๊ณผ์ •์—์„œ @Provides ๋‹ฌ์•„๋‘” ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด๋‹ค.
  • `@Binds`๋Š” ์ด๋ฏธ ์ปดํŒŒ์ผ ํƒ€์ž„์— Hilt ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„์— ๋ฐ”์ธ๋”ฉ ์ •๋ณด๊ฐ€ ๋‹ค ์˜ฌ๋ผ๊ฐ€ ์žˆ๋Š” ์ƒํƒœ๋‹ค. ๋”ฐ๋ผ์„œ ๊ทธ๋ƒฅ ๋กœ์ง ์‹คํ–‰ ์—†์ด ๋ฐ”๋กœ ๊ตฌํ˜„์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฝ‚์•„์ค€๋‹ค.

์–ผ๋งˆ์ „์— Paging3๋ฅผ ์•„ํ‚คํ…์ณ์— ๋งž๊ฒŒ ๊ฐ€๊ณตํ–ˆ์–ด์•ผํ–ˆ๋Š”๋ฐ Paging์ด Repository์™€ ๊ฐ™์€ ์ˆ˜์ค€์ž„์„ ์•Œ๊ธฐ ์ „์— DataSource์ธ์ค„ ์•Œ๊ณ  ๋ณ„ ์ด์ƒํ•œ ์ง“์„ ํ•˜๋‹ค๊ฐ€ PagingSource๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” Factory๋ฅผ ๋งŒ๋“ค์–ด์„œ @Bindsํ•ด์ค€์ ์ด์žˆ๋‹ค. ๋‚˜์ค‘์— ๊ทธ๊ฒŒ ์ž˜๋ชป๋œ ํŒจํ„ด์ž„์„ ์•Œ๊ณ  ์‹ ์†ํ•˜๊ฒŒ ๊ณ ์ณค๋‹ค.

 

 

๋„์›€์ด ๋๋‹ค๋ฉด ๋Œ“๊ธ€์ด๋‚˜ ๊ณต๊ฐ ๋ฒ„ํŠผ ํ•œ ๋ฒˆ์”ฉ ๋ˆ„๋ฅด๊ณ  ๊ฐ€์ฃผ์„ธ์š”!

 

๋ฐ˜์‘ํ˜•
COMMENT