Spring IoC 와 DI, 그리고 Bean

Jay Lee·2023년 2월 13일
0

Spring

목록 보기
3/3

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

일반적인 프로그래밍의 경우 개발자가 직접 객체를 생성하고 다른 클래스와 연결 및 사용하는 등 프로그램의 흐름을 개발자가 주도하였습니다. 하지만 Spring 등과 같은 Framework의 경우 객체의 생명주기관리 및 의존성 관리를 프레임워크가 도맡아 해주게 되는데 이를 제어권이 개발자에서 프레임워크로 넘어갔다고 하여 제어의 역전이라고 한다.

Framework vs Library

  • Framework: 객체의 생성 및 실행을 프레임워크가 수행한다.
  • Library: 개발자가 코드의 흐름을 제어하고 이에 도움을 준다.

따라서, IoC는 Spring에서만 사용되는 것이 아닌 모든 Framework에 대해 공통적으로 적용되는 용어이다.


의존성 주입 (Dependency Injection)

의존성 주입이란 객체에서 필요한 다른 객체 인스턴스들을 내부에서 직접 종속된 객체의 인스턴스를 생성하여 사용하지 않고, 외부에서(Spring의 경우 Bean) 가져다 사용할 수 있도록 하는 디자인 패턴이다.

의존관계 주입은 구체적인 의존 오브젝트와 그것을 사용할 주체, 보통 클라이언트라고 부르는 오브젝트를 런타임 시에 연결해주는데 다음 3가지 조건을 충족해야 한다.
1. 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. 그러기 위해서는 인터페이스에만 의존하고 있어야 한다.
2. 런타임 시점의 의존관계는 컨테이너나 팩토리 (ApplicationContext)같은 제 3의 존재가 결정한다.
3. 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공해줌으로써 만들어진다.

DI를 통해 코드를 보다 유연하고 유지 관리 및 테스트할 수 있도록 만들 수 있게 된다. 종속성을 명시적으로 만들고 이를 필요로 하는 개체에 주입할 수 있도록 함으로써 개체를 분리하고 나머지 코드에 영향을 주지 않고 종속성을 쉽게 변경하거나 대체할 수 있게 된다.

DI에는 3가지 방식이 있다.

1. 생성자 주입

생성자 주입은 해당 객체의 생성자에 의존성을 주입하는 방식이다

@Service
public class FooService {

    private FooRepository fooRepository;
    private BarService barService;

    @Autowired
    public FooService(FooRepository fooRepository, BarService barService) {
        this.fooRepository = fooRepository;
        this.barService = barService;
    }
    
}

생성자의 호출 시점에 1회 호출 되는 것이 보장된다. 그렇기 때문에 주입받은 객체가 변하지 않거나, 반드시 객체의 주입이 필요한 경우에 강제하기 위해 사용할 수 있다. Spring 프레임워크에서 공식적으로 권장하는 의존성 주입 방식이다. 생성자 주입은 생성자가 1개만 있을 경우 @Autowired 어노테이션을 생략할 수 있다.

@Service
@RequiredArgsConstructor
public class FooService {

    private final FooRepository fooRepository;
    private final BarService barService;
    
}

2. 수정자 주입

수정자 주입은 필드 값을 변경하는 Setter를 이용해 의존 관계를 주입하는 방법이다. 수정자 주입은 생성자 주입과 다르게 주입받는 객체가 변경될 가능성이 있는 경우에 사용한다.

@Service
public class FooService {

    private FooRepository fooRepository;
    private BarService barService;

    @Autowired
    public void setFooRepository(FooRepository fooRepository) {
        this.fooRepository = fooRepository;
    }

    @Autowired
    public void setBarService(BarService barService) {
        this.barService = barService;
    }
}

3. 필드 주입

@Service
public class FooService {

	@Autowired
    private FooRepository fooRepository;
    @Autowired
    private BarService barService;

필드 주입은 외부에서 접근이 불가능하다는 단점이 존재한다. 하지만 최근 테스트 코드의 중요성이 부각됨에 따라 필드의 객체를 수정할 수 없는 필드 주입은 거의 사용되지 않게 되었다.


IoC 컨테이너와 Bean

Spring의 IoC 컨테이너는 Spring 기반 애플리케이션에서 객체 생성 및 구성을 관리하는 Spring Framework의 중심 구성 요소이다. Spring ApplicationContext라고도 한다. IoC 컨테이너는 Spring 애플리케이션에서 개체 간의 종속성을 관리하는 방법을 제공하므로 유지 관리 및 테스트가 더 쉬운 분리된 모듈식 코드를 작성할 수 있다는 장점을 가진다.

Bean은 Spring에서 IoC 컨테이너가 관리하는 객체의 단일 인스턴스이다.. IoC 컨테이너는 인스턴스화에서 소멸까지 빈의 수명 주기를 만들고 관리하는 역할을 한다. Spring 기반 애플리케이션에서는 구성 파일에 빈을 정의하고 IoC 컨테이너는 이 구성을 읽어 빈을 만들고 관리하는 방법을 결정한다. 구성 파일은 Bean을 구성하는 클래스, 해당 종속성 및 Bean을 만들고 구성하는 데 필요한 모든 구성 정보를 지정한다.


Spring에서의 IoC 동작 원리

profile
Data Engineer

0개의 댓글