[SOLID] DIP에 대해 알아보자

eunduk.log·2024년 7월 7일
1

드디어 SOLID에 마지막 법칙인 DIP !

사실 DIP 없이는 OCP를 구현할 수 없다고 생각해서.. OCP를 완전히 이해하고 적용할 수 있는 사람이라면 DIP 개념이 어렵지 않을 것이라고 생각한다.

그렇지만 처음 본다면 상당히 어려운 개념.. 쉬운 비유와 예시를 통해 마스터 해보도록 하자 ;-;


DIP

Dependency Inversion Principle : 의존성 역전 법칙

  • 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
  • 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.

이게 도대체 무슨 소리인가 싶지만.. 비유를 통해 차근차근 알아보자.


노트북 VS 데스크탑

일단 시작에 앞서 상위 모듈은 컴퓨터, 하위 모듈은 키보드라고 해보자.

노트북은 내장되어 있는 빌트인 키보드에 절대적으로 의존하고 있다고 볼 수 있다.
키보드가 고장나면 노트북 사용에 큰 영향을 끼치고 다른 키보드로 바꿔끼기도 싶지 않다.
이 상황에서 첫번째 정의와 같이 상위 모듈이 하위 모듈에 의존하고 있다고 볼 수 있다.

그럼 다음으로 데스크탑에서의 키보드 사용을 살펴보자.

데스크탑은 어떤 키보드 자체를 의존하고 있는 것이 아닌 키보드의 신호가 들어오는 USB 포트를 의존하고 있다.
마찬가지로 키보드 입장에서도 데스크탑이 아닌 USB 포트를 의존하고 있다고 볼 수 있다.
각 모듈의 독립성은 유지한 채 USB포트라는 추상화를 바라봄으로써 상위 모듈과 하위 모듈은 추상화에 의존한다고 볼 수 있다.
이 때, 키보드가 고장나더라도 쉽게 다른 키보드로 교체할 수 있어 유연성과 확장성에 용이하다.

이 처럼, 실생활에서도 의존성이 낮아지면 좋은 이점을 많이 얻어갈 수 있다.


코드 예시

  • 노트북 코드 예시
class BuiltInKeyboard {
    func type() {
        print("Typing on built-in keyboard")
    }
}

class Laptop {
    let keyboard = BuiltInKeyboard()
    
    func useKeyboard() {
        keyboard.type()
    }
}

// 사용 예시
let myLaptop = Laptop()
myLaptop.useKeyboard()

// result
// "Typing on built-in keyboard"

코드에서 상위 모듈인 Laptop은 BuiltInKeyboard라는 하위 모듈을 완전히 의존하고 있는 상태이다.
이러면 Laptop 클래스는 BuiltInKeyboard클래스만을 위한 클래스가 되는 것이다.
이 것은 DIP가 위반된 것으로 상위 모듈과 하위 모듈 모두 추상화를 바라볼 수 있게 리팩토링 해줘야 한다.
만약, 기존 키보드를 새로운 키보드로 교체하여 사용하려고 하면 Laptop 코드의 변경이 일어나야 하므로 OCP 원칙을 위반한게 될 것이다.

  • 데스크탑 코드 예시
// 추상화된 프로토콜
protocol Keyboard {
    func type()
}

// 구체적인 구현 1: Normal 키보드
class NormalKeyboard: Keyboard {
    func type() {
        print("Typing on normal keyboard")
    }
}

// 구체적인 구현 2: LED 키보드
class LEDKeyboard: Keyboard {
    func type() {
        print("Typing on led keyboard")
    }
}

// 데스크탑 클래스는 추상화된 프로토콜에 의존
class Desktop {
    var keyboard: Keyboard
    
    init(keyboard: Keyboard) {
        self.keyboard = keyboard
    }
    
    func useKeyboard() {
        keyboard.type()
    }
}

// 사용 예시
let normalKeyboard = NormalKeyboard()
let ledKeyboard = LEDKeyboard()

let myDesktopWithUSB = Desktop(keyboard: normalKeyboard)
myDesktopWithUSB.useKeyboard()

// result
// "Typing on USB keyboard"

let myDesktopWithBluetooth = Desktop(keyboard: ledKeyboard)
myDesktopWithBluetooth.useKeyboard()  

// result
// "Typing on Bluetooth keyboard"

해당 코드에서는 프로토콜로 추상화를 구현하고 상위 모듈인 Desktop과 하위 모듈인 NormalKeyboard, LEDKeyboard가 모두 추상화를 의존하고 있는 형태이다.

DIP를 위반하지 않은 코드로, Desktop에서는 여러 형태의 키보드를 사용할 수 있으며 새로운 키보드로 교체 하여도 Desktop 코드에 영향을 끼치지 않으므로 OCP 원칙도 잘 지킨 것을 확인할 수 있다.


여기까지 실생활 비유와 코드 예시를 통해 DIP를 알아보았다.

처음에는 다소 생소한 원칙이지만 좋은 코드 구조를 위해서 꼭 필요한 원칙으로 실무에서도 적용하려는 습관을 들이려고 노력해야 한다.

DIP 한 줄 결론

추상화에 의존하라!!


모든 피드백 감사합니다. (꾸벅)

profile
iOS 개발자

0개의 댓글