DI

DI (Dependency injection / μ˜μ‘΄μ„± μ£Όμž…) μ΄λž€?

μš°μ„  μ•ˆλ“œλ‘œμ΄λ“œ DI λ₯Ό μ μš©ν•˜λ©΄ ν›Œλ₯­ν•œ μ•± μ•„ν‚€ν…μ²˜λ₯Ό μœ„ν•œ ν† λŒ€λ₯Ό λ§ˆλ ¨ν•  수 μžˆλ‹€. μ•ˆλ“œλ‘œμ΄λ“œ κ³΅μ‹λ¬Έμ„œμ— λ”°λ₯΄λ©΄ DI λ₯Ό μ μš©ν•˜λ©΄ μ•„λž˜μ™€ 같은 이점이 λˆ„λ¦΄ 수 μžˆλ‹€.

  • μ½”λ“œ μž¬μ‚¬μš© κ°€λŠ₯

  • λ¦¬νŒ©ν† λ§ νŽΈμ˜μ„±

  • ν…ŒμŠ€νŠΈ νŽΈμ˜μ„±

이 글을 μž‘μ„±ν•˜λ©΄μ„œ λ‚˜ 슀슀둜 μœ„μ— 이점듀을 잘 λˆ„λ¦¬κ³  μžˆμ—ˆλŠ”μ§€ λ˜λŒμ•„ λ³Ό 것이닀.

μš°μ„  ν΄λž˜μŠ€μ—λŠ” λ‹€λ₯Έ 클래슀 μ°Έμ‘°κ°€ ν•„μš”ν•˜λ‹€. 예λ₯Ό λ“€μ–΄ Car ν΄λž˜μŠ€λŠ” Engine 클래슀 μ°Έμ‘°κ°€ ν•„μš”ν•  수 μžˆλ‹€. 이처럼 ν•„μš”ν•œ 클래슀λ₯Ό 쒅속 ν•­λͺ©(dependencies) 이라고 ν•˜λ©°, Car ν΄λž˜μŠ€κ°€ μ‹€ν–‰λ˜κΈ° μœ„ν•΄μ„œλŠ” Engine 클래슀의 μΈμŠ€ν„΄μŠ€κ°€ ν•„μš”ν•˜λ‹€.

ν΄λž˜μŠ€κ°€ ν•„μš”ν•œ 객체λ₯Ό μ–»λŠ” 방법은 3가지가 μžˆλ‹€.

  • ν΄λž˜μŠ€κ°€ ν•„μš”ν•œ 쒅속 ν•­λͺ© (Engine Class) 을 κ΅¬μ„±ν•œλ‹€. μœ„ μ˜ˆμ—μ„œλŠ” Car ν΄λž˜μŠ€λŠ” 자체 Engine μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ—¬ μ΄ˆκΈ°ν™”ν•œλ‹€.

  • λ‹€λ₯Έ κ³³μ—μ„œ 객체λ₯Ό κ°€μ Έμ˜¨λ‹€. Context getter & getSystemService() 와 같은 일뢀 Android APIλŠ” μ—¬λŸ¬ν•œ λ°©μ‹μœΌλ‘œ μž‘λ™ν•œλ‹€.

  • 객체λ₯Ό λ§€κ²Œλ³€μˆ˜λ‘œ μ œκ³΅λ°›λŠ”λ‹€. 앱은 ν΄λž˜μŠ€κ°€ ꡬ성될 λ•Œ μ΄λŸ¬ν•œ 쒅속 ν•­λͺ©μ„ μ œκ³΅ν•˜κ±°λ‚˜ 각 쒅속 ν•­λͺ©μ΄ ν•„μš”ν•œ ν•¨μˆ˜μ— 전달할 수 μžˆλ‹€. μœ„ μ˜ˆμ—μ„œλŠ” Car μƒμ„±μžλŠ” Engine 을 λ§€κ°œλ³€μˆ˜λ‘œ λ°›λŠ”λ‹€.

μ—¬κΈ°μ„œ λ§ν•˜λŠ” 3번째 방법이 λ°”λ‘œ DI / μ˜μ‘΄μ„±μ£Όμž…μ΄λ‹€ πŸ”₯ 이 방법을 μ‚¬μš©ν•˜λ©΄ 클래슀 μΈμŠ€ν„΄μŠ€κ°€ 자체적으둜 쒅속 ν•­λͺ©μ„ μ–»λŠ” λŒ€μ‹  클래슀의 쒅속 ν•­λͺ©μ„ λ°›μ•„μ„œ μ œκ³΅ν•œλ‹€.

μš°μ„  1번과 같은 λ°©λ²•μœΌλ‘œ μΈμŠ€ν„΄μŠ€ν™” ν•˜λŠ”κ±°λŠ” μ•„λž˜ μ½”λ“œμ™€ κ°™λ‹€.

class Car {

    private val engine = Engine()

    fun start() {
        engine.start()
    }
}

class Engine {
    fun start() {
        // write code...
    }
}

