Skip to content

๐Ÿค– AN DI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

JUNWON LEE edited this page Oct 24, 2024 · 20 revisions

Hilt์™€ Koin

์ตœ์ข… ์ •๋ฆฌ : Koin

  • ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ํฐ ์ˆ˜์ • ์—†์ด ๋น ๋ฅด๊ฒŒ ์ ์šฉ ๊ฐ€๋Šฅ
  • ๋Ÿฐํƒ€์ž„ ์˜์กด์„ฑ ์ฃผ์ž…์ด ์•ฑ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ํฌ๊ฒŒ ๋ผ์น˜์ง€ ์•Š์Œ
  • Unit Test ์— Koin ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค
  • ๋””๋ฒ„๊น…์ด ์‰ฌ์›€
  • ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ๊ฐ€ ๋ณต์žกํ•˜์ง€ ์•Š์Œ
  • Hilt๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ๋ธŒ๋žœ์น˜ ์ด๋™ํ•  ๋•Œ๋งˆ๋‹ค ์ปดํŒŒ์ผ ์˜ค๋ฅ˜ ๋ฐœ์ƒ

๋Ÿฐํƒ€์ž„์— ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•œ๋‹ค๋Š” ๋‹จ์  ๋•Œ๋ฌธ์— ์ฃผ์ž… ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด์•ผ๋œ๋‹ค๋Š” ๊ฒฐ์ •์„ ๋‚ด๋ฆผ


์˜ค๋‘ฅ

์žฅ์ )

  • โญ๏ธโญ๏ธ ๋นŒ๋“œ์‹œ๊ฐ„์— ์˜ํ–ฅ์„ ์•ˆ์ค€๋‹ค. (vs Hilt ๋Š” ๋นŒ๋“œ ํƒ€์ž„์— ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ ๋นŒ๋“œ์‹œ๊ฐ„์ด ๋Š˜์–ด๋‚จ)
  • โญ๏ธโญ๏ธ ๊ณต์‹ ๋ฌธ์„œ๊ฐ€ ์ง„์งœ ๊ฐ€๋…์„ฑ ์žˆ๊ฒŒ ์ž˜ ์ •๋ฆฌ
  • โญ๏ธโญ๏ธ Test ๋„ ์‰ฌ์›€
  • โญ๏ธ Only Kotlin ์ธ ์ ์ด ์žฅ์ ์ธ๋“ฏ
  • ์šฐ๋ฆฌ ์•ฑ์€ ๋ณต์žกํ•œ ๋ฉ€ํ‹ฐ ๋ชจ๋“ˆ ๊ตฌ์กฐ๊ฐ€ ์•„๋‹ˆ๋‹ค! (๊ทธ๋ ‡๊ธฐ์— Hilt ์˜ ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„๊ฐ€ ํ•„์š” ์—†๋‹ค)
  • Debugger ๊ฐ€ ์ž˜ ๋™์ž‘ํ•ด์„œ ์˜์กด์„ฑ ํŒŒ์•…์ด ๋กœ๊น…์ด ์‰ฌ์›€ (Hilt ๋Š” ์ง„์งœ ์•Œ์•„๋ณด๊ธฐ ํž˜๋“ค๋‹ค)

๋‹จ์ )

  • ๐Ÿšจ๐Ÿšจ๐Ÿšจ ๋Ÿฐํƒ€์ž„์— DI๊ฐ€ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ˆ˜ํ•˜๋ฉด ์•ฑ์ด ์ฃฝ๋Š”๋‹ค -> Test ์ฝ”๋“œ๊ฐ€ ์ง„์งœ ํ•„์ˆ˜ ์ผ๋“ฏ
  • ๐Ÿšจ๐Ÿšจ ๊ฐ™์€ Activity ๋งŒ๋“œ๋ ค๋ฉด ๊ฐ Activity ๋งˆ๋‹ค ScopeID ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ํ•ด์ค˜์•ผํ•จ (๊ทธ๋Ÿฌ๋‚˜ ์ด๋Ÿด ์ผ์ด ์—†์„๋“ฏ)
  • ๐Ÿšจ๐Ÿšจ Scope Component ๊ฐ€ ์ง„์งœ ์งœ์ฆ๋‚œ๋‹ค ๐Ÿ”ฅ ์ข€ ๋” ๋”ฅํ•˜๊ฒŒ ์–˜๊ธฐํ•˜์ž๋ฉด, ViewModel ์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๋”ฐ๋ฅด๋Š” ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ , Activity ์—์„œ by ViewModel() ์— ๋„˜๊ฒจ์ฃผ๊ณ  ์‹ถ์—ˆ๋Š”๋ฐ ๋ถˆ๊ฐ€๋Šฅํ•จ. ViewModel ๋‚ด๋ถ€์— ์„œ๋น„์Šค ๋กœ์ผ€์ดํ„ฐ ํŒจํ„ด์œผ๋กœ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐํ•ด์•ผํ•จ ๐Ÿ˜จ Hilt ๋Š” Android Scope ๋ฅผ ์ข€ ๋” ์นœ์ ˆํ•˜๊ฒŒ ์ง€์›ํ•ด์ฃผ๋Š”๋“ฏ~

