[Android] Dependency Injection Part 1. Overview
μ΄ κΈμ Android Developer κ°μ΄λ λ΄μ©μ ν λλ‘ μμ±λμμ΅λλ€. μμ μ½λλ Kotlinλ§ κ°μ ΈμμΌλ©°, Java μ½λλ μλ¬Έμμ νμΈν μ μμ΅λλ€.
μμ‘΄μ± μ£Όμ (Dependency injection, DI)μ νλ‘κ·Έλλ°μμ λ리 μ¬μ©λκ³ , Android κ°λ°μ μ ν©ν κΈ°μ μ λλ€. DIμ μμΉμ λ°λ₯΄λ©΄ μ’μ μ± μν€ν μ²μ κΈ°λ°μ κ°μΆ μ μμ΅λλ€.
DIλ₯Ό ν΅ν΄ μ»μ μ μλ μ₯μ
- μ½λ μ¬μ¬μ© κ°λ₯
- 리ν©ν λ§ μ©μ΄
- ν μ€νΈ μ©μ΄
DIμ κΈ°λ³Έ κ°λ
Androidμμμ DIλ₯Ό μ΄ν΄λ³΄κΈ° μ μ, μ΄ ννΈμμλ DIμ λμ λ°©μμ λν μ’ λ κΈ°λ³Έμ μΈ κ°λ μ μ€λͺ ν©λλ€.
μμ‘΄μ± μ£Όμ μ΄λ?
ν ν΄λμ€μμ λ€λ₯Έ ν΄λμ€ μ°Έμ‘°λ μμ£Ό νμν©λλ€. μλ₯Ό λ€μ΄, Car
ν΄λμ€λ Engine
ν΄λμ€λ₯Ό μ°Έμ‘°ν΄μΌ ν©λλ€. μ΄λ κ² νμν ν΄λμ€λ₯Ό λνλμλΌκ³ ν©λλ€. κ·Έλ¦¬κ³ μ΄ μμμμ Car
ν΄λμ€λ μ€νμ Engine
μΈμ€ν΄μ€λ₯Ό κ°λ κ²μ μμ‘΄ν©λλ€.
ν΄λμ€μ νμν κ°μ²΄λ₯Ό μ»λ λ°©λ²μ 3κ°μ§κ° μμ΅λλ€:
- ν΄λμ€κ° νμν λνλμλ₯Ό μμ±νλ€.
Car
ν΄λμ€κ°Engine
μΈμ€ν΄μ€λ₯Ό μ§μ μμ±νκ³ μ΄κΈ°ν - λ€λ₯Έ μ΄λκ°μμ κ°μ Έμ¨λ€.
getContext()
λgetSystemService()
κ°μ λͺλͺ Android APIκ° μ΄λ κ² λμν¨ - νλΌλ―Έν°λ₯Ό ν΅ν΄ λ°λλ€. ν΄λμ€κ° μμ±λ λ λλ κ° λνλμλ§λ€ νμν ν¨μμ νλΌλ―Έν°λ₯Ό ν΅ν΄ μ λ¬λ°μ μ μλ€.
Car
μμ±μμ νλΌλ―Έν°λ‘Engine
μ μ λ¬λ°λλ€.
μΈ λ²μ§Έ λ°©λ²μ΄ λ°λ‘ DI μ λλ€! μ΄ λ°©λ²μ ν΅ν΄ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό ν¬ν¨μν€μ§ μκ³ λ μμ‘΄μ±μ μ»κ±°λ μ 곡ν μ μμ΅λλ€.
μλλ μμ‘΄μ± μ£Όμ
μμ΄ Car
ν΄λμ€κ° Engine
μΈμ€ν΄μ€λ₯Ό μ§μ μμ±νλ μμ μ½λμ
λλ€.
class Car {
private val engine = Engine()
fun start() {
engine.start()
}
}
fun main(args: Array) {
val car = Car()
car.start()
}
μ΄ μ½λλ μλμ μ΄μ λ‘ λ¬Έμ κ° λ μ μλ μ½λμ λλ€.
Car
μEngine
μ΄ λ¨λ¨ν μ°κ²°λμ΄ μμ΅λλ€ -Car
μΈμ€ν΄μ€κ°Engine
μ΄λΌλ ν κ°μ§ νμ μ μ¬μ©νμ¬, μλΈ ν΄λμ€λ λ체ν ꡬν체λ₯Ό μ½κ² μ¬μ©ν μ μμ΅λλ€.Car
μ체μμ μ¬μ©νEngine
μ μ§μ μμ±νλ―λ‘,Gas
λElectric
μμ§ νμ μ΄ μΆκ°λλ©΄Car
λ₯Ό μ¬μ¬μ©ν μ μκ³ λ κ°μ§Car
νμ μ μλ‘ λ§λ€μ΄μΌ ν©λλ€.Engine
μ λν λ¨λ¨ν μμ‘΄μ±μ ν μ€νΈλ λμ± μ΄λ ΅κ² λ§λλλ€.Car
κ° μ€μ Engine
μΈμ€ν΄μ€λ§ μ¬μ©νκΈ° λλ¬Έμ μ¬λ¬ ν μ€νΈ μΌμ΄μ€λ₯Ό μνEngine
μ Mock κ°μ²΄ μ¬μ©μ΄ μ΄λ ΅μ΅λλ€.
μμ‘΄μ± μ£Όμ
μ μ¬μ©νλ©΄ μ½λκ° μ΄λ»κ² λ³κ²½λ κΉμ? Car
μΈμ€ν΄μ€λ§λ€ μ΄κΈ°ν μμ μ Engine
μ μμ±νμ§ μκ³ , Car
μμ±μμ νλΌλ―Έν°λ₯Ό ν΅ν΄ μ λ¬λ°μ΅λλ€.
class Car(private val engine: Engine) {
fun start() {
engine.start()
}
}
fun main(args: Array) {
val engine = Engine()
val car = Car(engine)
car.start()
}
main
ν¨μμμ Car
λ₯Ό μ¬μ©ν©λλ€. Car
κ° Engine
μ μμ‘΄νκΈ° λλ¬Έμ Engine
μΈμ€ν΄μ€λ₯Ό λ¨Όμ μμ±νμ¬ Car
μΈμ€ν΄μ€ μμ± μ μ¬μ©ν©λλ€. DI κΈ°λ°μ μ κ·Όλ²μ μλμ μ₯μ μ κ°μ§λλ€:
Car
μ¬μ¬μ© κ°λ₯ -Engine
μ λ€λ₯Έ ꡬν체λ₯ΌCar
μ μ λ¬ν μ μμ΅λλ€. μλ₯Ό λ€μ΄,ElectricEngine
μ΄λΌλEngine
μ μλ‘μ΄ μλΈ ν΄λμ€λ₯Ό μ μνμ λ, DIλ₯Ό μ¬μ©νλ€λ©΄Car
ν΄λμ€ λ³κ²½μμ΄ElectricEngine
λ§Car
μ μ λ¬νλ©΄ λ©λλ€.Car
ν μ€νΈ μ©μ΄ - μ¬λ¬ μλλ¦¬μ€ ν μ€νΈλ₯Ό μν κ°μ²΄λ₯Ό μ λ¬ν μ μμ΅λλ€. μλ₯Ό λ€μ΄,FakeEngine
μ΄λΌλEngine
μ ν μ€νΈμ© κ°μ²΄λ₯Ό λ§λ€μ΄ κ° ν μ€νΈ μΌμ΄μ€μ λ§κ² μ€μ ν μ μμ΅λλ€.
Androidμμ μμ‘΄μ± μ£Όμ λ°©λ²μ ν¬κ² 2κ°μ§κ° μμ΅λλ€:
- μμ±μ μ£Όμ : μ μ½λμμ μ€λͺ ν λ°©μμΌλ‘, λνλμλ₯Ό μμ±μμ μ λ¬ν©λλ€.
- νλ μ£Όμ (λλ Setter μ£Όμ ): Activityλ Fragment κ°μ νΉμ Android Framework ν΄λμ€λ€μ μμ€ν μ μν΄ μμ±λμ΄, μμ±μλ₯Ό ν΅ν μμ‘΄μ± μ£Όμ μ΄ λΆκ°λ₯ν©λλ€. νλ μ£Όμ μ μ¬μ©νλ©΄ ν΄λμ€ μμ± μ΄νμ μμ‘΄ κ΄κ³λ₯Ό λνλΌ μ μμ΅λλ€. μλ μ½λκ° νλ μ£Όμ μμμ λλ€.
class Car {
lateinit var engine: Engine
fun start() {
engine.start()
}
}
fun main(args: Array) {
val car = Car()
car.engine = Engine()
car.start()
}
DI μλν
μμμ λ³Έ DI μμ μ½λλ λͺ¨λ λ€λ₯Έ ν΄λμ€μ λν μμ‘΄ κ΄κ³λ₯Ό μ§μ μμ±, μ λ¬, κ΄λ¦¬νμ΅λλ€. Car
ν΄λμ€κ° μ§κΈμ νλμ λνλμλ§ κ°μ§λ§ λνλμμ ν΄λμ€κ° λμ΄λ¨μ λ°λΌ 볡μ‘λ λν μ¦κ°νκ² λ©λλ€.
κ·λͺ¨κ° ν° μ±μ κ²½μ°, λͺ¨λ λνλμλ₯Ό μ»μ΄μ μλ§κ² μ°κ²°νκΈ° μν λ§μ μμ 보μΌλ¬νλ μ΄νΈ μ½λκ° μκΈ°κ² λ©λλ€. Multi-layered architectureμ κ²½μ°, μμ κ³μΈ΅μ μ νμν κ°μ²΄λ₯Ό μμ±νκΈ° μν΄ νμμ λͺ¨λ λνλμλ₯Ό μ λ¬ν΄μΌ ν©λλ€.
κ·Έλμ λνλμλ₯Ό μμ±νκ³ μ λ¬νλ κ³Όμ μ μλννκΈ° μν λΌμ΄λΈλ¬λ¦¬λ€μ΄ μμ΅λλ€. Java, Kotlin κ·Έλ¦¬κ³ Androidμ μμ‘΄μ± μ£Όμ λΌμ΄λΈλ¬λ¦¬λ‘λ Googleμ Daggerκ° λ§μ΄ μ°μ΄κ³ μμ΅λλ€.
DIμ λμ - Service Locator
DI λμ Service Locator λμμΈ ν¨ν΄μ μ¬μ©ν μλ μμ΅λλ€. Service Locator λν ν΄λμ€κ° λ¨λ¨ν μ°κ²°κ³ 리λ₯Ό λΆλ¦¬νλ λ° λμμ μ€λλ€. λ³΄ν΅ ServiceLocatorλΌλ ν΄λμ€λ₯Ό λ§λ€κ³ , λνλμλ₯Ό μμ±ν΄μ μ μ₯ν΄λλ€κ° νμν κ²½μ° μ λ¬νλ λ‘μ§μ λ΄μ΅λλ€.
object ServiceLocator {
fun getEngine(): Engine = Engine()
}
class Car {
private val engine = ServiceLocator.getEngine()
fun start() {
engine.start()
}
}
fun main(args: Array) {
val car = Car()
car.start()
}
Service Locator ν¨ν΄μ ν΄λμ€κ° μ£ΌλκΆμ κ°μ§κ³ μ£Όμ λμ΄μΌ ν ν΄λμ€λ₯Ό μμ²νμ§λ§, DIλ μ±μ΄ μ£ΌλκΆμ κ°μ§κ³ νμν ν΄λμ€λ₯Ό μ¬μ μ μ£Όμ ν©λλ€.
μ±μ κ·λͺ¨μ λ°λΌ μλ§μ λ°©λ² μ ννκΈ°
λ¨Όμ νλ‘μ νΈμ κ·λͺ¨λ μ΄λ»κ² νμ ν κΉμ? μ¬κΈ°μλ μ±μ μ¬μ΄μ¦κ° ν°κ° μμκ°λ₯Ό νλ©΄ κ°μλ‘ μ ν μ μμ΅λλ€. λ¬Όλ‘ νλ©΄μ κ°μλ μ±μ ν¬κΈ°λ₯Ό κ²°μ νλ λ§μ μμ μ€ νλμΌ λΏμ λλ€.
νλ‘μ νΈ ν¬κΈ° | μλ€ | μ€κ° | ν¬λ€ |
---|---|---|---|
νλ©΄ κ°μ | 1-3 | 4-7 | 8+ |
- μ§μ μμ‘΄μ± μ£Όμ : νμ₯μ±μ΄ μ’μ§ μμΌλ―λ‘ λΉκ΅μ μμ μ±μλ§ μ ν©ν©λλ€. νλ‘μ νΈ ν¬κΈ°κ° 컀μ§μλ‘ λ³΄μΌλ¬νλ μ΄νΈ μ½λλ μ¦κ°ν©λλ€.
- Service Locator: 보μΌλ¬νλ μ΄νΈ μ½λκ° λΉκ΅μ μ μ§λ§ νμ₯μ±μ΄ μ’μ§ μμ΅λλ€. μ±κΈν€ κ°μ²΄μ μμ‘΄νλ―λ‘, ν μ€νΈ λν μ΄λ ΅μ΅λλ€.
- Dagger: νμ₯μ±μ΄ μ’κ³ , 볡μ‘ν μ±μλ μ ν©ν©λλ€.
νλ‘μ νΈ ν¬κΈ° | μλ€ | μ€κ° | ν¬λ€ |
---|---|---|---|
μΆμ²νλ λ°©λ² | μλ DI Service Locator Dagger |
Dagger | Dagger |
νμ¬λ μμ μ±μΈλ° κ·λͺ¨κ° μ»€μ§ κ²μΌλ‘ μμλλ€λ©΄, λ λ§μ μ½λκ° λ³κ²½λκΈ° μ μ 미리 Daggerλ‘ μ ννλ κ²μ΄ μ’μ΅λλ€.
λΌμ΄λΈλ¬λ¦¬ κ·λͺ¨μ λ°λΌ μλ§μ λ°©λ² μ ννκΈ°
SDKλ λΌμ΄λΈλ¬λ¦¬λ₯Ό κ°λ°νκ³ μλ€λ©΄ μλ DI λλ κ·λͺ¨μ λ°λΌ Daggerλ₯Ό μ¬μ©νμΈμ. λ€λ§ μμ‘΄μ± μ£Όμ μ μν΄ 3rd party λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νλ©΄ λΌμ΄λΈλ¬λ¦¬μ ν¬κΈ° λν μ¦κ°ν μ μλ€λ μ μ μ£Όμκ° νμν©λλ€.
κ²°λ‘
DIλ₯Ό μ¬μ©νλ©΄ μλμ κ°μ μ₯μ μ΄ μμ΅λλ€.
- μ½λ μ¬μ¬μ© κ°λ₯ λ° μμ‘΄μ± λΆλ¦¬: ꡬν체λ₯Ό λ³κ²½νκΈ° μ¬μμ§λλ€. ν΄λμ€κ° λμ΄μ λνλμλ€μ΄ μ΄λ»κ² μμ±λλμ§ μ κ²½μ°μ§ μμλ λκ³ , μ μ΄μ μμ λλΆμ μ½λμ μ¬μ¬μ©μ±μ΄ μ¦κ°ν©λλ€.
- 리ν©ν λ§ μ©μ΄: μμ‘΄ κ΄κ³κ° APIμ λΆλͺ ν λλ¬λκΈ° λλ¬Έμ, ꡬν체μ μ¨κ²¨μ§ λ΄μ©μ λ³΄μ§ μκ³ κ°μ²΄ μμ± μμ λλ μ»΄νμΌ μμ μλ§ νμΈνλ©΄ λ©λλ€.
- ν μ€ν μ©μ΄: ν΄λμ€κ° μμ μ μμ‘΄ κ΄κ³λ₯Ό κ΄λ¦¬νμ§ μκΈ° λλ¬Έμ, ν μ€νΈ μ κ° ν μ€νΈ μΌμ΄μ€μ λ§λ ꡬν체λ₯Ό μ λ¬νκΈ°λ§ νλ©΄ λ©λλ€.
DIμ μ₯μ μ μλ²½νκ² μ΄ν΄νλ €λ©΄ μ±μ μ§μ μ¨λ³΄λ κ²μ΄ μ’μ΅λλ€. λ€μ ννΈμμ μ§μ μμ‘΄μ±μ μ£Όμ νλ λ°©λ²μΌλ‘ λμμ€κ² μ΅λλ€!
Comments