의존성 역전 (DI)
- 의존성의 역전이라는 용어는 처음 들었을 때 상당히 어려운 용어이다. 처음에 볼 때는 이해가 안되었는데, 클린아키텍쳐 도서의 일부 설명을 보고 드디어 이해가 되었다. 내가 이해를 못 한건 '역전'이라는 키워드를 쓴 이유가 궁금했기 때문이다..
- 의존성의 역전을 알기 위해서는
의존
의 의미와 보편적 의존
은 어떤 형태인지를 알아야한다.
의존
: 특정 모듈/클래스/메서드 A 가 다른 모듈/클래스/메서드 B에 있는 어떤 내용을 가져다 쓸 때, A는 B에 의존한다.
보편적 의존
: 상위모듈이 하위모듈에 의존하며, 의존성의 방향은 한쪽으로 (위에서 아래) 이어진다.
- 이제
의존성 역전
을 보자.

클린아키텍쳐 (로버트 C 마틴, 인사이트) - 5장 객체지향 프로그래밍 49p
- 사진을 보면 상위모듈
HL1
이 하위모듈 ML1
의 메서드 F()
를 참조하므로 HL1이 ML1에 의존
해야 한다.
그러나, HL1
은 ML1
를 직접적을 의존하는 것이 아니라 인터페이스 I를 통해 의존
하고 있다.
또한, ML1
은 I
를 구현하기 위해 인터페이스 I에 의존
한다. ( 이부분이 역전을 일으킴 )
- 즉 한 방향을 바라보고 의존하는 것이 아니라, 공통된 요소(인터페이스)를 바라보게 함으로써,
보편적 의존방향에 역전
을 일으킨다.
NestJS에서의 의존성 역전
@Injectable()
export class ProductService {
constructor(
@InjectModel(Product.name)
private readonly productModel: PaginateModel<ProductDocument>,
private hashtagService: HashtagService,
) {}
...
}
- nestJS에서 임의의 클래스를 보면, 인터페이스가 아닌, 클래스 주입받아서 구현하는 경우가 있다.
- 인터페이스를 통한 의존이 의존성 역전을 만들어 낸다고 했는데, 단지 클래스를 주입하는 것만으로도 의존성 역전이 성립할 수 있나?
- 혼동하지 말아야 할 것 : 생성자에 기입된 클래스는(a) 클래스가 직접 주입되는 것이 아니라, 클래스로 생성된 인스턴스를 주입하는 것이다.
즉, 주입되는 것은 구체적 개념인 인스턴스(사진에서 ML1)
이고, 의존하는 것은 추상적 개념인 클래스(사진에서 I)
이다.
- 예시로 들은 코드에서,
ProductService
는 HashtagService
클래스에 의존하지만, 주입되어 사용되는 것은 HashtagService (I)
의 인스턴스인 hashtagService(ML1)
이다.
그래서?
- 의존성 역전이 왜 필요할까?
- 결론부터 이야기하면, 각 모듈을 독립적으로 개발 할 수 있는 개발 독립성을 얻는다.
OO (Object Oriented)의 본질 : 다형성
문제
- 다형성 : 포인터를 응용하여, 외부에서 필요한 내용을 갖다 쓴 객체의 형태. 즉 한 객체가 여러 가지 타입을 가질 수 있는 능력.
- 다형적인 객체를 만들게 되면, 객체는 다른 요소들에 의존하게 된다.
- 이 의존은 객체들을 떨어지고 못 사는 관계로 만들어 버린다. 한 쪽이 변해 버리면 의존하고 있는 객체가 고장난다.
- 이런 현상은 프로그램 개발에서 어떤 영향을 미칠까?
- 하나를 수정하기위해 이것에 의존하는 다른 객체를 고려해야할 것이고, 이에 연관된 또 다른 객체들을 고려해야할 것이다.
- 즉, 의존성이 커져버리면, 수정과 예측이 (거의)불가능한 구조의 프로그램이 되 버릴 것이다.
해결
- 의존성 역전을 사용하면, 이 객체간의 강한 의존을 덜어낼 수 있다.
- 의도적으로 인터페이스와 같은 중간 매개체를 생성하여 이것에 의존하게 만든다.
- 의존하고 제공하는 두 객체는 인터페이스라는 매개체에 의존하고 제공하므로, 직접적인 연쇄적인 강한 결합력을 끊어낼 수 있다는 것.
- 이는 컴포넌트와 모듈들을 독립적으로 개발할 수 있게 만들고, 유지보수성과 생산성을 올릴 수 있는 구조가 된다.
결론
- 따라서 OO란, (소프트웨어 아키텍쳐 관점에서) 다형성을 이용하여 의존성에 대한 절대적인 제어 권한을 획득할 수 있는 방법이다.
전체결론
의존성의 역전을 통해 다형성을 가진 객체들을 제어하여, 생산성이 증대된 프로그래밍이 가능하다.