Spring의 IoC(제어의 역전)와 DI(의존성 주입) 이해하기
Spring 프레임워크에서 가장 중요한 개념 중 하나는 IoC(제어의 역전, Inversion of Control)와 DI(의존성 주입, Dependency Injection)입니다. 이 두 가지 개념은 Spring이 객체들 간의 의존성을 관리하는 방식에 대해 설명하며, 객체지향 프로그래밍의 중요한 원칙 중 하나인 유연한 코드 구조를 만들기 위해 사용됩니다.
1. IoC (제어의 역전)
IoC는 제어 흐름을 개발자가 아닌 프레임워크가 담당하는 것을 의미합니다. 전통적인 애플리케이션에서는 객체를 개발자가 직접 생성하고, 객체 간의 의존성을 개발자가 직접 관리합니다. 하지만 IoC를 도입하면 객체의 생성과 관리, 의존성 주입 등을 개발자가 아닌 컨테이너(Spring IoC Container)가 처리합니다.
쉽게 말해, 객체의 생명 주기와 의존성 관리를 프레임워크에 위임하는 것입니다. 개발자는 객체를 만들고 관리하는 부담을 덜고, 오직 객체의 비즈니스 로직에 집중할 수 있습니다.
예시:
public class OrderService {
private OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public void placeOrder(Order order) {
orderRepository.save(order);
}
}
위의 OrderService
클래스에서 OrderRepository
는 반드시 필요하지만, IoC 컨테이너를 사용하면 OrderRepository
객체를 직접 생성하지 않아도 됩니다. Spring이 대신 이 객체를 관리하고 주입해줍니다.
2. DI (의존성 주입)
IoC가 제어권을 프레임워크에 넘기는 개념이라면, DI는 그 제어권을 바탕으로 의존성을 주입하는 구체적인 방법입니다. DI는 객체가 필요로 하는 의존성을 외부에서 주입받는 방식입니다. Spring에서는 의존성을 생성자 주입, 필드 주입, 그리고 세터 주입 방식으로 관리합니다.
생성자 주입 (Constructor Injection)
의존성을 생성자를 통해 주입하는 방식입니다. 객체 생성 시점에 필요한 모든 의존성을 주입하므로 불변 객체를 만들기에 적합합니다.
public class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
}
세터 주입 (Setter Injection)
필요한 의존성을 세터 메서드를 통해 주입하는 방식입니다. 특정 시점에서 의존성을 변경하거나 선택적으로 주입해야 할 때 유용합니다.
public class OrderService {
private OrderRepository orderRepository;
public void setOrderRepository(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
}
필드 주입 (Field Injection)
필드를 통해 직접 의존성을 주입하는 방식입니다. Spring에서는 주로 @Autowired
를 사용하여 필드에 의존성을 주입할 수 있습니다. 하지만 테스트나 유지보수 측면에서 권장되지 않기 때문에 가급적 생성자 주입을 사용하는 것이 좋습니다.
public class OrderService {
@Autowired
private OrderRepository orderRepository;
}
3. IoC와 DI의 이점
Spring의 IoC와 DI를 사용하면 다음과 같은 이점을 얻을 수 있습니다.
- 유연성: 객체 간의 결합도를 낮춰 더 유연한 코드를 작성할 수 있습니다. 이를 통해 객체를 쉽게 교체하거나 수정할 수 있습니다.
- 재사용성: 의존성 관리가 효율적이므로 코드를 재사용하거나, 새로운 기능을 추가하기가 쉽습니다.
- 테스트 용이성: 의존성 주입을 통해 각 객체가 외부에서 주입되므로 단위 테스트가 더 쉬워집니다. 테스트할 때 Mock 객체나 대체 구현을 쉽게 주입할 수 있습니다.
4. Spring에서 IoC와 DI 사용 예시
Spring에서 IoC 컨테이너는 @Component
와 @Autowired
같은 어노테이션을 통해 객체를 관리하고 주입합니다. 예를 들어, Spring에서 자동으로 객체를 관리하려면 다음과 같이 작성할 수 있습니다.
@Component
public class OrderRepository {
// 데이터베이스 접근 로직
}
@Service
public class OrderService {
private final OrderRepository orderRepository;
@Autowired
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public void placeOrder(Order order) {
orderRepository.save(order);
}
}
위 코드에서는 OrderRepository
가 @Component
로 등록되어 IoC 컨테이너에 의해 관리되고, OrderService
에서 생성자 주입을 통해 의존성을 주입받습니다.
결론
Spring의 IoC와 DI는 객체 간의 의존성을 효율적으로 관리함으로써 개발자가 더 유연하고 유지보수하기 쉬운 코드를 작성할 수 있도록 돕습니다. Spring 프레임워크는 이 개념들을 기반으로, 대규모 애플리케이션에서도 관리와 확장이 용이한 구조를 제공합니다.
Spring을 처음 접하신다면, IoC와 DI 개념을 확실히 이해하는 것이 중요하며, 이를 통해 객체지향 프로그래밍의 진정한 가치를 느낄 수 있을 것입니다.
'TIL > 스파르타 TIL' 카테고리의 다른 글
[내일배움캠프] CH 3 일정 관리 앱 Develop 리팩토링 (0) | 2024.10.28 |
---|---|
[내일배움캠프] CH 3 일정 관리 앱 Develop (0) | 2024.10.13 |
[내일배움캠프] Spring 1차 숙제 (튜터님께 받은 피드백) (0) | 2024.10.08 |
[내일배움캠프] 본캠프 TIL Spring 입문(3) (0) | 2024.09.28 |
[내일배움캠프] 본캠프 TIL Spring 입문(2) (0) | 2024.09.28 |