엄범

 

의존성이란?

"의존성 주입"이 무엇인지 얘기하기 전에 "의존성"이 무엇인지부터 명확히 해야 한다.

우리가 의존성 의존성 말은 많이 하는데, 의존성이라는 단어가 등장할때면 어김없이 추상적인 개념이 하나 둘 튀어나오다 보니 코드에서 정확히 뭘 의미하는건지 감을 못잡는 경우가 많다.

```java

public class SimpleMovieLister {
    // the SimpleMovieLister has a dependency on a MovieFinder

    private MovieFinder movieFinder;

}

```

이게 의존성이다. 별게 아님. 그냥 한 객체에서 다른 객체 갖다 쓰면 의존성이다. 

 

그렇다면 의존성 주입은 무엇이냐? 

```java

public class SimpleMovieLister {

    private MovieFinder movieFinder;

 

    public SimpleMovieLister(MovieFinder movieFinder) {

        this.movieFinder = Objects.requreNonNull(movieFinder);

    }

}

```

  • 이렇게 생성자를 통해서 객체(의존성)을 외부에서 넣어주면 그게 의존성 주입이다.
    "외부에서 객체를 만들고, 그걸 넣어준다." 를 어렵게 표현하면 의존성 주입.
    • SimpleMovieLister 내부에서 new MovieFinder()를 해서 직접 객체를 만들어버리는게 의존성 주입의 반대 라고도 할 수 있을 것 같다.
  • 의존성 주입은 이처럼 생성자를 통해서도 가능하고, setter를 통해서도 당연히 가능하다.
    • Constructor-based DI
    • Setter-based DI

 

이 개념이 왜 중요할까? : 인터페이스 참조를 통한 의존성 끊기

만약 MovieFinder가 인터페이스고, MovieFinder를 implement한 HorrorMovieFinder 클래스가 있다고 가정하자.

그러면 SimpleMovideFinder 안에서 MovideFinder 변수를 resolve하려면

```java

public class SimpleMovieLister {

    ... this.movieFinder = new HorrorMovieFinder()

}

```

요렇게 될 것이다.

근데 이렇게 SimpleMovieLister 안에서 구체적인 타입이 결정되어 버리면, SimpleMovieLister는 MovieFinder라는 인터페이스 자체가 아니라 HorrorMovieFinder와 의존성을 갖게 된다.

 

그래서 이걸 해결해 주는 것이 바로? DI다.

 

내부에서 new로 구체적인 객체를 생성해서 변수를 resolve하는게 아니라, 외부에서 구체적인 타입(HorrorMovieFinder)을 결정하고 그걸 SimpleMovieLister에 주입해 주겠다는 것이다.

 

DI를 사용하면 SimpleMovieLister는 MovieFinder의 실제 구현체가 무엇인지와 관계 없이 그냥 MovieFinder로 모든 것을 처리한다.

즉, MovieFinder와의 의존성만 존재하는 것이다. 어떤 구현체든지 그냥 외부에서 만들어서 넘기기만 하면 되니 재활용성이 높아진다.

 

그러나 DI를 사용하지 않고, SimpleMovieLister 안에서 new HorrorMovieFinder()를 만들게 되면 다른 MovieFinder 구현체를 사용하기 위해서는 코드를 수정해야한다.

 

```java

public class SimpleMovieLister {

    1... HorrorMovieFinder movieFinder = new HorrorMovieFinder();

    // 제일 별로. SimpleMovieLister 안에서 HorrorMovieFinder에 종속적인 필드,메서드를 사용하면서 의존성이 강해짐.

 

    2... MovieFinder movieFinder = new HorrorMovieFinder();

    // 이 정도만 해도... 다른 MovieFinder가 필요하다면 선언부만 변경해주면 되니까 변경에 대한 부담이 크진 않은.

    // 하지만 다른MovieFinder를 사용해 테스트를 하기 위해서는? 여기까지 와서 Horror..를 다른 것으로 변경해주어야 한다.

 

    3... MovieFinder movieFinder;

    // DI를 사용하면 아예 의존성 그래프 자체가 HorrorMovieFinder와 직접 연결되지 않음.

    // 다른MovieFinder를 사용해 SimpleMovieLister를 테스트하고 싶다면, 그냥 다른MovieFinder를 DI 해주면 되므로 테스트 용이.

}

```

 

언제 써야 하나?

DI 개념은 그냥 객체를 외부에서 만들어서 넣어주면 되는 것이기 때문에, 프레임워크와 무관하게 언제든 사용할 수 있다.

그러나 의존성이 많아지면 그 만큼 코드가 어지러워 진다.

그래서 Spring, Dagger같은 DI 프레임워크를 사용하는 것이고,

이를 사용하면 설정한 대로 프레임워크가 알아서 DI 해준다.

 

'Coding Note > CodingKnowledge' 카테고리의 다른 글

Promise / Future에 대한 개념 정리  (0) 2020.03.20
Reactive Programming  (0) 2020.02.17
의존성 주입(DI, Dependency Injection)이란?  (0) 2019.05.10
REST api / RESTful 이란.  (0) 2019.05.03
자료 구조 선택 가이드  (0) 2018.12.20
직렬화, Serialization  (0) 2017.12.01