DIP는 Dependency Inversion Principle의 약자로, 객체 지향 설계 원칙 중 하나입니다. 이 원칙은 의존성 역전 원칙이라고도 하며, SOLID 원칙 중 마지막에 해당합니다. DIP의 핵심은 상위 모듈(추상화된 모듈)이 하위 모듈(구체화된 모듈)에 의존하지 않도록 하여, 모듈 간의 결합도를 낮추고 코드의 유연성을 높이는 것입니다.
DIP의 기본 개념
DIP는 다음 두 가지 규칙으로 정의됩니다:
- 상위 모듈은 하위 모듈에 의존해서는 안 된다. 둘 다 추상화에 의존해야 한다.
- 추상화는 구체적인 사항에 의존하지 않는다. 구체적인 사항이 추상화에 의존해야 한다.
이 원칙에 따라 구체적인 구현이 아닌 추상화(인터페이스나 추상 클래스)에 의존하게 만들어야 합니다. 이렇게 하면, 구현을 바꾸더라도 상위 모듈에 미치는 영향을 최소화할 수 있어 유연하고 유지보수가 용이한 코드를 작성할 수 있습니다.
DIP가 필요한 이유
DIP가 없으면, 상위 모듈이 하위 모듈의 구체적인 구현에 의존하게 되어 두 모듈 간의 결합도가 높아집니다. 이렇게 되면, 하위 모듈의 변경 사항이 상위 모듈에 영향을 주기 때문에 코드 수정 시 변경 범위가 넓어지고 유지보수가 어려워집니다.
DIP를 적용하면 인터페이스나 추상 클래스를 통해 상위 모듈이 하위 모듈과 소통하므로, 하위 모듈의 변경이 상위 모듈에 미치는 영향을 줄일 수 있습니다.
DIP의 예제
예를 들어, 아래와 같은 Keyboard
와 Monitor
클래스가 있고, 이를 사용하는 Computer
클래스가 있다고 가정해 보겠습니다.
class Keyboard {
void type() {
System.out.println("키보드를 입력합니다.");
}
}
class Monitor {
void display() {
System.out.println("화면을 출력합니다.");
}
}
class Computer {
private Keyboard keyboard;
private Monitor monitor;
public Computer() {
this.keyboard = new Keyboard();
this.monitor = new Monitor();
}
void start() {
keyboard.type();
monitor.display();
}
}
위의 코드에서는 Computer
클래스가 Keyboard
와 Monitor
클래스에 직접 의존하고 있습니다. 이런 구조에서는 키보드나 모니터의 구체적인 구현을 바꾸거나 새롭게 추가해야 할 때, Computer
클래스도 함께 수정해야 합니다. 결합도가 높아지는 문제점이 발생합니다.
DIP 적용 예제
DIP를 적용하여 의존성을 낮추기 위해 Keyboard
와 Monitor
에 인터페이스를 정의하고, Computer
는 인터페이스에 의존하도록 바꿔 보겠습니다.
interface InputDevice {
void type();
}
interface DisplayDevice {
void display();
}
class Keyboard implements InputDevice {
public void type() {
System.out.println("키보드를 입력합니다.");
}
}
class Monitor implements DisplayDevice {
public void display() {
System.out.println("화면을 출력합니다.");
}
}
class Computer {
private InputDevice inputDevice;
private DisplayDevice displayDevice;
public Computer(InputDevice inputDevice, DisplayDevice displayDevice) {
this.inputDevice = inputDevice;
this.displayDevice = displayDevice;
}
void start() {
inputDevice.type();
displayDevice.display();
}
}
이제 Computer
클래스는 Keyboard
와 Monitor
의 구체적인 구현이 아닌, InputDevice
와 DisplayDevice
라는 인터페이스에 의존하게 됩니다. 따라서, 키보드나 모니터의 구체적인 구현을 교체하거나 새로운 입력 장치 또는 디스플레이 장치를 추가하더라도 Computer
클래스는 변경할 필요가 없습니다.
DIP의 장점
- 유연성 향상: 코드가 구체적인 클래스가 아닌 추상화에 의존하므로 구현을 쉽게 교체할 수 있습니다.
- 유지보수 용이성: 변경이 필요할 때 영향 범위가 줄어들어 수정이 용이합니다.
- 테스트 용이성: 테스트 시 특정 구현을 쉽게 대체(mocking)할 수 있어 단위 테스트에 유리합니다.
DIP는 특히 의존성 주입(Dependency Injection)을 통해 구현되는 경우가 많으며, Spring과 같은 프레임워크에서도 DIP를 쉽게 적용할 수 있도록 지원합니다. DIP는 결합도를 줄이고 코드의 재사용성을 높이기 위한 중요한 원칙입니다.
'Spring' 카테고리의 다른 글
파일 디렉터리 구조 형성 방법들 (0) | 2024.11.10 |
---|---|
IoC와 DI: Java 개발에서 꼭 알아야 할 개념 (0) | 2024.11.10 |
SQL, JPQL, 쿼리 메소드 비교 및 정리글 (0) | 2024.11.10 |
다양한 디자인 패턴 정리글 (0) | 2024.11.10 |
Lombok,Gradle,Jackson에 대하여 (0) | 2024.11.10 |