IoC (Inversion of Control)
IoC(Inversion of Control)는 제어의 역전이라는 의미로, 객체의 생성, 의존성 관리, 생명주기 등을 개발자가 아닌 프레임워크나 컨테이너가 관리하도록 위임하는 디자인 원칙입니다. 이는 애플리케이션의 유연성을 높이고, 코드의 결합도를 낮추는 데 핵심적인 역할을 합니다.
IoC의 기본 개념
1. 전통적인 제어 방식:
- 개발자가 객체를 직접 생성하고, 필요한 의존성을 명시적으로 주입하며, 객체의 생명주기를 관리합니다.
1
2
3
4
5
6
7
public class ServiceA {
private ServiceB serviceB;
public ServiceA() {
this.serviceB = new ServiceB();
}
}
위와 같은 방식은 ServiceA가 ServiceB의 구체적인 구현에 강하게 의존하게 되어 결합도가 높아집니다.
2. IoC 방식:
- 객체의 생성과 의존성 주입을 컨테이너(Spring IoC 컨테이너)가 관리하며, 개발자는 필요한 객체를 사용만 합니다.
1
2
3
4
5
6
7
8
9
@Component
public class ServiceA {
private final ServiceB serviceB;
@Autowired
public ServiceA(ServiceB serviceB) {
this.serviceB = serviceB;
}
}
이 경우 객체의 생성과 의존성 관리가 컨테이너에 의해 자동으로 처리됩니다.
IoC의 핵심 원리
제어의 역전(Inversion of Control):
- 기존에는 개발자가 객체의 생성과 의존성 주입을 제어했지만, IoC에서는 이 역할을 컨테이너가 대신 수행합니다.
- 즉, 객체는 필요한 의존성을 외부에서 주입받고, 자신의 생성 및 생명주기를 스스로 관리하지 않습니다.
IoC를 가능하게 하는 메커니즘:
- Dependency Injection (DI):
- 객체 간의 의존성을 컨테이너가 주입하는 방식으로, IoC를 구현하는 대표적인 패턴입니다.
- IoC 컨테이너가 DI를 통해 객체와 의존성을 관리합니다.
- Service Locator:
- 객체가 필요한 의존성을 요청하는 방식으로, 특정 객체를 조회하여 사용하는 방식입니다.
- 그러나 Spring에서는 주로 DI 방식을 선호합니다.
Spring에서의 IoC 컨테이너
Spring IoC 컨테이너는 애플리케이션의 모든 객체를 관리하는 핵심 컴포넌트입니다. 객체를 생성하고 의존성을 주입하며, 객체의 생명주기를 제어합니다.
IoC 컨테이너의 주요 역할:
- Bean 관리:
- @Component, @Bean 등으로 정의된 객체(Bean)를 관리합니다.
- 의존성 주입:
- 객체가 필요로 하는 의존성을 자동으로 주입합니다.
- Bean의 생명주기 관리:
- 객체의 생성, 초기화, 소멸 과정을 관리합니다.
IoC 컨테이너의 구성 요소:
- BeanFactory:
- IoC 컨테이너의 가장 기본적인 인터페이스로, 객체를 생성 및 관리합니다.
- Lazy Initialization(지연 초기화)을 지원합니다.
- ApplicationContext:
- BeanFactory를 확장한 인터페이스로, 다양한 기능(국제화, 이벤트 처리, AOP 등)을 제공합니다.
- 일반적으로 ApplicationContext를 IoC 컨테이너로 사용합니다.
IoC 컨테이너 동작 과정
- Bean 정의 읽기:
- Java Config, Annotation 등으로 정의된 Bean 정보를 읽어들입니다.
- Bean 생성:
- 컨테이너가 Bean의 인스턴스를 생성합니다.
- 의존성 주입:
- 생성된 Bean의 의존성을 주입합니다.
- 초기화 및 사용:
- 초기화 메서드를 호출한 뒤 Bean을 애플리케이션에서 사용합니다.
- 소멸:
- 애플리케이션 종료 시 Bean 소멸 과정을 처리합니다.
IoC의 이점
- 결합도 감소 (Low Coupling):
- 객체 간의 의존성을 컨테이너가 관리하므로, 코드의 변경이 다른 객체에 영향을 덜 미칩니다.
- 코드의 유연성 증가:
- 객체 생성 및 의존성 관리가 외부로 위임되어, 애플리케이션 구조가 더 유연해집니다.
- 테스트 용이성:
- Mock 객체를 주입하여 단위 테스트를 손쉽게 수행할 수 있습니다.
- 코드의 재사용성 및 유지보수성 향상:
- 객체 생성과 관리를 분리하여 재사용 가능한 구조를 만듭니다.
IoC와 DI의 관계
- IoC는 객체 생성과 관리에 대한 원리입니다.
- DI는 IoC를 구현하는 구체적인 방법입니다.
- IoC 컨테이너는 DI를 통해 객체의 의존성을 관리합니다.
Java Config 기반 IoC:
1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class AppConfig {
@Bean
public ServiceA serviceA(ServiceB serviceB) {
return new ServiceA(serviceB);
}
@Bean
public ServiceB serviceB() {
return new ServiceB();
}
}
Annotation 기반 IoC:
1
2
3
4
5
6
7
8
9
@Component
public class ServiceA {
private final ServiceB serviceB;
@Autowired
public ServiceA(ServiceB serviceB) {
this.serviceB = serviceB;
}
}
IoC는 객체 관리에 대한 개발자의 부담을 줄이고, 시스템의 확장성과 유연성을 높이는 데 중요한 역할을 합니다. Spring IoC 컨테이너는 이러한 IoC의 구현을 극대화하여 엔터프라이즈 애플리케이션 개발을 효율적으로 지원합니다.
This post is licensed under CC BY 4.0 by the author.