Programming/Java

[Java] SOLID - 의존성 역전 원칙 (DIP / Dependency Inversion Principle)이란? (개념/ 예제)

JeongKyun 2022. 5. 12.
반응형

서론


드디어 마지막 순서인 객체지향 설계 원칙(SOLID)의 DIP에 대해서 알아보자!



객체지향 설계 5대 원칙



DIP(Dependency Inversion Principle) - 의존성 역전 원칙이란?


DIP의 뜻을 정의한 내용은 아래와 같다.


"고수준 모듈은 저수준 모듈에 의존하면 안된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야한다. 즉, 자신보다 변하기 쉬운것에 의존하지 마라"

이 정의를 말을 다시 말하면,
의존 관계를 맺을 때 변화하기 쉬운 것과 자주 변화하는 것 보다는 변화하기 어려운것과 거의 변화가 없는것에 의존하라는 원칙을 말한다.

이것을 적용시키기 위해서는 우선 변화하기 어려운 것을 알아야한다. 여기서 변화하기 어려운것을 말하는 것은 추상적인 객체(Interface, abstract)를 말한다.

예졔를 통해 이해해보자.


[예제]

[DIP 적용 전]

[예제 시나리오]

운전하고 싶은 차량(Car)을 탑승하여 운전(drive())을 할 때의 예제이다.

Truck (Class)

class Truck {
    String drive() {
        return "Truck";
    }
}

Truck 클래스에서 운전을 하기 위해 drive()함수를 만들어주었다.

Van (Class)

class Van {
    String drive() {
        return "Van";
    }
}

CarService (Class)

public class CarService {
    private Truck car1;
	private Van car2
    
    public void setCar1(Truck car1) {    
        this.car1 = car1;
    }

    public void setCar2(Van car2) {
        this.car2 = car2;
    }

    public String drive1() {
        return car1.drive();
    }
    
        public String drive2() {
        return car2.drive();
    }
}

위와 같이 작성한다면, 차량의 종류가 추가될 때마다 setCar의 함수가 늘어날 수 밖에 없는 구조이다. 이러한 잘못된 구조를 변경하기 위해 아래와 같이 변화하지 않는 추상화 인터페이스를 하나 만들어 놓고 작업을 해야한다.


[DIP 적용 후]

Car (Interface)

public interface Car {
    String drive();
}

Interface에서 공통 부분을 추상화한 함수인 drive()를 생성해준다.

Truck (Class)

public class Truck implements Car {
    @Override
    public String drive() {
        return "Truck";
    }
}

위와 같이 작업을 추상화한 인터페이스를 오버라이딩하여 작성해주었다.

Van (Class)

public class Van implements Car {
    @Override
    public String drive() {
        return "Van";
    }
}


위 처럼 Truck과 다른점은 없고 Car 인터페이스를 상속받는 구조는 똑같다.

CarService (Class)

public class CarService {
    private Car car;	
    
    public void setCar(Car car) {    
        this.car = car;
    }

    public String drive() {
        return car.drive();
    }
    
    public void print() {
        System.out.println(car.drive());
    }
}

MainController (Class)

public class MainController {
	public static void main(String[] args) {
		CarService carService = new CarService();
		Car truck = new Truck();
		Car van = new Van();
		
		carService.setCar(truck);
		carService.print();

		carService.setCar(van);
		carService.print();
		
	}
}

결과

실행결과

MainController에서 실행시 위와 같은 결과가 나온다.
위 처럼 Car라는 Interface를 만들어서 프로그램을 보다 더 확장성있게 만들어줄 수 있다. 또한, DIP를 잘 작성해주면 객체간의 관계를 최대한 느슨하게 해주는 효과도 있다.

"고수준 모듈은 저수준 모듈에 의존하면 안된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야한다. 즉, 자신보다 변하기 쉬운것에 의존하지 마라"

앞서 말했던 정의와 비교하여 생각해보면,
예제에서 CarService가 고수준 모듈이 되고 Trcuk과 Van이 저수준 모듈이라하면 현재 이 둘은 서로 의존하지 않고 Car 인터페이스라는 추상화 된 것에 의존하게 만들어주었다고 보면된다.

이상 SOLID의 개념을 마무리지어보겠습니다.

댓글

💲 많이 본 글