
➡️의존성 주입이란
- 어떤 객체가 사용하는 의존 객체를 직접 만들어 사용하는게 아니라, 주입 받아 사용하는 방법이다.
- 예를 들어 장난감,리모컨,휴대폰 모두 배터리를 교체 할 수 있는 제품이라면 장난감,리모컨,휴대폰 모두 배터리에 의존하기 때문에 배터리를 갈아끼우는 것을 의존성 주입이라고 보면 된다.
- 그러나 만약 장난감이나 휴대폰이 배터리 교체가 불가능한 일체형이라면 교체하지 못하고 새제품으로 바꿔야 하기때문에 설계로 본다면 유연하지 못한 설계가 된다.
밑에 예제를 보고 의존성 주입이 필요한 이유를 알아보자
|
1
2
3
|
public class Americano{
}
|
cs |
|
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Cafe{
private Americano americano;
public Cafe() {
this.americano = new Americano();
}
}
|
cs |
- 예를 들어 아메리카노를 파는 카페 클래스를 만들었다.
- 그러나 위 예제는 객체들 간의 관계가 아니라 클래스 간의 관계가 맺어지고 있다. 객체지향적 설계라면 객체들 간에 관계가 맺어져야 하지만 현재는 카페 클래스와 아메리카노 클래스끼리 관계를 맺고 있다.객체들 간에 관계가 맺어졌다면 다른 커피종류의 클래스가 생겼는데 카페클래스가 알지 못하더라도 인터페이스 타입으로 사용할 수 있다.
- 그리고 카페클래스에서 메뉴를 추가할려면 카페클래스의 생성자 변경이 필요하다.일단 유연성이 떨어진다는 단점이 있다.
- 이걸 보면 상속으로는 해결할 수 있을거 같은데?라고 생각 하실수도 있지만 상속은 제약이 많고 확장성이 떨어지므로 피하는것이 좋다.
- 이 같은 문제는 관심사 분리가 되지 않았기 때문에 발생하는 문제이다. Spring에서는 의존성 주입을 통하여 이런 문제를 해결하려고 한다.
위와 같은 문제를 해결하기 위해선 다형성이 필요하다.일단 여러 메뉴를 하나로 표현하기 위해서는 인터페이스가 필요하다.그리고 Americano클래스에서 인터페이스를 우선 구현을 해준다.
|
1
2
3
4
|
public interface Menu{
}
|
cs |
|
1
2
3
4
|
public class Americano implements Menu{
}
|
cs |
다음으로 위에 문제가 있는 코드에서 Cafe와 Americano가 결합된 부분을 제거해준 다음 외부에서 상품을 주입(Injection)받아야 한다
|
1
2
3
4
5
6
7
8
9
10
11
|
public class Cafe {
private Menu menu;
public Cafe(Menu menu) {
this.Menu = menu; }
}
|
cs |
|
|
➡️이제 여기서부터 Spring이 DI컨테이너가 필요하다. 왜냐하면 Cafe에서 Menu객체를 주입하기 위해서는 애플리케이션 실행 시점에 필요한 객체를 생성해야 하고,의존성이 있는 두 객체를 연결하기 위해 한객체는 다른 객체주입시켜야 하기 떄문이다.
|
1
2
3
4
5
6
7
8
9
10
11
12
|
public class BeanFactory {
public void cafe() {
Menu americano = new Americano();
Cafe cafe = new Cafe(americano);
}
}
|
cs |
➡️위 처럼 Americano객체를 만들고 ,객체를 Cafe로 주입시켜주는 역할을 위해서 DI 컨테이너가 필요한것이다.
➡️또 이러한 개념은 제어의 역전이라고 불리기도 한다.객체를 사용할지에 대한 책임이 Beanfactory로 넘어갔고 객체 자신은 수동적으로 중비받는 객체를 사용하기때문이다.
💻의존성 주입 장단점
장점
- 재사용성을 높여준다.
- 테스트에 용이하다.
- 코드를 단순화 시켜준다.
- 사용하는 이유를 파악하기 수월하고 코드가 읽기 쉬워지는 점이 있다.
- 종속성이 감소하기 때문에 변경에 민감하지 않다.
- 결합도(coupling)는 낮추면서 유연성과 확장성은 향상 시킬 수 있다.
- 객체간의 의존관계를 설정할 수 있다.
단점
- 의존성 주입을 위한 선행작업이 필요함.
- 코드를 추적하고 읽기가 어려워짐.
마무리
➡️한 객체가 어떤 객체를 의존할 것인지는 별도의 관심사다.DI 컨테이너를 통해 서로 강하게 결합되어 있는 두 클래스를 분리하고, 두 객체 간의 관계를 결정해 줌으로써 결합도를 낮추고 유연성을 확보하고자 하였다. 의존성 주입으로 애플리케이션 실행 시점에 객체를 생성하고 관계를 결정해 줌으로써 다른 구체 클래스에 의존하는 코드를 제거하며 서로 다른 두 객체의 결합을 약하게 만들어 주었다. 또한 이러한 방법은 상속보다 훨씬 유연하다
의존 관계를 주입할 객체를 계속해서 생성하고 소멸한다면, 아무리 GC가 성능이 좋아졌다고 하더라도 부담이 된다. 그래서 Spring에서는 Bean들을 기본적으로 싱글톤(Singleton)으로 관리하는게 좋을거 같다.
REFERENCE
- https://velog.io/@jojo_devstory/DIDependency-Injection에-대해-알아보자
- https://devlog-wjdrbs96.tistory.com/165
- https://mangkyu.tistory.com/150
'Dev > Spring' 카테고리의 다른 글
| @RequestMapping에 대하여 (0) | 2021.07.24 |
|---|---|
| [Spring]@RestController 와 @Controller의 차이 (0) | 2021.07.18 |
| 로깅(Logging) (0) | 2021.07.13 |
| [Spring]다양한 의존관계 주입 방법 (0) | 2021.06.25 |
| [Spring]@RequiredArgsConstructor (0) | 2021.06.23 |