02.12 DI / IoC / Bean
2023. 2. 12. 19:50ㆍ개발일지
IoC (Inversion of Control) : 제어의 역전
- 스프링 애플리케이션에서는 오브젝트(Bean)의 생성과 의존 관계 설정, 사용, 제거 등의 작업을 애플리케이션 코드 대신 스프링 컨테이너가 담당하며, 이를 스프링 컨테이너가 코드 대신 오브젝트에 대한 제어권을 갖고 있다고 해서 IoC라고 부릅니다. (스프링 컨테이너를 IoC컨테이너라고 부릅니다.)
IoC 컨테이너
- Spring에서 IoC를 담당하는 컨테이너를 빈 팩토리, DI 컨테이너, 애플리케이션 컨텍스트라고 부르며, 오브젝트의 생성과 오브젝트 사이의 런타임 관계를 설정하는 DI관점으로 보면, 컨테이너를 빈 팩토리 또는 DI 컨테이너라고 부릅니다. 그러나 스프링 컨테이너는 단순한 DI작업보다 더 많은 일을 하는데, DI를 위한 빈 팩토리에 여러 가지 기능을 추가한 것을 애플리케이션 컨텍스트라고 합니다.
(애플리케이션 컨텍스트는 그 자체로 IoC와 DI 그 이상의 기능을 가졌다고 보면 됩니다.)
애플리케이션 컨텍스트
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory,
HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher,
ResourcePatternResolver {
- 애플리케이션 컨텍스트는 빈 팩토리 기능을 모두 상속 받아서 제공하며, 인터페이스에서 extends한 인터페이스들은 모두 빈 팩토리 인터페이스의 서브 인터페이스이며, 빈 팩토리에게 없는 추가 기능을 가지고 있습니다. 따라서, 애플리케이션은 이를 혼합하여 다음과 같은 기능을 제공합니다.
- 메시지 소스를 활용한 국제화 기능
- 한국에서 들어오면 한국어로, 영어권에서 들어오면 영어로 출력
- 환경변수
- 로컬, 개발, 운영 등을 구분해서 처리
- 애플리케이션 이벤트
- 이벤트를 발행하고 구독하는 모델을 편리하게 지원
- 편리한 리소스 조회
- 파일, 클래스 패스, 외부 등에서 리소스를 편리하게 조회
- 메시지 소스를 활용한 국제화 기능
DI (의존 관계 주입)
의존관계 (Dependency)
- 'A가 B를 의존한다'는 굉장히 추상적인 표현이지만, 토비의 스프링에서는 '의존 대상 B가 변하면, 그것이 A에 영향을 미친다'고 하며, B의 기능이 추가되거나 변경되면 그 영향이 A에 미치는 것입니다.
// ex(코드)
class BurgerChef {
private HamBurgerRecipe hamBurgerRecipe;
public BurgerChef() {
hamBurgerRecipe = new HamBurgerRecipe();
}
}
- ex1(코드1) : 햄버거 레시피가 변화게 되었을 때, 변화된 레시피에 따라서 BurgerChef 클래스를 수정해야 합니다. 레시피의 변화가 요리사의 행위에 영향을 미쳤기 때문에 요리사는 레시피에 의존한다고 말할 수 있습니다.
- 의존관계 ex1(코드1)를 보면, BurgerChef는 HamburgerPecipe만 의존할 수 있는 구조로 되어있습니다. 더 다양한 햄버거 레시피를 의존할 수 있게 구현하려면 인터페이스로 추상화해야 합니다.
class BurgerChef {
private BurgerRecipe burgerRecipe;
public BurgerChef() {
burgerRecipe = new HamBurgerRecipe();
//burgerRecipe = new CheeseBurgerRecipe();
//burgerRecipe = new ChickenBurgerRecipe();
}
}
interface BugerRecipe {
newBurger();
}
class HamBurgerRecipe implements BurgerRecipe {
public Burger newBurger() {
return new HamBerger();
}
}
- ex2(코드2) : 다양한 버거 레시피에 의존할 수 있는 BurgerChef가 되었습니다. 이처럼 의존 관계를 인터페이스로 추상화하게 되면, 더 다양한 의존 관계를 맺을 수 있고, 실제 구현 클래스와의 관계가 느슨해지면서 결합도가 낮아집니다.
DI (의존 관계 주입)
- ex(코드) 구현에서는 BurgerChef 내부적으로 의존 관계인 BurgerRecipe가 어떤 값을 가질지 직접 정하고 있습니다. 이때 DI는 어떤 햄버거 레시피를 만들 지는 버거 가게 사장님이 정하는 상황이라 할 수 있습니다. 즉, BurgerChef가 의존하고 있는 BurgerRecipe를 외부(사장님)에서 결정하고 주입하는 것입니다.
class BurgerChef {
private BurgerRecipe burgerRecipe;
public BurgerChef(BurgerRecipe bugerRecipe) {
this.burgerRecipe = bugerRecipe;
}
}
//의존관계를 외부에서 주입 -> DI
new BurgerChef(new HamBurgerRecipe());
new BurgerChef(new CheeseBurgerRecipe());
new BurgerChef(new ChickenBurgerRecipe());
- 위에처럼 그 의존 관계를 외부에서 결정하는 것을 DI(의존 관계 주입)라 합니다.
DI와 IoC의 차이
- DI는 의존관계를 어떻게 가질 것인가에 대한 문제고, IoC는 누가 소프트웨어의 제어권을 갖고 있느냐의 문제입니다. IoC 컨테이너가 빈을 생성할 때 빈들간의 의존관계를 DI를 통해 해결합니다. DI는 IoC 사용을 필수로 요구하지 않는다는 점을 주의해야 합니다.
Bean(Spring Bean)
- Spring IoC 컨테이너가 관리하는 자바 객체를 빈(Bean)이라고 부릅니다. 자바 프로그래밍에서는 Class를 생성하고 new 키워드를 이용항여 객체를 생성한 후 사용했습니다. 하지만 Spring에서는 직접 new 키워드를 이용하여 객체를 생성하는게 아닌 Spring에 의하여 관리당하는 자바 객체를 사용합니다. 이렇게 Spring에 의해 생성되고 관리되는 자바 객체를 Bean이라고 합니다.
'개발일지' 카테고리의 다른 글
02.16 연관관계 (0) | 2023.02.16 |
---|---|
02.13 @Valid와 @Validated의 차이점 (0) | 2023.02.13 |
02.11 TIL (0) | 2023.02.11 |
02.11 Spring Boot Validation 어노테이션(@) 정리 (0) | 2023.02.11 |
02.11 @PathVariable (0) | 2023.02.11 |