Inversion of Control : 제어의 역전
프레임워크 없이 개발할 때, 객체의 생성, 설정, 초기화, 메소드 호출, 소멸을 프로그래머가 직접 관리한다. 또한 전통적인 프로그래밍에서는 외부 라이브러리를 사용할 때, 개발자가 직접 외부 라이브러리를 호출하는 방식으로 사용된다.
하지만, 프레임워크를 사용하면 객체의 생명 주기를 모두 프레임워크에 위임할 수 있다. 즉, 외부 라이브러리가 프로그래머가 작성한 코드를 호출하고 흐름을 제어한다. 이와 같이 개발자가 작성한 객체나 메서드의 제어를 개발자가 아니라 외부에 위임하는 설계 원칙을 제어의 역전이라고 한다. 즉, 프레임워크는 제어의 역전 개념이 적용된 대표적인 기술이다.
IoC의 구현 방식 중 하나로 DI(Dependency Injection)이 존재한다.
컨테이너가 lookup context를 통해 필요한 Resource나 Object를 얻는 방식이다.
JNDI 이외의 방법을 사용한다면, JNDI 관련 코드를 오브젝트 내에서 일일이 변경해주어야 한다. Lookup한 Object를 필요한 타입으로 Casting 해주어야 하며, Naming Exception을 처리하기 위한 로직이 필요하다.
Object에 lookup 코드를 사용하지 않고 컨테이너가 직접 의존 구조를 Object에 설정할 수 있도록 지정해 주는 방식이다.
Object가 컨테이너의 존재 여부를 알 필요가 없으며, Lookup과 관련된 코드가 Object 내에서 사라진다.
Setter Injection과 Constructor Injection이 존재한다.
객체의 생성, 사용, 소멸에 해당하는 라이프사이클을 담당한다. 라이프사이클을 기본으로 애플리케이션 사용에 필요한 주요 기능을 제공한다.
Spring DI Container가 관리하는 객체를 빈(Bean)이라 하고, 이 빈들의 생명주기(Life-Cycle)를 관리하는 의미로 빈팩토리(BeanFactory)라 한다.
BeanFactory에 여러가지 컨테이너 기능을 추가한 것을 Application Context라 한다.
MemberService 구현체와 AdminService 구현체를 HomeController에서 직접 생성하여 사용. MemberService 또는 AdminService가 교체되거나 내부 코드가 변경되면 HomeController까지 수정해야 할 가능성이 있다.
객체 간의 강한 결합을 다형성을 통해 결합도를 낮출 수 있다.
MemberService와 AdminService는 CommonService를 상속받는다. HomeController에서 각 서비스를 이용할 시 MemberService와 AdminService는 CommonService Type으로 사용 가능하다.
객체 간의 강한 결합을 Factory를 통해 결합도를 낮출 수 있다.
각 Service를 생성하여 반환하는 Factory를 만들었다. Service를 이용하는 쪽에서는 Interface만 알고 있으면 어떤 구현체가 어떻게 생성되는지 알 필요가 없다.
이 Factory 패턴이 적용된 것이 Container의 기능이며 이 Container의 기능을 제공해주고자 하는 것이 IoC 모듈이다.
객체 간의 강한 결합을 Assembler를 통해 결합도를 낮출 수 있다.
각 Service(객체)의 라이프사이클을 관리하는 Assembler를 사용한다. Spring Container가 외부 조립기(Assembler) 역할을 한다.