์‹ฌ์ง€

์ฝ”์ธ

PROS

  • ์ž‘์€ ํ”„๋กœ์ ํŠธ์—์„œ ๊ฐ€์žฅ ํ”ํžˆ ์“ฐ๋Š” ๊ธฐ๋Šฅ๋“ค์€ ์ง๊ด€์ ์ด๋‹ค. ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋“ค ํŽธํ•˜๋„ค์š”.
  • ๋นŒ๋“œ ์†๋„๊ฐ€ ๋น ๋ฅด๋‹ค! ๊ต‰์žฅํžˆ ์ž‘์€ ํ”„๋กœ์ ํŠธ์—ฌ์„œ ๋นŒ๋“œ ์†๋„๊ฐ€ ๋งŽ์ด ์ฐจ์ด๋‚œ๋‹ค..
  • ๋กœ๊ทธ ํ™•์ธ์ด ํŽธํ•˜๋‹ค.

CONS

  • ๋Ÿฐํƒ€์ž„์— DI ๋˜์–ด์„œ ๋ถˆ์•ˆํ•˜๋‹ค. ๊ทธ๋ž˜์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ํ•„์š”ํ•  ๋“ฏ... ์–ด์ฉŒ๋ฉด..? ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ๊ฐ•์ œ๋˜์–ด์„œ ์žฅ์ ์ด ๋  ์ˆ˜๋„ ์žˆ๊ฒ ๋„ค์š”..?

  • ์กฐ๊ธˆ ๋ณต์žกํ•œ ๊ธฐ๋Šฅ์„ ์“ฐ๋ฉด ์˜คํžˆ๋ ค ๋” ์–ด๋ ต๋‹ค. ์•กํ‹ฐ๋น„ํ‹ฐ ์Šค์ฝ”ํ”„์—, ๋ทฐ๋ชจ๋ธ ์Šค์ฝ”ํ”„์— ์กด์žฌํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ท€์ฐฎ๋”๋ผ๊ตฌ์š”.. ์ƒ์† ์จ์•ผํ•จ.

  • ์ƒ๊ฐ๋ณด๋‹ค ํ•œ๊ตญ ์ฝ”์ธ ๊ด€๋ จ ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ์—†๋‹ค. ์ฝ”์ธ ๋ทฐ๋ชจ๋ธ์Šค์ฝ”ํ”„ ๋ผ๊ณ  ๊ฒ€์ƒ‰ํ•˜๋ฉด ์ฝ”๋ฃจํ‹ด ์Šค์ฝ”ํ”„ ๊ด€๋ จ ๊ธ€๋งŒ ๋‚˜์˜จ๋‹ค.

ํžํŠธ

PROS

  • ์•ฝ๊ฐ„ ๋ณต์žกํ•œ ์Šค์ฝ”ํ”„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์˜คํžˆ๋ ค ํŽธํ•˜๋‹ค.
  • ๋ทฐ๋ชจ๋ธ ์Šค์ฝ”ํ”„ ์ปดํฌ๋„ŒํŠธ -> @ViewModelScoped
  • ์•กํ‹ฐ๋น„ํ‹ฐ ์Šค์ฝ”ํ”„ ์ปดํฌ๋„ŒํŠธ -> '@ActivityScoped` ์กฐ๊ธˆ๋งŒ ๊ณต๋ถ€ํ•˜๋ฉด ์˜คํžˆ๋ ค ์‰ฌ์›Œ์š”

