Spring Framework를 처음 접하거나 사용해 온 개발자라면, 반드시 이해하고 있어야 하는 두 가지 핵심 개념이 있습니다. 바로 Spring Bean과 IoC/DI (제어의 역전 / 의존성 주입)입니다.
현업에서 수없이 사용되는 이 개념들을 실무 중심의 예제와 함께 정리해보겠습니다.
1. Spring Bean이란?
간단히 말해 Spring Container가 생성하고 관리하는 객체를 Spring Bean이라고 합니다. 자바 클래스라도 개발자가 new로 직접 생성하면 일반 객체지만, @Component
, @Service
, @Repository
, @Controller
등의 어노테이션을 붙여 Spring이 관리하게 만들면 그것은 Bean이 됩니다.
@Service
public class UserService {
...
}
이렇게 등록된 Bean은 Singleton Scope이 기본이기 때문에, 한 번 생성되면 컨테이너 내에서 재사용됩니다.
2. IoC (Inversion of Control) – 제어의 역전
전통적인 자바 애플리케이션에서는 개발자가 필요한 객체를 직접 생성하고, 필요한 곳에 주입해 사용하는 방식입니다. 하지만 Spring은 이 흐름을 반대로 가져갑니다. 객체의 생성과 연결(주입)은 개발자가 아니라 프레임워크(SDI 컨테이너)가 담당합니다.
이러한 구조를 IoC – 제어의 역전이라 부릅니다. 객체 제어의 주체가 개발자가 아닌 Spring으로 “역전”된 것이죠.
3. DI (Dependency Injection) – 의존성 주입
IoC의 한 구현 방식이 바로 DI (Dependency Injection)입니다. DI는 필요한 객체를 외부(컨테이너)로부터 주입받는 방식을 의미하며, Spring은 주로 세 가지 방식으로 주입을 지원합니다.
3-1. 생성자 주입
@Service
public class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
가장 권장되는 방식으로, 불변 객체(Immutable) 설계에 유리하고 테스트가 쉬워집니다.
3-2. 필드 주입
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
}
가장 간단하지만 테스트 시 주입이 어려운 단점이 있어, 실무에서는 잘 사용하지 않습니다.
3-3. 세터 주입
@Service
public class OrderService {
private PaymentService paymentService;
@Autowired
public void setPaymentService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
주입이 선택적이거나 순환 참조가 있는 경우 유용하게 사용됩니다.
4. IoC Container – Bean 관리의 핵심
Spring에서는 모든 Bean이 IoC Container(ApplicationContext)에 의해 관리됩니다. Bean의 생성, 생명주기, 의존성 주입, 소멸까지 모두 이 컨테이너가 관장합니다.
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean(UserService.class);
Spring Boot에서는 이러한 설정이 자동으로 구성되며, 대부분의 경우 직접 ApplicationContext를 다룰 필요는 없습니다.
5. 실무에서의 IoC/DI 활용 전략
- 생성자 주입을 기본 원칙으로 사용한다
- 빈의 책임이 명확하도록 단일 책임 원칙(SRP)을 지킨다
- 테스트 코드 작성이 쉬워진다 (Mock 주입 용이)
- 객체 간 결합도를 낮추고 유연한 구조 설계가 가능하다
6. 마무리
Spring에서 Bean과 IoC/DI는 단순한 구조 개념을 넘어, 전체 애플리케이션의 설계 철학이자 유지보수성을 좌우하는 기초 체계입니다. 처음엔 다소 개념이 어렵게 느껴질 수 있지만, 이해하고 나면 객체 관리의 대부분을 프레임워크에 맡기면서 더 유연하고 테스트 가능한 코드를 작성할 수 있게 됩니다.
'개발 > JAVA' 카테고리의 다른 글
@Autowired vs 생성자 주입 – 스프링 DI에서 가장 많이 묻는 질문 (0) | 2025.09.21 |
---|---|
@Component, @Service, @Repository 차이 – 스프링 개발자를 위한 실전 가이드 (0) | 2025.09.20 |
@RestController vs @Controller – Spring MVC에서의 핵심 차이점 정리 (0) | 2025.09.18 |
Spring에서 Controller, Service, Repository 계층 구조란? (0) | 2025.09.17 |
Spring Boot로 Hello World REST API 만들기 (0) | 2025.09.16 |