🤔 < IoC ? >

< IoC(Inversion of Control) : 제어의 역전 >

-출처: Wikipidia - 

In software engineering, inversion of control (IoC) is a programming principle. IoC inverts the flow of control as compared to traditional control flow. In IoC, custom-written portions of a computer program receive the flow of control from a generic framework. A software architecture with this design inverts control as compared to traditional procedural programming: in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls into the custom, or task-specific, code.

 

번역하자면, 

"제어의 역전(Inversion of Control, IoC)"은 소프트웨어 엔지니어링의 한 프로그래밍 원칙입니다. 전통적인 제어 흐름에 비해 IoC는 제어 흐름을 역전시킵니다. IoC에서는 사용자가 작성한 컴퓨터 프로그램의 일부가 일반적인 프레임워크로부터 제어 흐름을 받습니다. 이런 디자인을 가진 소프트웨어 아키텍처는 전통적인 절차적 프로그래밍과 비교해 제어를 역전시킵니다: 전통적인 프로그래밍에서는 프로그램의 목적을 표현하는 사용자 정의 코드가 일반적인 작업을 처리하기 위해 재사용 가능한 라이브러리를 호출하는 반면, 제어의 역전에서는 프레임워크가 특정 작업에 대한 사용자 정의 코드를 호출합니다." 으로 번역 된다.

 

더 자세히 설명하자면, 일반적은 프로그래밍에서는 프로그램이 어떠한 작업을 실행할지 결정하고 그 작업을 수행하는 코드를 "직접" 호출한다. 예를 들어, 프로그램이 DataBase에서 정보를 가져오는 작업을 수행해야 한다면, 그 작업을 수행하는 코드를 "직접" 호출하고 실행 한다.

 

허나 IoC를 사용하는 경우, 이러한 '제어'가 역전된다. 프로그램 자체가 더 이상 어떤 코드가 언제 실행될지 결정하지 않고, Freamwork가 그 역할을 담당해버린다. 프로그램은 필요한 기능을 수행하는 코드를 작성하고, 실행될지는 FrameWork가 결정한다. 

 

이로 인해 코드의 결합도가 낮아져 코드의 재사용성이 높아지며, 개발자는 프로그램의 전반적 흐름과 동작에 대해 신경 쓸 필요 없이 특정 작업을 수행하는 코드에 집중할 수 있게 된다. 

 


💻 < 코드 설명 >

A Class에서 B를 Field로 가지고 있고

생성자 내부에서 직접 생성해 필드를 초기화 하고 있다.

이러한 코드를 객체 생명주기를 직접 제어하는 코드라고 말할 수 있다.

제어란, 관리라는 말로도 대신 할 수 있다.

 


🤔 < 역전 ?>

앞서 본 것과 같은 A 클래스가 있다.

하지만 이 코드에서는 외부로 부터 B를 인자로 받아 초기화하고 있다.

이렇게 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 "제어를 역전시켰다"고 말할 수 있다.


🌳 < IoC가 필요한 이유> 

간단한 예시를 들어보겠다

배고픈 윤태영은 점심으로 서브웨이를 먹으러 갔다.

이탈리안 비엠티를 주문하자 서브웨이는 기본 레시피대로 만들기 시작한다. 하지만 윤태영은 나오는 재료를 변경하고 싶었다고 말을 한다. 서브웨이는 이탈리안 비엠티 레시피가 아니라며 당황을 한다.

(02:11)

앞서 본 얘기를 코드로 살펴보면 빵,치즈,소스를 모두 ItalianBMT Code 내에서 생성해 초기화 하는 것을 알 수 있다.

즉, 각 재료들에 대한 제어권이 객체 내부에 있는 것이다.

만약 윤태영과 같은 변경이 생기게 되면 ItalianBMT 에도 큰 변경이 필요해 진다.

< 이런 문제를 어떻게 해결할까? >

🔥 < IOC가 적용된 예시 >

태영이 요구한 재료로 주문하였고, 요구한 재료로 구성된 ItalianBMT를 만들어 주었다.

(02:59)

 

위의 예시를 코드로 살펴보면

ItalianBMT는 화이트,파마산 오레가노 빵등 어떠한 빵 종류도 받을 수 있는 Bread라는 인터페이스를 인자로 받고 있다.

이와 같이 Chesses,Sauce도 종류에 상관없이 인자로 받아, 필드를 초기화 할 수 있도록 되어 있다.

 

결과적으로 객체 내부에서 재료의 종류를 제거해 변경에 자유롭지 못하다는 코드가 외부에서 제어를 받으면서 변경에 자유로워 진것을 알 수 있다.

 

