Dependency Injection(DI), 의존성 주입에 대해 조금 쉽게? 접근해보기

tom·2022년 2월 15일
0
post-thumbnail

Dependency Injection 말그대로 "의존성 주입"입니다.

객체지향 프로그래밍을 공부하다보면 한번쯤은 나오고, 들어봤을 용어입니다.

그래서 오늘은 이 DI(Dependency Injection), 의존성 주입이 어떤 것인지 알아보려고 합니다.

DI의 장점

DI로 인하여 아래와 같은 이점들을 가질 수 있습니다.

  • 코드의 재사용성을 높여준다.
  • 테스트의 편의성을 높여준다.
  • 객체간의 의존성을 줄이거나 없앨 수 있다.
  • 객체간의 결합도를 낮출 수 있다.
  • 위와 같은 장점들로 인하여 리팩터링의 편의성도 함께 높아진다.
  • ...

의존성 (Dependency)

먼저 의존성에 대해서 알아보도록 하겠습니다.

흔히 객체지향 프로그래밍으로 개발을 진행하면, 하나의 클래스는 다른 클래스의 참조가 필요하게 됩니다.

말로는 잘 모르겠습니다. 예시를 저희한테 꼭 필요한 Computer 객체를 통해 들어보도록 하겠습니다.

Computer 는 동작을 시작하거나 지속하기 위해서 Power 를 필요로 합니다. Power 가 없다면 Computer 는 동작할 수 없기 때문이죠. (Developer 도 Computer 가 없다면 동작할 수 없듯이말이죠...)

class Computer {
    private val power = Power()

    fun start() {
        power.on()
    }
}

class Power {
    fun on() {
        println("Power ON!")
    }
}

위의 코드처럼 start() 메소드를 동작시키기 위해 Computer 클래스 내에 변수로 Power 클래스의 인스턴스를 생성함으로써 Computer 클래스는 Power 클래스에 의존하게 되었습니다.

한 마디로 위에서 설명한 예시처럼, Computerstart 하기 위해서는 꼭 Power 가 필요하기 때문에 ComputerPower 에 의존한다는 것입니다.

의존성을 설명하였으니, 이제 주입 (Injection) 에 대해 알아야 합니다.

주입 (Injection)

주입이란, 위의 Computer 클래스처럼 클래스 내에서 다른 클래스의 인스턴스를 생성하여 사용하는 것이 아니라 클래스 외부에서 인스턴스를 생성하여 넘겨주는 것을 의미합니다.

또 말로만 해서는 잘 모르겠습니다. 위의 Computer 클래스 코드를 조금 고쳐보겠습니다.

class Computer(private val power: Power) {
    fun start() {
        power.on()
    }
}

class Power {
    fun on() {
        println("Power ON!")
    }
}

수정된 코드의 Computer 클래스를 보면, 생성자의 매개변수로 Power 인스턴스를 받고 있습니다.

어딘가(외부) 에서 Computer 인스턴스를 생성하기 위해서는 Power 의 인스턴스도 (외부에서) 함께 생성하여 Computer 의 생성자로 해당 인스턴스를 주입해주어야 한다는 의미입니다.

이렇게 주입까지 알아보았습니다.

더하기

그렇다면 위에서 다룬 의존성과 주입을 더하면 의존성 주입, 즉 DI가 완성 될 것 같습니다.

다음의 main() 함수를 보도록 하겠습니다.

fun main() {
    val power = Power()
    val computer = Computer(power)

    computer.start()
}

Computer 클래스의 생성을 위해서 Power 클래스의 인스턴스를 먼저 생성한 후, Computer 클래스의 생성자에 넣어주는 것을 확인할 수 있습니다.

위에서 설명하였듯이, ComputerPower 에 의존하는데 Computer 의 생성자에 Power 인스턴스를 주입하고 있습니다.

이렇게 되면 의존성+주입이 완성되었습니다.

그러면 의존성주입이 주는 이점들을 한번 다시 확인해보겠습니다.

  1. 코드의 재사용성을 높여준다.
    우리는 이제 Computer 를 바꿀 때, 같은 Power 를 계속 사용할 수 있게 된 것입니다.

  2. 테스트의 편의성을 높여준다.
    우리는 이제 Computer 가 정상적으로 동작하는 지 확인할 때 여러가지 Power 들로 테스트할 수 있게 되었습니다.

  3. 객체간의 의존성을 줄이거나 없앨 수 있다.
    주입을 진행하지 않았다면 Computer 클래스의 생성과 함께 Power 클래스가 생성되는 것과 마찬가지인데, 그렇게 되면 ComputerPower 는 완전의존성을 가진다고 볼 수 있습니다.
    하지만, 주입을 통해 Power 클래스 생성과 Computer 클래스의 생성을 독립적으로 진행함으로써 의존성을 줄였다고 생각할 수 있습니다.

  4. 객체간의 결합도를 낮출 수 있다.
    위의 3번과 마찬가지입니다. Computer 클래스가 생성되지 않으면 Power 클래스가 생성될 수 없기 때문에 결합도가 아주 높아집니다. 하지만 주입으로 인해 결합도가 낮아졌다고 볼 수 있습니다.

  5. 위와 같은 장점들로 인하여 리팩터링의 편의성도 함께 높아진다.
    우리는 이제 Power 가 고장나면 Power 만 고치면 됩니다. 물론 Computer 내에 다른 부분이 고장이 났다면 Power 를 고칠 필요도 없다는 뜻입니다.

이렇게 의존성 주입에 대해서 알아보았습니다.


참고 링크 (좋은 설명들 감사합니다!):

https://developer.android.com/training/dependency-injection?hl=ko

https://velog.io/@wlsdud2194/what-is-di

https://medium.com/@jang.wangsu/di-dependency-injection-이란-1b12fdefec4f

profile
🌱 주니어 안드로이드 개발자 최우영입니다.

0개의 댓글