DI(Dependency Injection)

DI(Dependency Injection)를 하는 방법은 여러가지가 있다. 그 방법을 알아보기 전에 DI가 왜 필요한가에 대해서 알아보자.

DI는 왜 필요한가?

객체 의존성은 객체가 다른객체를 참조, 상호작용을 하여 긴밀한 연결, 결합이 생기는 것이다.
객체 의존은 아래와 같은 문제가 발생된다.

  1. 하나의 모듈이 바뀌면 의존한 다른 모듈까지 변경되어야한다.
  2. 결합이 강하기 때문에 Unit Test 작성이 어렵다.

그렇기 때문에 Framework에 의해 객체의 의존성을 주입하게 되는 설계패턴, DI를 이용하게 되는 것이다.

DI를 찾다보면 Ioc(제어의 역전)라는 것도 보게되는데 이 둘은 같은의미로 사용되며 IocDI를 통해 달성된다.

Ioc는 말그대로 모든 제어의 중심이 Framework로 넘어가는 것이다.

#DI의 장점

  1. 종속성 감소(느슨한 결합)
  2. 재사용성 증가
  3. 더 많은 테스트코드 작성 가능
  4. 코드 가독성 증가

의존성 주입 방법

대표적으로 마틴파울러가 제시한 세가지 방법이 있다.

1. 생성자를 통한 주입

1
2
3
4
5
6
7
8
9
10
11
12
@Component
public class DI {
private Dependency dependency;
private Dependency2 dependency2;

@Autowired
public DI(Dependency dependency,Dependency2 dependency2) {
this.dependency = dependency;
this.dependency2 = dependency2;
}
...
}
  • 필요한 의존성을 모두 포함하는 클래스의 생성자를 만들고, 그 생성자를 통해 의존성을 주입한다.

2. Setter를 통한 주입

1
2
3
4
5
6
7
8
9
@Component
public class DI {
private Dependency dependency;

@Autowired
public void setDependency(Dependency dependency) {
this.dependency = dependency;
}
}
  • 의존성을 입력받는 Setter메소드를 만들고, 이를 통해 의존성을 주입한다.

3. Interface를 통한 주입

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface InjectFinder {  
void injectFinder(MovieFinder finder);
}

class MovieLister implements InjectFinder...
public void injectFinder(MovieFinder finder) {
this.finder = finder;
}

public interface InjectFinderFilename {
void injectFilename (String filename);
}

class ColonMovieFinder implements MovieFinder, InjectFinderFilename......
public void injectFilename(String filename) {
this.filename = filename;
}
  • 의존성을 주입하는 함수를 포함한 인터페이스를 작성하고 인터페이스를 구현함으로써 실행시에 주입을 한다. (스프링에서 지원하지 않는 방식)

어떤방법을 쓸까?

  • Spring 3.x에서는 Setter를 이용한 방법을 지지하고있다. 왜냐하면 외부에서 제공받은 오브젝트 레퍼런스를 저장해뒀다가 내부의 메소드에 의해서 사용하게 하기 때문에 DI 방식에서 활용하기 적당하기 때문이다.
  • 하지만 Spring 4.x로 넘어오면서 Constructor를 이용한 주입을 지지하고있다. 생성자에는 final을 선언할 수 있으므로 객체가 불변하도록 할 수 있고, 순환의존성도 알 수 있다고한다.

0%