IoC 관점에서 다시 요약하자면 재료에 대한 제어권을 기존에는 이탈리안비엠티가 가졌었지만

변경된 코드에서는 태영이 가지게 된 것.

 

IoC 프로그램 모델은 "역할과 책임의 분리"라는 내용과 관련이 있다.

(03:42)

이렇게 역할과 책임을 분리해 객체의 응집도를 높이고

객체간 결합도를 낮추면서 앞서 본 예시와 같이 변경에 유연한 코드를 작성할 수 있는 구조가 될 수 있다.

IoC 설명을 찾아보면 할리우드 법칙을 본 적이 있을텐데

 

(04:09)

Don't call us, we'll call you

즉, "우리에게 연락하지 마시오,알아서 불러 줄 테니" 라는 말이다.

우리가 어떤 것을 주도하여 호출하는 것이 아니라, 주도권은 빼앗기고 호출 당하기를 기다리는 모습이 IoC와 비슷해서 Gof 디자인 패턴에서는 Holywood principle이라고 불리기도 한다.

 

할리우드 원칙에서는 DIP에 대한 설명도 있는데

실제로 DIP와 IOC는 함께 사용되길 권장 받는 관계 이기도 하다. 그만큼 헷갈리기 쉬울 수도 있어

 

DIP에 대해서도 이야기를 해보겠다.

 

🔥 < DIP (Dependency Inversion Principle) >

(04:56)

DIP란 Dependency Inversion Principle의 약자로서 번역을 하면 "의존 역전 원칙" 이라는 뜻을 가지고 있다.

DIP는 상위 레벨의 모듈은 절대 하위 레벨 모듈에 의존하지 않는다. 둘 다 추상화에 의존해야 한다.

🤔 그렇다면 상위 레벨 모듈은 무엇이며 하위 레벨 모듈은 무엇이며 추상화에 의존한다는 말은 무엇일까?

쉬운 예시를 들어보겠다.

앞서 본 코드에서 WhiteBread라는 Field를 포함하는 ItalianBTM Class를 High Level Module, Field로 포함되는 WhiteBread를 Low Level Module이라고 볼 수 있다.

ItalianBTM에서는 기본 빵이 WhiteBread이다.

ItalianBTM라는 고수준 모듈에서 저수준 모듈인 WhiteBread에 의존하고 있었던 것이다.

하지만 태영이 파마산오레가노로 변경해달라고 한다면 화이트는 의존하고 있던 이탈리안비엠티 코드에서도 연쇄적으로 영향이 일어난다. 이 문제를 DI(Dependency Injection)를 이용해 추상화로 해결해 보겠다.

 


 

 

(06:44)

위의 그림을 살펴보면, High Level Module인  ItalianBTM는 더 이상 Low Level Module인 WhiteBread에 의존하고 있지 않고, Bread Interface에 의존하고 있다.

Low Level Module인 Bread 종류들도 이 Bread Interface에 의존하고 있다.

즉,모두 추상화에 의존하고 있는 것이다.

여기서 "Bread"는 High Level Module인 ItalianBMT 입장에서 만들어졌고

따라서 상황이 역전되어 Low Level Module이 High Level Module에 의존하게 된 것을 알 수 있다.

 

이렇게 의존 방향이 역전되는 것을 의존 역전(DI) 이라고 할 수 있다.

 

위의 코드도 High Level Module인 ItalianBMT가 Low Level Module인 재료의 종류에 의존하지 않으면서

Cheese, Bread, Sauce Interface 재료들에 의존하며 이미 DI가 적용되어 있던 것이다. 

 

IoC와 DIP는 Class간 결합을 느슨히 하고자 하는 같은 목적이 있다. 

두 원칙은 하나의 Class의 변경이 다른 Class들에게 전이되는 것을 최소화함으로써, App을 지속 가능하게 하며,확장성 있게 만들고자 한다. 그래서 시너지가 높은 DIP,IoC를 함께 사용하도록 강력하게 권장하고 있다.

 

 

 

 

 

참고: https://www.youtube.com/watch?v=8lp_nHicYd4

'스프링부트' 카테고리의 다른 글

Member class 고밀도 상세 분석  (0) 2023.04.06
ApplicationException code analysis  (0) 2023.04.05
Container in springboot  (0) 2023.04.04
ResponseEntity 고찰  (0) 2023.04.04
Model이라는 데이터 전달자  (0) 2023.04.04

+ Recent posts