본문 바로가기
개발용어

dependency injection이란, DI란, 의존성 주입이란

by devscb 2021. 12. 22.
반응형





dependency injection이란, DI란, 의존성 주입이란


spring framework를 공부할때 dependency injection(DI)를 많이들 들어보셨을 것입니다.
혹은 SOLID원칙을 배울때도 D부분이 dependency inversion principle이기도 하지요.
dependency injection, 한국어로는 의존성 주입이 무엇인지 알아보겠습니다.
먼저 용어 뜻을 분해해서 dependecny 와 injection 이 무엇인지 살펴보겠습니다.

1. dependency란? (의존성이란)
의존성이 있다라는 것은 한 클래스(A)에서 다른 클래스(B)를 사용한다라고 이해하면 됩니다.
의존성이 있다면 B가 변경이 되었을때, A도 변경을 해야하며, 이를 A가 B에 의존해 있다라고 (dependecny가 존재한다) 라고 표현합니다.
예를 들어 아래와 같은 코드를 봅시다.
아래 코드는 Computer가 Monitor 클래스에 의존하는 형태입니다.


class Computer{
 Computer(){}
 void on(){
 Monitor m = new Monitor();
 m.turnOn();
 }
}

class Monitor(){
 Monitor(){}
 void turnOn(){
 print("monitor turn on");
 }
}



만일 Monitor가 on되는 method를 아래와 같이 변경한다면?


class Monitor(){
 Monitor(){}
 void on(){
 print("monitor turn on");
 }
}



Computer class의 on method가 아래와 같이 변경되어야 겠지요


class Computer{
 Computer(){}
 void on(){
 Monitor m = new Monitor();
 m.on(); //m.turnOn();
 }
}


이렇게 한 클래스가 변경될때 다른 클래스도 변경되어야 하는것이 의존성이 있다라고 표현합니다.
UML 로 표현하면 아래와 같이 됩니다.

 



2. Dependency Injection이란? (의존성 주입이란?)
의존성을 주입한다는것은 무슨뜻인지 알아봅시다.
위 예제에서 의존성을 갖게 되는것은 Computer란 class 안에서 Monitor를 사용했기 때문에 의존성이 생겼습니다.
그렇다면, 의존성을 주입한다는 것은 Monitor를 사용하는 Computer Class가 아니라,
다른 클래스에서 Monitor를 사용하도록 한다는 뜻이 되겠습니다.
Spring framework에서는 이를 Container 라 칭합니다.
의존성을 주입한다는 것은 어떻게 이뤄질까요? 다음과 같이 주입을 해줄 수 있습니다.



class Person{
 void action(){
 Computer c = new Computer(new Monitor());
 c.on();
 }
}
interface Device{
 void on();
}
implements Device(){
 void on(){
 print("monitor turn on");
 }
}
class Computer{
 Device device;
 Computer(Device d){
 this.device = d;
 }
 void on(){
 d.on();
 }
}



앞선 예제보다 갑자기 코드가 길어졌네요.
우선, Person의 action 메소드를 봅시다.
Computer class의 객체가 생성될때 Monitor를 생성하여 매개변수로 넘겨줍니다.
이것이 바로 injection 입니다. Computer가 아니라, Computer 외부에서 Monitor 객체를 넘겨주어 Computer와 Monitor class와의 의존성을 없애줍니다.
이를 이루기 위해서 Device라는 interface를 만들었고,
Monitor 클래스는 이를 상속하게 하였습니다.
Dependency Injection은 이처럼 class 간의 의존성을 제거하기 위해 사용되는 패턴이라고 말할 수 있습니다.
이것이 추상화에 의존하고, 구체화에 의존하지 말라는 SOLID 원칙 중의 Dependency inversion principle 입니다.


더 깊게 예제 살펴보기


Monitor를 사용하는 class가 Computer말고도 Television이 있다고 해봅시다.
DI를 쓰지 않는 버전의 코드는 다음과 같이 되겠습니다.


class Person{
 void action(){
 Computer c = new Computer();
 c.on();
 
 Television t = new Television();
 t.on();
 }
}

class Computer{
 Monitor m;
 Computer(){
 m = new Monitor();
 }
 void on(){
 m.on();
 }
}