์•ˆ์ •์„ฑ

  • ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„๊ฐ€ ์ด์ƒํ•˜๊ฒŒ ์„ค์ •๋˜๋ฉด ์ปดํŒŒ์ผ(๋นŒ๋“œ) ํƒ€์ž„์— ํ„ฐ์ ธ์„œ ์•ˆ์‹ฌ์ด ๋ฉ๋‹ˆ๋‹ค.

๋ž˜ํผ๋Ÿฐ์Šค ๋งŽ์Œ

CONS

  • ๋Ÿฌ๋‹ ์ปค๋ธŒ: ์ด์ „์— ์‚ฌ์šฉํ•ด๋ดค๋Š”๋ฐ๋„ ๊ฝค ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค.

  • ๋””๋ฒ„๊น… ์–ด๋ ค์›€.. ๋‹ค๋ฅธ ๋ฌธ์ œ๋กœ ํ„ฐ์ง€๋Š”๋ฐ, ๊ฐ™์€ ๋นŒ๋“œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜์™€์„œ ์ข€ ํž˜๋“ค์—ˆ์–ด์š”.. ๊ทผ๋ฐ ์ œ๊ฐ€ ์ฒ˜์Œ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ๋ณด๋‹ค๋Š” ๋” ์ข‹์•„์ง„ ๋“ฏ?

  • ๋นŒ๋“œ ์‹œ๊ฐ„ (์ฝ”์ธ์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์Œ)

๊ทธ๋ž˜์„œ ์ €๋Š” ์ฝ”์ธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ญ๋‹ˆ๋‹ค.

๊ผฌ์ƒ

Hilt

  • ๊ณต์‹ ๋ฌธ์„œ ์ฝ”๋“œ๋žฉ์ด ์ž˜ ๋˜์–ด ์žˆ์–ด์„œ ์‰ฝ๊ฒŒ ๋ณด๊ณ  ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ์—ˆ์Œ
  • ๊ณต์‹ ๋ฌธ์„œ๋ฟ ์•„๋‹ˆ๋ผ ์ž๋ฃŒ๋„ ๋งŽ์•„์„œ ๊ตฌ๊ธ€๋ง ํ•˜๊ธฐ๋„ ํŽธํ–ˆ์Œ
  • ๋ญ”๊ฐ€ ์•ˆ๋“œ๋กœ์ด๋“œ ์นœํ™”์ ์ด๋ž€ ๋Š๋‚Œ์„ ๋ฐ›์•˜์Œ Scope ๊ด€๋ฆฌ๊ฐ€ ๋” ์‰ฌ์›Œ์„œ ๊ทธ๋Ÿฐ๊ฐ€..
  • ๋งŽ์€ ์• ๋…ธํ…Œ์ด์…˜๋“ฑ ์ ์šฉํ•ด์•ผ ํ•  ๋ฒ ์ด์Šค ์ฝ”๋“œ๊ฐ€ ๋งŽ์•„์„œ ๋‹ค์†Œ ๋ถˆํŽธํ•œ๋“ฏ
  • import๋ฅผ ๊ฐ€๋” ๋ชปํ•˜๋Š”๋“ฏ ?? ์ฃผ๊ธฐ์ ์ธ clean project, rebuild๊ฐ€ ํ•„์š”ํ•จ --> ์ด๊ฒŒ ์™œ ๋•Œ๋ฌธ์ธ๊ฐ€์š”..

Koin

  • Logger๋ฅผ ํ†ตํ•ด ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ, ์—๋Ÿฌ ๋กœ๊น…์ด ์‰ฌ์›Œ์„œ ์ข‹์•˜์Œ
  • DSL์ด ์ต์ˆ™ํ•˜์ง€ ์•Š์•„์„œ ์ ์šฉํ•  ๋• ๋ถˆํŽธํ–ˆ๋Š”๋ฐ, ์ ์šฉํ•˜๊ณ  ๋‚˜๋‹ˆ๊นŒ ์ข‹์•„๋ณด์ด๋„ค..
  • ๋นŒ๋“œ์†๋„๊ฐ€ ๋” ๋น ๋ฅธ๋“ฏ
  • ๋ž˜ํผ๋Ÿฐ์Šค๊ฐ€ ๋ณ„๋กœ ์—†์–ด์„œ ํžํŠธ๋ณด๋‹ค ์˜คํžˆ๋ ค ํ•™์Šตํ•˜๋Š”๋ฐ ์˜ค๋ž˜๊ฑธ๋ฆฐ ๋Š๋‚Œ

