Spring Bean과 IoC/DI 개념 이해 – 스프링의 핵심 철학

Spring Framework를 처음 접하거나 사용해 온 개발자라면, 반드시 이해하고 있어야 하는 두 가지 핵심 개념이 있습니다. 바로 Spring BeanIoC/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는 단순한 구조 개념을 넘어, 전체 애플리케이션의 설계 철학이자 유지보수성을 좌우하는 기초 체계입니다. 처음엔 다소 개념이 어렵게 느껴질 수 있지만, 이해하고 나면 객체 관리의 대부분을 프레임워크에 맡기면서 더 유연하고 테스트 가능한 코드를 작성할 수 있게 됩니다.