728x90
IoC(Inversion of Contorl) - 제어의 역전
IoC란?
객체의 생성 및 제어권을 개발자가 아닌 스프링 컨테이너가 관리하는 프로그래밍 원칙입니다.
일반적으로 객체 생성과 의존성 관리는 개발자가 직접 수행하지만, IoC에서는 스프링이 이를 대신 관리합니다.
IoC의 핵심
전통적인 개발 방식에는 객체가 다른 객체를 직접 생성하고 호출합니다.
이는 객체 간 강한 결합도를 만들어 유지보수와 확장에 어려움을 초래합니다.
IoC는 이 제어권을 스프링 같은 프레임워크로 넘김으로써 객체 간 결합도를 낮추고 유연성을 제공합니다.
전통적인 방식(제어권이 개발자에게 있음)
class MyService {
private val repository = MyRepository() // 직접 객체 생성
fun performTask() {
repsotiroy.doSometing()
}
}
- 문제점:
- MyService가 MyRepository에 강하게 결합되어 있어 대체하거나 테스트하기 어려움.
- 객체 생성 및 관리 책임이 MyService에 있어 코드가 복잡해짐
IoC를 적용한 방식(제어권이 컨테이너에 있음)
@Component
class MyRespository
@Service
class MyService(val repository: MyRepository) {
fun performTask() {
repository.doSomething()
}
}
- 동작 방식:
- 스프링이 MyRepository와 MyService객체를 생성하고, MyService에 MyRepository를 주입
- 개발자는 객체 생성 및 주입 로직을 작성할 필요가 없음
IoC의 구현 방식
스프링에서 IoC는 주로 의존성 주입(DI)을 통해 구현됩니다.
IoC 컨테이너는 애플리케이션 시작 시 객체를 생성하고 관리하며, 필요한 경우 객체를 다른 객체에 주입합니다.
- Bean관리
- 스프링 IoC 컨테이너는 객체를 Bean으로 관리합니다.
- @Component, @Service, @Repository, @Controller 같은 어노테이션을 사용해 Bean으로 등록합니다.
- Bean 등록 및 주입
- @Autowired 또는 생성자 주입 방식으로 Bean간 의존성을 연결합니다.
- 의존성은 런타임에 스프링 컨테이너가 자동으로 처리합니다.
IoC의 주요 이점
- 결합도 낮춤
- 객체가 자신이 사용할 객체를 직접 생성하지 않으므로 서로 강하게 결합되지 않습니다.
- 예를 들어 MyRepository를 MockRepository로 쉽게 대체 가능합니다.
- 유연성 및 테스트 용이성
- 객체 생성 및 주입 로직이 스프링 컨테이너에 있으므로 개발자는 비즈니스 로직에만 집중 가능합니다.
- 유닛 테스트 시 Mock 객체를 쉽게 주입할 수 있습니다.
- 코드 재사용성 향상
- 의존성 주입을 통해 동일한 클래스가 다른 설정과 객체를 주입받아 다양한 용도로 재사용 가능합니다.
- 관심사 분리
- 객체 생성 및 라이프사이클 관리와 비즈니스 로직을 분리합니다.
IoC 컨테이너 동작 과정
스프링 IoC 컨테이너는 다음과 같은 과정을 거쳐 객체를 관리합니다.
- 설정 일기
- 설정 파일(XML or Java Config)이나 어노테이션을 읽어 어떤 Bean을 생성할지 파악합니다.
- Bean 생성
- 설정된 클래스의 객체를 생성하고, 의존성을 주입합니다.
- Bean 관리
- 생성된 Bean을 스프링 컨테이너가 관리합니다(싱글톤, 프로토타입 등 스코프에 따라 관리합니다)
- 의존성 주입
- Bean 간 의존성을 설정하고 필요한 경우 런타임에 주입합니다.
IoC 컨테이너 작동 예제
1. Configuration으로 Bean 등록
@Configuration
class AppConfig {
@Bean
fun myRepository() = MyRepository()
@Bean
fun myService(repository: MyRepository) = MyService(repository)
}
2. IoC 컨테이너 활용
fun main() {
val context = AnnotationConfigApplicationContext(AppConfig::class.java)
val service = context.getBean(MyService::class.java)
service.performTask()
}
- AnnotationConfigApplicationContext는 IoC 컨테이너 역할을 수행
- MyService를 요청하면 IoC 컨테이너가 MyRepository를 주입해 생성된 객체를 반환
IoC 쉽게 알아보기
IoC를 비유해서 알아보자면
- 전통적인 방식: 주방에서 요리사가 재료부터 모든 요리를 직접 준비
- IoC 방식: 요리사는 필요한 재료를 요리사 대신 준비해 주는 보조 셰프에게 요청, 보조 셰프는 주방(컨테이너)에서 재료를 준비해 요리사에게 넘겨줌
이렇게 요리사는 요리에만 집중할 수 있는 환경을 제공하는 것이 IoC의 핵심입니다.
728x90
'Kotlin' 카테고리의 다른 글
Spring - Servlet(서블릿)이란? (0) | 2024.12.24 |
---|---|
AOP (Aspect-Oriented Programming) - 관점 지향 프로그래밍 (0) | 2024.12.23 |
DI (Dependency Injection) - 의존성 주입 (0) | 2024.12.20 |
Kotlin Class 알아보기 1(Class, Data Class, Enum Class, Abstract Class) (1) | 2024.12.19 |