이 글은 객체지향 5대 원칙, SOLID principle 중 D인 Dependency Inversion Principle, 의존성 역전 원칙에 대해 알아본다.
정의
dependency를 가지는 component가 구현체가 아닌 추상화에 의존해야 한다는 원칙이다.
- 각 모듈들이 dependency를 가질 때(상위 module이 하위 module을 사용할 때) concretion이 아닌 abstraction에 의존해야 한다.
- abstraction은 concretion에 의존하면 안 된다. concretion은 abstraction에 의존해야 한다.
결국 모든 경우에 abstraction에 의존해야 한다.
예전의 설계는 상위 module이 하위 module의 concretion을 직접적으로 사용하며, 이 때 dependency가 생긴다. 그러나 Dependency Inversion Principle을 준수하게 되면 상위 module의 concretion은 하위 moudle의 abstraction에 의존해야 한다. 이처럼 concretion에 직접 의존하는 기존의 방식과 반대되는 방식이기 때문에 Dependency Inversion이라고 부른다.
언제 사용해야 할까?
Dependency Inversion Principle은 Open Closed Principle과도 아주 유사하다. abstraction이 아닌 concretion에 의존하는 경우인 다음 예시를 보자.
일반적으로 아무것도 신경쓰지 않고 코드를 작성한다고 하자. A는 B를 사용하고 B는 C를 사용하고 있다. 따라서 A는 B에 depend하고, B는 C에 depend한다. 이런 상황에서 직접 구현체에 의존하면 C가 바뀌면 B도 바뀌어야 하고 B가 바뀌면 C도 바뀌어야 한다. 요구사항은 시시때때로 바뀌기 때문에 요구사항 하나의 변화로 인해 너무 많은 코드를 고쳐야 하며 너무 많은 코드를 고치다 보면 실수가 나기 십상이다.
Dependency Inversion Principle을 준수하기 위해서는 위와 같이 바꾸어야 한다. Class B는 Interface of B를 implement하고, Class C는 interface of C를 implement한다. 이렇게 각 module을 abstraction한다. 이후, Class A는 Interface of B, B의 abstraction에 depend하게 설정한다. 마찬가지로 Layer B는 C의 abstraction에 의존하게 설정한다.
이를 통해 의존관계가 있는 component 사이의 coupling이 줄어들게 된다. concretion인 Class B나 Class C가 변경되더라도 interface에는 영향을 주지 못한다.
어떻게 사용해야 할까?
Dependency Injection, Abstract Factory Pattern 등을 사용할 수 있다.
Dependency Injection
Polymorphism에서 주구창창 다뤘던 upcasting이다. runtime에 interface나 parent class에 들어갈 내용을 넣어줄 수 있기 때문에 dependency injection이라 한다.
Abstract Factory Pattern
유사한 object 생성 시 사용하며 여러 개의 factory를 abstraction한 interface와, 이것을 구현한 factory pattern을 사용하는 방법이다.
이점
유지보수성, 유연성, 확장성 증가
concretion을 바꾸어도 interface에는 영향을 주지 않기 때문에 interface에 의존하는 상위 수준 module을 바꾸지 않아도 된다. 따라서 코드 변경의 유연성이 증가하고, 유지보수성 또한 증가한다.
결합도Coupling 감소
class들이 직접 의존하지 않기 때문에 coupling이 감소한다.
유의점
concretion은 변하고, interface는 변하지 않는다. 따라서 Object로 구현해야 할 것(변하는 것)과 Interface로 구현해야 할 것(변하지 않는 것)을 잘 구분해야 한다. 이것을 잘 구분하고 module hierarchy를 설계해야 한다.
'CS > OOP' 카테고리의 다른 글
[OOP] SOLID 정리 (0) | 2023.03.12 |
---|---|
[OOP] SOLID - Interface Segregation Principle (0) | 2023.03.11 |
[OOP] SOLID - Liskov Substitution Principle (0) | 2023.03.09 |
[OOP] SOLID - Open Closed Principle (0) | 2023.03.07 |
[OOP] SOLID - Single Responsibility Principle (0) | 2023.03.06 |