스프링 의존 관계 역전 원칙 (DIP)



의존 관계 역전 원칙 (from SOLID)

그림 1

문제

  • 이렇게 고수준 모듈이 저수준 모듈을 의존하고, 저수준 모듈이 다시 고수준 모듈을 의존하는 것을 의존성 부패(Dependency Rot) 라고 한다.
  • 또한 지나친 의존관계는 많은 변경 포인를 유발한다.


지나친 의존 관계

그림 2


확장에 유연하지 못함

@RequestMapping(value = "/payments", method = RequestMethod.POST)
public void pay(PaymentRequest req){
    if (req.getType() == CardType.SHINHAN) {
        shinhanCardPaymentService.pay(req);
    } 
    else if (req.getType() == CardType.WOORI) {
        wooriCardPaymentService.pay(req);
    }
    ...
    // 이런 반복적인 if 구조는 리팩터링 대상일 확률이 높다..
}

해결

  • 의존 관계 역전 원칙 : DIP (Dependency Inversion Principle)

” 고차원 모듈은 저차원 모듈에 의존하면 안된다. 이 모듈 모두 다른 추상화된 것에 의존해야 한다.
추상화 된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다. “

  1. 고차원 모듈에 존재하는 저차원 모듈 의존을 끊는다.
    그림 3
  2. 모듈 모두 다른 추상화된 것에 의존해야 한다. 추상화 된 것은 구체적인 것에 의존하면 안 된다.
    그림 4
  3. 구체적인 것이 추상화된 것에 의존해야 한다.
    그림 5


  • 의존성 부패가 발생한 코드는 class들이 전부 엉켜있어 재사용이 불가능하다. (가독성, 유지보수성 모두 떨어짐)
  • 목 객체로 대체될 수도 없으며, 단위 테스트도 불가능한 경우가 대부분이다.


의존성이 역전된 코드

class PaymentController {
    @RequestMapping(value = "/payments", method = RequestMethod.POST)
    public void pay(PaymentRequest req) {
        final PaymentService paymentService = paymentFactory.getType(req.getType());
        paymentService.pay(req);
    }
}

public interface PaymentService {
    void pay(PaymentRequest req);
}

public class ShinhanPaymentService implements PaymentService {
    @Override
    public void pay(PaymentRequest req) {
        shinhanApi.pay(req);
    }
}

” 또한 확장에는 열려있고 변경에는 닫혀있는 ‘OCP’ 를 준수하게 된다. “