이 μ˜ˆλŠ” Car ν΄λž˜μŠ€κ°€ 자체 Engine 을 객체생성 ν›„ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— DI κ°€ μ•„λ‹ˆλ‹€. λ˜ν•œ μ•„λž˜μ™€ 같은 λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλ‹€.

  • Car 와 Engine 은 λ°€μ ‘ν•˜κ²Œ μ—°κ²°λ˜μ–΄μžˆλ‹€. Car μΈμŠ€ν„΄μŠ€λŠ” ν•œ 가지 μœ ν˜•μ˜ Engine 을 μ‚¬μš©ν•˜λ―€λ‘œ μ„œλΈŒν΄λž˜μŠ€ λ˜λŠ” λŒ€μ²΄ κ΅¬ν˜„μ„ μ‰½κ²Œ μ‚¬μš©ν•  수 μ—†λ‹€. Car κ°€ 자체 Engine 을 κ΅¬μ„±ν–ˆλ‹€λ©΄ Gas / Electric μœ ν˜•μ˜ 엔진에 λ™μΌν•œ Car λ₯Ό μž¬μ‚¬μš©ν•˜λŠ” λŒ€μ‹  두 가지 μœ ν˜•μ˜ Car을 생성해야 ν•œλ‹€.

  • μœ„ μ˜ˆμ œμ™€ 같이 μ˜μ‘΄μ„±μ΄ 높은 경우 λ‹€μ–‘ν•œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ—μ„œ ν…ŒμŠ€νŠΈλ₯Ό λ”μš± μ–΄λ ΅κ²Œ λ§Œλ“ λ‹€.

DI μ •μ˜

μ˜μ‘΄μ„± μ£Όμž…μ€ ν•˜λ‚˜μ˜ 객체가 λ‹€λ₯Έ 객체의 μ˜μ‘΄μ„±μ„ μ œκ³΅ν•˜λŠ” κΈ°μˆ μ΄λ‹€.

μ˜μ‘΄μ„± μ£Όμž…μ€ κ΄‘λ²”μœ„ν•œ μ—­μ œμ–΄ ν…Œν¬λ‹‰μ˜ ν•œ ν˜•νƒœμ΄λ‹€. μ–΄λ–€ μ„œλΉ„μŠ€λ₯Ό ν˜ΈμΆœν• λ €λŠ” ν΄λΌμ΄μ–ΈνŠΈλŠ” κ·Έ μ„œλΉ„μŠ€κ°€ μ–΄λ–»κ²Œ κ΅¬μ„±λ˜μ—ˆλŠ”μ§€ μ•Œμ§€ λͺ»ν•΄μ•Ό ν•œλ‹€. ν΄λΌμ΄μ–ΈνŠΈλŠ” λŒ€μ‹  μ„œλΉ„μŠ€ μ œκ³΅μ— λŒ€ν•œ μ±…μž„μ„ μ™ΈλΆ€ μ½”λ“œ(μ£Όμž…μž)둜 μœ„μž„ν•œλ‹€. ν΄λΌμ΄μ–ΈνŠΈλŠ” μ£Όμž…μž μ½”λ“œλ₯Ό ν˜ΈμΆœν•  수 μ—†λ‹€. κ·Έ λ‹€μŒ μ£Όμž…μžλŠ” 이미 μ‘΄μž¬ν•˜κ±°λ‚˜ μ£Όμž…μžμ— μ˜ν•΄ κ΅¬μ„±λ˜μ—ˆμ„ μ„œλΉ„μŠ€λ₯Ό 클라인트둜 μ£Όμž…ν•œλ‹€. 그리고 λ‚˜μ„œ ν΄λΌμ΄μ–ΈνŠΈλŠ” μ„œλΉ„μŠ€λ₯Ό μ‚¬μš©ν•œλ‹€. μ˜μ‘΄μ„± μ£Όμž…μ€ λ„€ 가지 역할을 λ‹΄λ‹Ήν•˜λŠ” 객체 및 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ „μ œλ‘œ ν•œλ‹€.

  • μ‚¬μš©λ  μ„œλΉ„μŠ€ 객체 - μ „κΈ°, κ°€μŠ€, ν•˜μ΄λΈŒλ¦¬λ“œ λ˜λŠ” λ””μ € μžλ™μ°¨

  • μ‚¬μš©ν•˜λŠ” μ„œλΉ„μŠ€μ— μ˜μ‘΄ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈ 객체 - 엔진에 상관 없이 λ™μΌν•˜κ²Œ μ°¨λ₯Ό μ‚¬μš©ν•˜λŠ” μš΄μ „μž

  • ν΄λΌμ΄μ–ΈνŠΈμ˜ μ„œλΉ„μŠ€ μ‚¬μš© 방법을 μ •μ˜ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€ - μš΄μ „μžκ°€ 기어와 같은 μ—”μ§„μ˜ μ„ΈλΆ€ 사항을 이해할 ν•„μš”κ°€ 없도둝 보μž₯ν•΄μ£ΌλŠ” μžλ™λ³€μ†κΈ°

  • μ„œλΉ„μŠ€λ₯Ό μƒμ„±ν•˜κ³  ν΄λΌμ΄μ–ΈνŠΈλ‘œ μ£Όμž…ν•˜λŠ” μ±…μž„μ„ κ°–λŠ” μ£Όμž…μž - μ•„μ΄μ—κ²Œ μ–΄λ–€ μ°¨λ₯Ό 사쀄지 κ²°μ •ν•˜κ³  ꡬ맀해쀀 λΆ€