class Television{
 Monitor m;
 Television(){
 m = new Monitor();
 }
 void on(){
 m.on();
 }
}

class Monitor(){
 Monitor(){}
 void on(){
 print("monitor turn on");
 }
}



Monitor에서 BigMonitor로 바꾼다고 하면 다음과 같이 Computer와 Television 클래스를 찾아서, 변경을 해야겠지요.


class Person{
 void action(){
 Computer c = new Computer();
 c.on();
 
 Television t = new Television();
 t.on();
 }
}

class Computer{
 BigMonitor m;//Monitor m;
 Computer(){
 m = new BigMonitor();
 }
 void on(){
 m.on();
 }
}

class Television{
 BigMonitor m;
 Television(){
 m = new BigMonitor();
 }
 void on(){
 m.on();
 }
}



다음으로 DI 를 사용한 예제를 봅시다.


class Person{
 void action(){
 Computer c = new Computer(new Monitor());
 c.on();
 
 Television t = new Television(new Monitor());
 t.on();
 }
}

class Computer{
 Device device;
 Computer(Device d){
 device = d;
 }
 void on(){
 d.on();
 }
}

class Television{
 Device device;
 Television(){
 device = d;
 }
 void on(){
 d.on();
 }
}



마찬가지로 BigMonitor로 바꾼다면, 아래와 같이 Person Class만 바꿔주면 됩니다.


class Person{
 void action(){
 Computer c = new Computer(new BigMonitor()); //Computer c = new Computer(new Monitor());
 c.on();
 
 Television t = new Television(new BigMonitor()); //Computer c = new Computer(new Monitor());
 t.on();
 }
}


이처럼 DI를 쓰지 않는다면 변경이 이뤄지는 각 class를 찾아야 하고(보통 파일이 각각 나눠져 있겠지요),
각 class마다 일일이 변경이 필요한 곳을 찾아 코드 수정을 해야합니다.
DI를 쓴다면 하나의 class에서만 변경을 하면 되니 훨씬 수정이 쉬워지게 되겠지요.
프로그램 규모가 커질수록 DI의 장점이 크게 느껴지실 겁니다.


Dependency Injection의 장점


위 내용을 토대로 DI 패턴을 사용하게 되었을 때의 장점을 더 알아보겠습니다.


1. 변화에 유연해집니다.
의존한다는 것은 그 의존대상의 변화에 취약하다는 것입니다.
(대상이 변화하였을 때(Monitor), 이에 맞게 수정필요(Computer))
DI로 구현하게 되었을 때, 주입받는 대상이 변하더라도 그 구현 자체를 수정할 일이 없거나 줄어들게 됩니다.
단, 인터페이스를 사용하였기 때문에 인터페이스 설계를 잘 해야겠지요.

2. 테스트하기 좋은 코드가 됩니다.
Monitor의 테스트를 Computer 테스트와 분리하여 진행할 수 있습니다.
또한, Computer는 다른 device들을 넣어 다양한 테스트를 할 수도 있고, test용 class 등을 만들어 mock을 이용한 테스트 등도 용이하게 할 수 있습니다.

3. 재사용성이 높은 코드가 됩니다.



총평


DI(의존관계 주입)는 객체가 의존하는 객체를 외부에서 선언하고 이를 주입받아 사용하는 패턴이라고 한줄로 요약할 수 있겠습니다.
직접 써봐야 예제에서는 코드가 복잡해지고 길어지는것처럼 보이는데요, (interface를 선언해야함.)
실제로 이 패턴을 사용하는 경우는 훨씬 복잡한 프로그램 개발시에 사용되는 패턴이기에 패턴을 사용하지 않았을때 보다 훨씬 더 짧은 코드가 만들어질 수 있습니다.
더 짧은 코드는 유지보수하기도 더 쉬운패턴이 되겠지요.


dependency injection이란, DI란, 의존성 주입이란
#DI,#spring,#springframework,#framework,#java,#class,#의존성,#주입,#dependecny,#injection,#SOLID,#solid,#의존성주입

 

https://devscb.com/post/77

 

What is dependency injection? What is DI? What is dependency injection?

What is dependency injection, what is DI, what is dependency injection?When studying spring framework, you may have heard of dependency injection (DI).Or, when learning SOLID principles, part D is als

devscb.com

 

728x90
반응형

댓글