Inversion of Control (IoC) 제어의 역전
소프트웨어 디자인 패턴 중 하나로,
소프트웨어 컴포넌트의 제어 흐름을 역전시키는 개념을 나타낸다.
기존의 프로그래밍 방식에서는 개발자가 코드 내에서 객체의 생성 및 관리를 직접 제어했지만,
IoC는 이를 역전시켜 객체의 생성 및 생명주기를 외부 컨테이너에 의해 관리하도록 하는 것을 말한다.
IoC의 주요 아이디어는 개발자가 작성한 코드가 외부 컨테이너에 의해 호출되고 관리되며,
개발자는 컨테이너가 객체를 생성하고 연결하는 방식에 대해 신경 쓸 필요가 없다는 것이다.
간단히 말해, IoC는 개발자가 코드의 제어 흐름을 직접 제어하는 것이 아니라
외부 컨테이너에게 제어의 권한을 넘겨주는 것을 의미한다.
이는 코드의 유지보수성, 테스트 용이성, 확장성 등을 향상시키는 데 도움이 된다.
대표적인 예로는 의존성 주입(Dependency Injection)이 있다.
도입효과
- 프로그램 진행 흐름과 구체적인 구현을 분리
- 개발자는 비즈니스 로직에 집중
- 구현체 사이의 변경이 용이
- 객체 간 의존성이 감소
왜 IoC
과거에는(기존에는, 현재는)
객체지향 (SOLID 지키기 위해 what to do)?
스프링의 컨테이너는 스프링 프레임워크의 핵심 기능 중 하나로, 애플리케이션의 객체를 생성하고 관리하는 역할을 한다. 이를 통해 객체의 라이프사이클을 관리하고 의존성 주입(Dependency Injection)을 지원하여 객체 간의 결합도를 낮추고 유연한 애플리케이션 개발을 가능케 한다.
스프링의 컨테이너는 객체의 생성과 관리를 담당하고,
의존성 주입은 객체 간의 의존 관계를 설정하는 것을 의미한다.
의존성 주입은 컨테이너가 객체를 생성하고 관리하는 동안에 이루어지며,
컨테이너는 객체가 요청하는 의존성을 확인하고 해당 객체에 필요한 의존성을 주입한다.
이를 통해 객체 간의 결합도를 낮추고 유연한 애플리케이션을 개발할 수 있게 된다.
따라서 컨테이너와 의존성 주입은 스프링 프레임워크의 핵심 개념 중 하나로,
함께 사용되어 객체 지향적인 애플리케이션을 구축하는 데 중요한 역할을 한다.
비유해보자면 컨테이너는 주방의 재료 담당 직원이다.
재료 담당은 요리에 필요한 재료를 관리하고, 요리를 준비할 때 필요한 도구를 제공한다.
식당은 파스타를 판매한다.
치즈를 갈기 위해서는 치즈 그라인더가 필요하다.
특별한 치즈로 만드는 파스타는 그 특별한 치즈에 따라 맛이 천차만별로 바뀐다.
그 파스타는 특별한 치즈에 의존한다.
재료 담당은 특별한 치즈가 떨어지지 않도록 공수하고,
치즈가 잘 갈리는 그라인더를 준비한다.
요리사는 준비된 치즈와 그라인더로 맛있게 파스타를 요리하기만 하면 된다.
의존성 제공(컨테이너): 재료 담당 직원
의존성(특별한 치즈): 객체나 모듈이 필요로 하는 기능이나 자원
의존성 주입받는 역할: 요리사 요리사는 컨테이너를 통해 필요한 치즈를 제공받아 파스타를 요리한다.
요리사가 필요로 하는 치즈(bean)를 직접 생성하거나 관리하지 않고,
외부에서 그라인더(컨테이너)를 통해 주입 받아 사용한다.
의존성 주입은 요리사가 재료나 도구를 담당 직원으로부터 받는 것이다.
요리사는 직접 재료를 만들고 도구를 제작할 필요 없다.
필요한 것들은 담당 직원이 준비하니, 요리만 하면 된다
의존성은
요리사가 주방의 재료 담당 직원으로부터 재료와 도구를 받는 것처럼,
소프트웨어 컴포넌트나 객체가
다른 컴포넌트나 객체로부터 필요한 기능이나 자원을 받는 것으로 생각할 수 있다.
요리사가 재료 담당 직원에게 의존하여 요리를 하는 것처럼,
소프트웨어 컴포넌트도 다른 컴포넌트에게 필요한 기능이나 자원을 제공받아야 한다.
예를 들어,
어떤 소프트웨어 모듈이 데이터베이스에 접근해야 한다면,
이 모듈은 데이터베이스 연결이나 쿼리 실행 등의 기능을 다른 모듈로부터 제공받아야 한다.
이렇게 다른 모듈로부터 필요한 기능이나 자원을 받는 것을 의존성 주입이라고 할 수 있다.
Dependency Injection 의존성 주입
의존성 주입은 의존성 역전 원칙을 구현하기 위한 디자인 패턴 중 하나이다.
("절대 IoC == DI가 아니다! (DI ⊂ IoC 라면 몰라도")
클래스가 직접 객체를 생성하고 관리하는 것이 아니라,
외부에서 해당 객체를 주입받아 사용함으로써
객체 간의 의존성을 완화시키는 방법이다.
스프링에서는 이러한 의존성 주입을 위해
컨테이너인 ApplicationContext가 객체의 생성과 라이프사이클을 관리하고,
@Autowired 어노테이션을 통해 객체를 주입한다.
개발자는 필요한 객체를 만들거나 만드는 코드를 작성한 뒤
이를 스프링의 빈으로 등록하고,
그 빈을 ApplicationContext가 관리하도록 설정한다.
그러면 스프링이 실행될 때 ApplicationContext가 객체를 생성하고 관리하며,
다른 빈에서는 @Autowired를 통해 필요한 객체를 주입받아 기능을 실행한다.
=> 코드의 결합도가 낮아지고 유연성과 확장성이 높아진다 !
요약
IoC (Inversion of Control):
기존의 프로그램에서는 개발자가 객체의 생명주기를 직접 관리하고,
외부 라이브러리를 호출할 때도 직접 관리했다.
그러나 IoC를 사용하면
프레임워크가 객체를 생성하고 관리하며,
객체 간의 제어 흐름을 프레임워크가 결정한다.
"Don't call us. We'll call you."
의존성 주입(Dependency Injection, DI):
의존성 주입은 IoC를 구현하는 디자인 패턴 중 하나다.
객체 간의 의존 관계를 설정하는 방법 중 하나로,
객체가 필요로 하는 의존 객체를 외부에서 주입받는 것을 의미한다.
객체 간의 의존성을 외부에서 주입하여,
객체가 직접 의존하는 대상을 결정하지 않게 한다.
주로 생성자 주입, setter 주입, 필드 주입 등의 방법을 사용하여 의존성을 주입한다.
이를 통해 객체 간의 결합도를 낮추고 유연한 구조를 만들어 준다.
또한 테스트 용이성을 높이고 코드의 재사용성을 증가시킨다.
[생성자 주입, setter 주입, 인터페이스 주입]
생성자 주입(Constructor Injection)
public class A {
private B b;
public A(B b) {
this.b = b;
}
}
Setter 주입(Setter Injection)
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
}
인터페이스 주입(Interface Injection)
public interface BInjection {
void inject(B b);
}
public A implements BInjection {
private B b;
@Override
public void inject(B b) {
this.b = b;
}
}
컨테이너:
스프링 컨테이너는 스프링 애플리케이션의 핵심이며, 객체(또는 빈)의 생성, 관리 및 제어를 담당한다.
이러한 역할을 수행하기 위해 스프링 컨테이너는 애플리케이션의 객체들을 생성하고, 런타임 중에 이들을 관리한다.
스프링은 IoC(Inversion of Control) 컨테이너로서, 객체의 생성과 생명주기 관리 등을 자동으로 처리하여 개발자가 직접 객체를 생성하거나 관리할 필요가 없도록 한다.
https://velog.io/@ohzzi/Spring-DIIoC-IoC-DI-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0
https://willgetjob.tistory.com/43
생성자 = 실행시점에 모든 클래스에 의존관계 주입
setter= 클래스 사용할 때 의존관계 주입
-> nullpointexception 발생할지도
factory 호출 방식
~~~ ocp
'CS' 카테고리의 다른 글
S)Spring_10_스프링 컴포넌트 스캔 Component Scan & DI 자동 주입 (0) | 2024.04.15 |
---|---|
S)Spring_09_스프링 컨테이너 (2) | 2024.04.10 |
S)DB_08_JOIN (0) | 2024.04.02 |
S)DB_08_DBCP (0) | 2024.04.02 |
S)DB_07_B tree, B+tree (1) | 2024.03.30 |