의존성 역전 원칙(Dependency Inversion Principle, DIP)
(C++ 소프트웨어 디자인 책 정리)
가장 유연한 시스템은 소스 코드 의존성이 구체화(concretion)가 아닌 추상화만 참조하는 시스템이다.
이 원칙은 의존성을 위해 구체 타입이나 구현 상세 대신 추상화에 의존할 것을 조언한다.
상속 계통에 대해서는 아무 말도 하지 않고 일반적인 추상화만 언급한다.
지금부터 자동 입출금기(ATM)의 논리를 구현한다고 생각해보자. ATM은 인출, 입금, 송금 등 여러가지 연산을 제공한다. 이 모든 연산은 실제 돈을 다루므로 완전히 완료하거나 오류가 있으면 중단하고 모든 변경을 되돌려야 한다. 이런 행위를 일반적으로 transaction 이라고 한다.
결과적으로 Transaction이라는 추상화를 도입할 수 있다. 모든 추상화 (Deposit, Withdrawal, Transfer)는 Transaction 클래스를 상속한다.

위 설정은 얼마간 작동할 수 있지만 잠재적 문제가 있다. 만약 새 transaction을 추가하면 어떻게 될까?
VIP고객을 위해 SpeedTransfer 트랜잭션을 추가해야한다고 가정하자.
이를 위해 UI 클래스를 변경하고 확장해야 할 수 있다. 이는 차례로 다른 모든 트랜잭션에도 영향을 준다. UI 클래스에 직접 의존하기 때문이다.
최상의 경우 트랜잭션을 단순히 다시 컴파일해 테스트하면 되지만, 최악으로 별도의 공유 라이브러리로 제공하는 경우 재배포해야 할 수도 있다.
단일 추상화로 이 문제를 해결할 수 없으므로, 트랜잭션 하나당 하나씩, 세 개의 추상화가 필요하다.

DepositUI, WithdrawalUI, TransferUI 클래스를 도입해 세 추상화 사이의 의존성을 깨뜨렸다. 세 추상화는 더 이상 구체 UI 클래스에 의존하지 않으며, 관련 트랜잭션이 실제 요구하는 연산만 나타내는 가벼운 추상화에 의존한다.
하지만 이 관심사 분리는 ISP를 따랐고 아직 DIP를 따르지 않는다

위 UML은 지역 역전이다. 아키텍처 관점에서는 고수준에서 저수준으로 의존한다. 따라서 추상화를 도입하는 것만으로는 충분하지 않다. 추상화를 도입할 위치를고려하는 것도 중요하다. 로버트 마틴은 다음 두가지로 이를 표현했다.
- 고수준 모듈은 저수준 모듈에 의존해서는 안된다. 둘 모두 추상화에 의존해야 한다.
- 추상화는 세부 내용에 의존해서는 안 된다. 세부 내용이 추상화에 의존해야 한다.
아래와 같이 추상화를 고수준에 배치하고 고수준을 추상화 소유자로 만듦으로써 진정으로 DIP를 따른다.

'Language > C++ Design Pattern' 카테고리의 다른 글
Visitor 패턴 (std::variant) (0) | 2025.02.05 |
---|---|
Visitor 패턴 (1) | 2025.02.02 |
LSP 원칙 (0) | 2025.01.30 |
OCP 원칙 (0) | 2025.01.29 |
ISP 원칙 (0) | 2025.01.29 |