[본캠프] IoC컨테이너,Bean

윤영범·2026년 4월 15일
post-thumbnail

1. 왜 Spring에서 IoC와 DI가 중요한가

Spring을 배우기 전에는 보통 객체를 직접 생성해서 사용했다
예를 들어 서비스 클래스에서 필요한 저장소 객체를 직접 new로 생성하는 방식이다

public class ScheduleService {
    private ScheduleRepository scheduleRepository = new ScheduleRepository();
}

이 방식은 처음에는 단순해 보이지만 문제가 있다
서비스가 저장소를 직접 생성하면 두 클래스가 강하게 연결되어 높은 결합도를 가지게된다
나중에 저장소 구현이 바뀌거나 테스트를 위해 다른 객체로 교체하고 싶어도 코드를 직접 수정해야 한다
즉, 객체 생성과 사용의 책임이 한 클래스 안에 같이 들어 있어서 유연성이 떨어진다

Spring은 이런 문제를 해결하기 위해 IoC(Inversion of Control) 와 DI(Dependency Injection) 를 사용한다
이 두 개념은 Spring 프레임워크의 핵심이라고 볼 수 있다

2. IoC(Inversion of Control, 제어의 역전)

IoC는 말 그대로 제어의 흐름이 뒤집힌 것이다
기존에는 개발자가 객체를 직접 생성하고, 필요한 시점에 직접 호출하고, 생명주기를 관리했다
하지만 Spring에서는 이 제어권을 개발자가 아니라 Spring 컨테이너가 가져간다

즉, 객체를 언제 만들지, 어떤 객체를 사용할지, 어떤 객체를 서로 연결할지에 대한 제어권이
개발자 코드에서 Spring으로 넘어간다

핵심 의미

정리하면 IoC는 다음 의미를 가진다

  • 객체 생성의 주도권이 개발자에게 있지 않다
  • 객체의 생명주기를 Spring이 관리한다
  • 객체 간의 관계 설정도 Spring이 담당한다
    ex)
    IoC가 없는 경우
public class ScheduleService {
    private ScheduleRepository scheduleRepository = new ScheduleRepository();
}

이 경우 ScheduleService가 ScheduleRepository를 직접 생성한다
즉, ScheduleService 제어권을 가지고 있다

ex)
IoC가 적용된 경우

public class ScheduleService {
    private final ScheduleRepository scheduleRepository;

    public ScheduleService(ScheduleRepository scheduleRepository) {
        this.scheduleRepository = scheduleRepository;
    }
}

여기서는 ScheduleService가 ScheduleRepository를 직접 생성하지 않는다.
단지 나는 ScheduleRepository가 필요하다! 라고 표현한다
실제로 객체를 만들어서 넣어주는 일은 Spring이 한다

이것이 바로 제어의 역전이다

3. DI(Dependency Injection, 의존성 주입)

개념

DI는 필요한 객체(의존 객체)를 직접 생성하지 않고 외부에서 주입받는 것이다

여기서 의존성(Dependency)이란 어떤 클래스가 동작하기 위해 반드시 필요한 다른 객체를 뜻한다
예를 들어 ScheduleService가 ScheduleRepository 없이는 제대로 동작할 수 없다면
ScheduleService는 ScheduleRepository에 의존한다고 말한다

Spring에서는 이 의존 객체를 외부(Spring 컨테이너)가 만들어서 넣어준다
이 과정을 의존성 주입이라고 한다

IoC와 DI의 관계

이 둘은 자주 같이 나오지만 완전히 같은 말은 아니다

IoC: 제어권을 Spring에게 넘긴다는 큰 개념
DI: 그 제어권을 실제로 구현하는 대표적인 방법

즉, DI는 IoC를 실현하는 방법 중 하나라고 이해하면 된다


이미지출저:https://isoomni.tistory.com/entry/TISPRING-IOC-DI-%EC%A0%95%EC%9D%98-%EC%9E%A5%EC%A0%90

4. DI 방식

Spring에서 의존성을 주입하는 방식은 대표적으로 3가지가 있다

1) 생성자 주입

가장 많이사용하고 권장되는 방식이다

@Service
public class ScheduleService {

    private final ScheduleRepository scheduleRepository;

    public ScheduleService(ScheduleRepository scheduleRepository) {
        this.scheduleRepository = scheduleRepository;
    }
}

장점

  • 객체 생성 시점에 반드시 필요한 의존성이 모두 주입된다
  • final을 사용할 수 있어 불변성을 유지할 수 있다
  • 테스트 코드 작성이 쉽다
  • 순환 참조 문제를 비교적 빨리 발견할 수 있다

Spring에서는 생성자가 하나만 있으면 @Autowired를 생략해도 자동 주입된다

2) 필드 주입

@Autowired
private UserRepository userRepository;

간단해 보이지만 권장되지 않는다
@Autowired를 필드에 직접 선언하여 의존성을 주입받는 방식
대표적으로 final 키워드 사용이 불가능하기 때문에 변수에 할당된 객체를 아래의 코드 예처럼 null 혹은 다른 객체로 바꿀 수 있어 안전하지 않다

3) Setter 주입

private UserRepository userRepository;

@Autowired
public void setUserRepository(UserRepository userRepository) {
    this.userRepository = userRepository;
}

선택적으로 바뀔 수 있는 의존성에는 사용할 수 있지만
필수 의존성은 보통 생성자 주입을 더 많이 사용한다

5. IoC 컨테이너란?

IoC 개념을 실제로 수행하는 주체가 바로 IoC 컨테이너이다

IoC 컨테이너는 객체를 생성하고, 저장하고, 관리하고, 의존성을 주입해주는 Spring의 핵심 구성요소이다

Spring에서 가장 대표적인 IoC 컨테이너는 ApplicationContext이다

역할

IoC 컨테이너는 다음과 같은 일을 한다

1) 객체 생성

개발자가 new 하지 않아도 컨테이너가 객체를 생성한다

2) 객체 보관

생성한 객체를 내부에 보관한다

3) 의존성 연결

어떤 Bean이 어떤 Bean을 필요로 하는지 파악해서 연결해준다

4) 생명주기 관리

객체 생성부터 초기화, 사용, 소멸까지 관리한다

5) 부가 기능 제공

이벤트 처리, 메시지 처리, 환경 설정, AOP 기반 기능 등도 지원한다

6. Bean이란 무엇인가

Bean은 Spring 컨테이너가 생성하고 관리하는 객체이다

단순히 클래스라고 해서 Bean이 되는 것이 아니라
Spring이 인식해서 등록하고 관리할 때 그 객체를 Bean이라고 부른다

Bean은 그냥 객체보다 한 단계 더 특별한 존재다
Spring 생태계 안에서 공식적으로 관리받는 객체라고 볼 수 있다

객체와 빈의 차이

구분일반 객체Bean
생성내가 new스프링
관리내가스프링
생명주기없음있음
DI 가능

정리

  • Spring에서 IoC는 객체의 생성과 제어권을 Spring에게 넘기는 개념
  • DI는 필요한 객체를 외부에서 주입받아 의존관계를 맺는 방식이다
  • IoC 컨테이너는 이러한 과정을 실제로 수행하는 관리 공간
  • 컨테이너가 관리하는 객체를 Bean이라고 한다

0개의 댓글