์˜ˆ๋‹ˆ

Hilt

  • ๊ตฌ๊ธ€์—์„œ ์ง€์›ํ•ด์ฃผ๋‹ค๋ณด๋‹ˆ Android ์— ๊ต‰์žฅํžˆ ์นœํ™”์ (?) ์ด๋ผ๋Š” ๋Š๋‚Œ์„ ๋งŽ์ด ๋ฐ›์•˜๋‹ค.
  • Android Component๋ณ„ Scope๊ฐ€ ๋ช…ํ™•ํ•˜๊ณ  ์ง๊ด€์ ์ด๋ผ์„œ ํŽธํ–ˆ.
  • ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค ์‚ฌ์šฉ ์‹œ ์ฃผ์ž… ๊ทธ๋ž˜ํ”„๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ํ‘œ์‹œํ•ด์ฃผ์–ด์„œ ๋ณด๊ธฐ ํŽธํ–ˆ์Šต๋‹ˆ๋‹ค.

Koin

  • ์ดˆ๋ฐ˜์—๋Š” DSL ์ด ์ต์ˆ™ํ•˜์ง€ ์•Š์•˜์œผ๋‚˜ ๋‹ค ๊ตฌํ˜„ํ•ด๋ณด๊ณ  ๋‚˜์„œ ๋ณด๋‹ˆ ์ฝ”๋“œ๊ฐ€ ๊ต‰์žฅํžˆ ์‹ฌํ”Œํ•˜๋‹ค! (์ฝ”๋“œ ๊ทœ๋ชจ๊ฐ€ ์ž‘์•„์„œ ๊ทธ๋Ÿฐ๊ฐ€..?)
  • AAC ViewModel ์‚ฌ์šฉ ์‹œ ์ฃผ์ž… ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ด์ฃผ์–ด์„œ ๋‚˜์˜์ง€ ์•Š๋‹ค!
  • scope ์„ค์ •์ด ์กฐ๊ธˆ ๋ฒˆ๊ฑฐ๋กญ๋‹ค .... ๐Ÿฅน

            // @Bind
            scopedOf(::StubCartRepository).bind<CartRepository>()

            // @Provide
            scoped<CartRepository> { StubCartRepository() }
  • ์ฃผ์ž… ํ…Œ์ŠคํŠธ๋Š” Robolectric/Androidx ๋กœ ViewModel ์ฃผ์ž… ํ…Œ์Šค๋งŒ ํ•˜๊ธฐ
@Test
fun `ViewModel ์ฃผ์ž… ํ…Œ์ŠคํŠธ`() {
    scenario.onActivity { activity ->
        activity.getViewModel<MainViewModel>().shouldNotBeNull()
    }
}
  • ๋ชจ๋“ˆ ์ฃผ์ž… ์ „๋žต
// :app
val appModule = module {
    includes(dataModule)
    
    viewModelOf(::CartViewModel)
    viewModelOf(::CartViewModel)
    viewModelOf(::CartViewModel)
    viewModelOf(::CartViewModel)
}
// :data
val dataModule = module {
    includes(localModule, remoteModule)
    singleOf(::RemoteDataSource)
    singleOf(::LocalDataSource)
    singleOf(::DefaultCartRepository).binds(CartRepository::class)
    singleOf(::DefaultProductRepository).binds(CartRepository::class)
}

// :local
val localModule = module {..}
// :remote
val remoteModule = module {..}

// :testing - test ํ•  ๋•Œ ์‚ฌ์šฉ 
val testModule = module { }

ViewModel ์— ํŒŒ๋ผ๋ฏธํ„ฐ ๋„˜๊ธฐ๊ณ  ์‹ถ์„ ๋•Œ

val appModule = module {
    viewModel<CartViewModel> { (id: Int) -> CartViewModel(id, get()) }
}

class MyActivity : AppCompatActivity() {
    val viewModel by viewModel<CartViewModel> {
        parametersOf(1)
    }
}
Clone this wiki locally