토비의 스프링 책을 학습하며 IoC(Inversion of Control)에 대한 개념이 완전히 이해가 안되는 것 같습니다. 예전에 잠시 읽었던 ‘스프링 입문을 위한 자바 객체 지향의 원리와 이해’ (김종민 저) 책을 다시 꺼내서 자동차와 바퀴 예시를 다시 읽어봅니다. 토비의 스프링에서 제시하는 여러 개념들을 위 예제에 빗대어 다시 정리해 보니 IoC 개념이 더 선명하게 이해가 되는 것 같습니다.
표준화된 자동차 바퀴가 없다고 가정해 봅시다. 자동차(전체)는 바퀴(부분)를 사용하는데 바퀴가 임의로 변경되면 바퀴와 인터페이스되는 자동차 차체가 바뀌어야 합니다. 전체인 자동차가 부분적인 바퀴에게 의존함으로 생기는 문제입니다. 바퀴가 바뀐 건데 자동차 차체가 바뀌어야(응집성이 낮고) 하고, 그 변경으로 인한 다른 부분으로의 영향(높은 결합도)도 함께 생각해야 합니다. 결론적으로 바퀴 하나 바꾸는데 바퀴만 바꿀 수 없고 자동차 전체에 변화가 폭 넓게 영향을 미치게 됩니다.
IoC 개념을 도입해 봅시다. 자동차 제조사는 바퀴의 표준화된 규격(인터페이스)을 정하고 단지 그 인터페이스를 사용하도록 자동차를 구현할 수 있습니다. 기존에는 내가 아닌 외부 바퀴 제조사에서 임의로 정한 바퀴 규격을 알고 그것에 의존해서 구현해야 했지만 이제 어떤 바퀴 제조사가 있는지에 관심을 가지지 않아도 됩니다. 반면에 바퀴 제조사는 이제 바퀴를 마음대로 구현할 수 없습니다. 바퀴는 자동차가 정한 인터페이스에 반대로 의존하여 인터페이스에 맞는 바퀴를 구현해야 합니다. 기존에 자동차가 바퀴에 의존하던 것을 이제는 바퀴가 자동차에서 정한 인터페이스에 의존하는 제어의 역전(의존관계의 역전)이 일어납니다.
이렇게 되면 실제 자동차에 어떤 제조사의 바퀴가 장착될지 자동차 구현이나 설계 시 고려될 필요가 없습니다. 단지 자동차에 실제로 바퀴를 장착하는 시점(런타임)에 인터페이스에 맞는 바퀴를 누군가(DI 컨테이너) 장착해 줄 수 있습니다.
디자인 패턴 관점으로 바라본다면 바퀴는 자주 변경될 것으로 예상되어 바퀴의 인터페이스를 정해 자동차인 나는 인터페이스만 알고 사용하도록 하고, 바퀴는 인터페이스에 의존하여 구현하도록 하여 다양한 바퀴(전략)를 자동차 구현의 변경 없이 상황에 따라 자유롭게 갈아끼울 수 있게 됩니다.
이로 인해 자동차는 인터페이스를 만족하는 다양한 바퀴 구현을 수용할 수 있어 외부의 확장에 개방되어 있게 되고, 반대로 바퀴 구현이 바뀌어도 자동차 구현에는 영향을 받지 않기 때문에 외부의 변경에는 닫혀 있게 됩니다.
물론 바퀴 구현이 바뀌면 자동차가 달릴 때(런타임) 실제 기능, 성능 등의 영향은 받습니다. 다만 자동차 설계, 구현 시점에 영향을 받지 않는다는 뜻입니다.
뿐만 아니라 자동차 바퀴 구현을 변경해야 한다면(인터페이스는 유지한 채) 바퀴의 변경에만 집중할 수 있습니다. 자동차는 자동차가 굴러가게 하는 본질적인 기능에 집중하고 바퀴와 규격을 맞추는 일에 최소한의 관심(인터페이스)을 가지게 되어 높은 응집도를 달성하게 됩니다. 또한 바퀴 구현의 변화에 자동차 구현이 영향을 받지 않음으로 낮은 결합도를 유지한다고 할 수 있습니다.