Spring 빈(Bean)과 의존관계, DI(Dependency Injection)

1. 스프링 컨테이너, IoC(제어 반전 Inversion of control) 컨테이너

스프링 Bean과 DI(Dependency Injection)의 개념에 대해서 살펴보기전에 스프링 컨테이너(IoC)의 특징을 살펴보겠습니다.

  • 스프링 애플리케이션에서는 오브젝트의 생성과 관계설정, 사용, 제거 등의 작업을 애플리케이션 코드 대신 독립된 컨테이너가 담당하게 됩니다. 컨테이너가 코드 대신 오브젝트에 대한 제어권 을 갖기때문에 IoC라고 부릅니다. 즉, 스프링컨테이너라는 것은 IoC컨테이너와 같은 말로 쓰여집니다.

  • 스프링 컨테이너는 DI(Dependency Injection)보다 많은 일들을 담당하게 됩니다. 예를 들면,
    DI를 위한 빈 팩토리에 엔터프라이즈 애플리케이션을 개발하는 데 필요한 여러 가지 컨테이너 기능을 추가한 것을 애플리케이션 컨텍스트를 관리하게 됩니다.

  • 스프링의 빈 팩토리와 애플리케이션 컨텍스트는 각각 기능을 대표하는 BeanFactory와 ApplicationContext라는 두 개의 인터페이스로 정의 되어있습니다.

  • ApplicationContext 인터페이스는 BeanFactory 인터페이스를 상속한 서브 인터페이스 입니다.

2. DI(Dependency Injection)

스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 객체 의존관계를 외부에서 넣어주는 것을 DI (Dependency Injection), 의존성 주입이라 합니다.

3. 스프링빈과 의존관계

컨트롤러와 서비스에 대한 레포지토리를 만들때 @Autowired가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어줍니다. 그렇게 객체 의존관계를 외부에서 넣어주는것을 DI(Dependency Injetion)이라 하며 이전 테스트 에서는 개발자가 직접 주입을 시켰지만 이제는 @autowired에 의해 스프링이 주입해줍니다.

스프링 빈이 등록되어 있지 않다면?

만약 컨트롤러와 서비스간의 스프링 빈이 등록되어 있지 않다면 @Controller가 스프링빈으로 자동등록해주거나 직접 자바코드로 직접 스프링빈을 등록할 수 있습니다. 그 이유는 @Controller에 포함되어있는 @Component 어노테이션이 빈으로 등록을 해주기 때문입니다. 그 외는 SpringConfig라는 설정파일을 만들어서 직접 자바코드로 스프링빈을 등록하게 할 수 있다.

4. 컴포넌트 스캔의 원리

컴포넌트 스캔은 어떤 원리를 가지고 있을까요?

@Component 애노테이션이 있으면 스프링빈으로 자동등록 됩니다.바로 @Controller가 스프링빈으로 등록된 이유도 컴포넌트 스캔때문이라고 할 수 있습니다.

@Component을 포함하는 애노테이션은 다음과 같습니다. @Controller, @Service @Repository가 있습니다. 즉, 스프링 빈으로 자동등록된다는 말입니다.

결론, 생성자에 @Autowired를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입해줍니다. 생성자가 1개만 있으면 @Autowired는 생략이 가능합니다.

스프링은 스프링 컨테이너에서 스프링 빈을 등록할 때, 기본적으로 싱글톤으로 등록합니다(유일하게 하나만 등록해서 공유하고) 같은 스프링 빈이면 모두 같은 인스턴스이다. 싱글톤이 아니게 설정할 수 있지만, 특별한 경우 제외하면 대부분 싱글톤을 사용합니다.

5. DI(Dependency Injection) 주입

DI주입필드주입, setter주입, 생성자 주입 총 3가지 방법이 있습니다.

의존관계가 실행중 동적으로 변하는 경우는 거의 없기때문에 생성자 주입을 통한 DI주입을 권장합니다. DI주입시 주의사항은 @Autowired를 통한 DI는 Controller, Service등과 같이 스프링이 관리하는 객체에서만 동작하게 됩니다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작되지 않습니다.