DI 접근방식

1. μƒμ„±μž μ‚½μž…

class Car(private val engine: Engine) {

    fun start() {
        engine.start()
    }
}

fun main(args: Array) {
    val engine = Engine()
    val car = Car(engine)
    car.start()
}  

2. ν•„λ“œ μ‚½μž…

class Car() {
    lateinit var engine: Engine

    fun start() {
        engine.start()
    }
}

fun main() {
    val car = Car()
    car.engine = Engine()
    car.start()

μœ„ μ˜ˆμ œμ™€ 같은 DI 기반 μ ‘κ·Όλ°©λ²•μ˜ 이점은 λ‹€μŒκ³Ό κ°™λ‹€.

  • Car 의 μž¬μ‚¬μš©κ°€λŠ₯. Engine 의 λ‹€μ–‘ν•œ κ΅¬ν˜„μ„ Car 에 전달할 수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄ GasEngine 을 μ‚¬μš©ν•˜λŠ” 경우, Engine 클래슀λ₯Ό 상속받아 μ„œλΈŒν΄λž˜μŠ€λ₯Ό μ •μ˜ν•  수 μžˆλ‹€. GasEngine 을 μΈμŠ€ν„΄μŠ€λ‘œ μ „λ‹¬ν•˜λ©΄ Car ν΄λž˜μŠ€λŠ” μ•„λ¬΄λŸ° 변경없이 μ‚¬μš©ν•  수 μžˆλ‹€.

  • ν…ŒμŠ€νŠΈ 더블을 μ „λ‹¬ν•˜μ—¬ λ‹€μ–‘ν•œ μ‹œλ‚˜λ¦¬μ˜€ ν…ŒμŠ€νŠΈλ₯Ό ν•  수 μžˆλ‹€.

이전 μ˜ˆμ—μ„œλŠ” 라이브러리λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  직접 생성 및 관리λ₯Ό ν•˜μ˜€λ‹€. 이λ₯Ό 직접 쒅속 | μˆ˜λ™ ν•­λͺ© μ‚½μž… 이라고 ν•œλ‹€. 쒅속 ν•­λͺ©μ΄ λ§Žμ•„ 질 수둝 쒅속 ν•­λͺ©μ„ μ‚½μž…ν•˜λŠ” μž‘μ—…μ΄ 지루해 질 수 μžˆλ‹€. 뿐만 μ•„λ‹ˆλΌ λ‹€μŒκ³Ό 같은 λ¬Έμ œμ λ“€μ΄ μžˆλ‹€.

  • λŒ€κ·œλͺ¨ μ•±μ˜ 경우 λͺ¨λ“  쒅속 ν•­λͺ©μ„ 가져와 μ˜¬λ°”λ₯΄κ²Œ μ—°κ²°ν•˜λ €λ©΄ λŒ€λŸ‰μ˜ μƒμš©κ΅¬ μ½”λ“œκ°€ ν•„μš”ν•˜λ‹€. 예둜, μžλ™μ°¨λ₯Ό λ§Œλ“€λ €λ©΄ 엔진,변속기 기타 λΆ€ν’ˆ μ—”μ§„μ—λŠ” 싀린더, 점화 ν”Œλ‘œκ·Έ 등이 ν•„μš”λ‘œ ν•˜λ‹€.

  • 쒅속 ν•­λͺ©μ„ μ „λ‹¬ν•˜κΈ° 전에 ꡬ성할 수 없을 λ•ŒλŠ” λ©”λͺ¨λ¦¬μ—μ„œ 쒅속 ν•­λͺ©μ˜ 전체 기간을 κ΄€λ¦¬ν•˜λŠ” 맞좀 μ»¨ν…Œμ΄λ„ˆλ₯Ό μž‘μ„±ν•˜κ³  μœ μ§€ν•΄μ•Ό ν•œλ‹€.

μ΄λŸ¬ν•œ λ¬Έμ œμ λ“€μ„ ν•΄κ²°ν•˜λŠ” λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ΄ μ‘΄μž¬ν•˜λ©°, μ΄λŠ” 두 가지 μΉ΄ν…Œκ³ λ¦¬λ‘œ λΆ„λ₯˜λœλ‹€.

  • λŸ°νƒ€μž„ μ‹œ 쒅속 ν•­λͺ©μ„ μ—°κ²°ν•˜λŠ” λ¦¬ν”Œλ ‰μ…˜ 기반 μ†”λ£¨μ…˜ - Koin...

  • 컴파일 νƒ€μž„μ— 쒅속 ν•­λͺ©μ„ μ—°κ²°ν•˜λŠ” μ½”λ“œλ₯Ό μƒμ„±ν•˜λŠ” 정적 μ†”λ£¨μ…˜ - Dagger / Hilt...

Last updated