정상에서 IT를 외치다

[디자인패턴] IoC, DI, DIP 용어 정리 본문

디자인패턴

[디자인패턴] IoC, DI, DIP 용어 정리

Black-Jin 2019. 4. 30. 11:50
반응형

안녕하세요. 블랙진입니다.


디자인패턴을 공부하다가 IoC, DI와 DIP에 관해 개념이 헷갈려 제 나름대로 정리 해봤습니다. 



IoC (Inversion of Control)


제어 반전제어의 반전역제어는 프로그래머가 작성한 프로그램이 재사용 라이브러리의 흐름 제어를 받게 되는 소프트웨어 디자인 패턴을 말한다. 줄여서 IoC(Inversion of Control)이라고 부른다. 전통적인 프로그래밍에서 흐름은 프로그래머가 작성한 프로그램이 외부 라이브러리의 코드를 호출해 이용한다. 하지만 제어 반전이 적용된 구조에서는 외부 라이브러리의 코드가 프로그래머가 작성한 코드를 호출한다. 설계 목적상 제어 반전의 목적은 다음과 같다:

  • 작업을 구현하는 방식과 작업 수행 자체를 분리한다.
  • 모듈을 제작할 때, 모듈과 외부 프로그램의 결합에 대해 고민할 필요 없이 모듈의 목적에 집중할 수 있다.
  • 다른 시스템이 어떻게 동작할지에 대해 고민할 필요 없이, 미리 정해진 협약대로만 동작하게 하면 된다.
  • 모듈을 바꾸어도 다른 시스템에 부작용을 일으키지 않는다.

- 위키백과


IoC 개념은 프레임워크와 라이브러리 사용차이에서 살펴 볼 수 있습니다. 라이브러리(ex. ConstaintLayout)를 사용하면 필요한 구성요소를 직접 가져와서 쓰면 되지만 프레임워크(ex. Android Studio)는 규칙에 따라 구성요소를 등록하면, 프레임워크에서 이 구성요소를 가져다 써야 합니다. 이 관계에서 제어가 역전되었다고 표현하는데 같은 맥락에서 팩토리 메소드와 템플리 메소드 패턴 역시 IoC를 설명하는 예 중 하나입니다.


즉 저희가 라이브러리를 사용할 때는 내 코드가 라이브러리 코드를 호출하지만 프레임워크를 사용할 때는 프레임워크가 내 코드를 호출합니다. 이렇게 제어가 역전되었다고 하는것이 소프트웨어 용어인 IoC 입니다.


코드에서 보게되면 IoC는 클래스의 생성자를 직접 호출해 인스턴스를 생성하는 방법입니다. 생성자를 일일이 호출하는 것이 번거롭다면, 이 작업을 프레임워크(ex. IoC 컨테이너)에 맡길 수 있습니다. IoC는 누가 작업을 수행하는냐에 관한 얘기입니다.




DI (Dependency Injection)


의존성 주입(Dependency InjectionDI)은 프로그래밍에서 구성요소간의 의존 관계가 소스코드 내부가 아닌 외부의 설정파일 등을 통해 정의되게 하는 디자인 패턴 중의 하나이다.

- 위키백과


DI를 이야기 할 때 Martin  Fowler의 글에서 그 배경을 알 수 있습니다. 


As a result I think we need a more specific name for this pattern. Inversion of Control is too generic a term, and thus people find it confusing. As a result with a lot of discussion with various IoC advocates we settled on the name Dependency Injection.


IoC는 너무 일반적인 용어라 사람들을 헷갈리게 한다. 이에 우리는 DI를 정의하게 되었다. 즉 IoC의 한 형태가 DI(Dependency Injection) 라고 하는것 같습니다.


제어의 역전을 위한 방법에는 다양하게 있습니다. 그중 DI 에 관한 위키백과에서는 3가지 패턴을 제시해 줬습니다.


마틴 파울러는 다음과 같은 세 가지의 의존성 주입 패턴을 제시하였다.

  • 생성자 주입 : 필요한 의존성을 모두 포함하는 클래스의 생성자를 만들고 그 생성자를 통해 의존성을 주입한다.
  • 세터(Setter)를 통한 주입 : 의존성을 입력받는 세터(Setter) 메소드를 만들고 이를 통해 의존성을 주입한다.
  • 인터페이스(Interface)를 통한 주입 : 의존성을 주입하는 함수를 포함한 인터페이스를 작성하고 이 인터페이스를 구현하도록 함으로써 실행시에 이를 통하여 의존성을 주입한다.




DIP (Dependency Inversion principle)


객체 지향 프로그래밍에서 의존 관계 역전 원칙은 소프트웨어 모듈들을 분리하는 특정 형식을 지칭한다. 이 원칙을 따르면, 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존 관계를 반전(역전)시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립되게 할 수 있다. 이 원칙은 다음과 같은 내용을 담고 있다. [1]

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

이 원칙은 '상위와 하위 객체 모두가 동일한 추상화에 의존해야 한다'는 객체 지향적 설계의 대원칙을 제공한다. [2]

- 위키백과


DI는 DIP를 구현하는 기법중 하나라고 생각하면 될 것 같습니다. 인수를 취하는 것이 DI 개념의 대부분이며 더 나아가 추상화를 해치지 않고 의존성을 넘겨주어야 합니다. 여기서 DIP는 더 중요한 모듈이 덜 중요한 모듈에 의존하면 안되게 다형성을 적극적으로 활용하며 모듈의 재사용성이 높이도록 하는 원칙이라고 생각됩니다.


굳이 정리하자면 DI는 의존성을 어떻게 가질 것인가? DIP는 실체에 의존할 것인가, 추상화에 의존할 것인가의 문제라고 생각됩니다.




정리


정의하기 애매한 용어를 굳이 제 시각에서 정리 해보았습니다.


1. IoC는 제어의 역전에 관한 소프트웨어 용어로 누가 작업을 수행하느냐가 포인트입니다.


2. DI는 DIP를 구현하는 기법중 하나로 의존성을 어떻게 주입 할 것인가가 포인트입니다.


3. DIP는 더 중요한 모듈이 덜 중요한 모듈에 의존하면 안되며 추상화에 의존해야 되는 원칙으로 실체에 의존할 것인가, 추상화에 의존할 것인가가 포인트입니다. 


4. 같이 스터디를 하시는 분이 "IoC(aka. DI) > DIP > DI"  정의를 내려 주셨는데 저도 공부하면서 비슷하게 정리되었습니다.



- 소프트웨어 용어인 IoC 가 너무 일반적인 용어라 스프링에는 적절하지 않다고 생각한 Mattin Fowler는 DI 용어를 제시함.


- Robert C. Martin 이 제시한 SOLID 원칙 중 DIP를 구현하는 기법 중 하나가 DI이다. 


(A ⊂ B)


이를 집합관계로 표현하면  (DI ⊂ DIP) ⊂ (DI ⊂ IoC) 인것 같습니다. 어디까지나 다른 고수분들의 글을 읽고 제 주관적인 생각으로 정리한 내용입니다. 시간이 지나면 제 생각 또한 바뀔 수 있습니다.



<참고자료>


의존성 역전 원리 용어

DI는 IoC를 사용하지 않아도 된다. (추천)

Dependency Injection의 Dependency란 무엇인가?

반응형
Comments