일반적으로 의존성에 대한 제어권은 직접 의존성을 만드는 개발자에게 있다. 그러나 직접적으로 의존성을 만들지 않고, 외부에서 의존성을 가져오는 경우가 있다. 이를 제어의 역전(IoC, Inversion of Control)이라고 한다. 이때, 밖에서 나에게 의존성을 주입하는 것을 DI라고 한다. 따라서 DI는 IoC의 일종이라고 생각할 수 있다.
스프링 프레임워크에서는 주입 대상이 되는 의존성 객체를 Bean이라고 한다. Bean은 스프링 IoC 컨테이너가 객체를 만든 뒤 Bean으로 등록하고, 의존성을 관리한다. 여기서 스프링 IoC 컨테이너는 ApplicationContext 또는 BeanFactory를 사용하는데, ApplicationContext는 BeanFactory를 상속 받기에 둘 다 같은 일을 한다. Bean의 구성 요소는 아래와 같다.
class
: Bean으로 등록할 Java 클래스id
: Bean의 고유 식별자scope
: Bean을 생성하기 위한 방법 (싱글톤, 프로토타입 등)constructor-arg
: Bean 생성 시 생성자에 전달할 파라미터property
: Bean 생성 시 setter에 전달할 인수그러나 Bean으로 등록까지는 개발자의 몫이다. 등록되지 않은 객체에는 의존성 주입을 해주지 않기에 이 점을 주의해야 한다.
예를 들어 다음과 같은 클래스가 있고, 이를 스프링 컨테이너에 등록하고자 한다.
public class SirubongResource {
...
}
이 클래스를 빈으로 등록하기 위해선 명시적으로 설정 클래스에서 @Bean
어노테이션을 사용해 수동으로 스프링 컨테이너에 빈을 등록하는 방법이 있다. 설정 클래스는 다음과 같이 @Configuration
어노테이션을 클래스에 붙여주면 되는데, @Bean
을 사용해 수동으로 빈을 등록해줄 때에는 메소드 이름으로 빈 이름이 결정된다. 그러므로 중복된 빈 이름이 존재하지 않도록 주의해야 한다.
@Configuration
public class ResourceConfig {
@Bean
public SirubongResource sirubongResource() {
return new SirubongResource();
}
}
스프링 컨테이너는 @Configuration
이 붙어있는 클래스를 자동으로 빈으로 등록해두고, 해당 클래스를 파싱(어떤 자료에서 원하는 정보만 가공하고 뽑아서 원하는 때에 불러올 수 있게 하는 것)해서 @Bean
이 있는 메서드를 찾아서 빈을 생성해준다. @Configuration
안에서 @Bean
을 사용하면 싱글톤을 보장받을 수 있기에 @Bean
어노테이션은 반드시 @Configuration
과 함께 사용해야 한다.
이러한 방법은 수동으로 빈을 직접 등록해줘야 하는 상황인데, 주로 다음과 같을 때 사용한다.
이때, 애플리케이션 전범위적으로 사용되는 클래스와 다형성을 활용하여 여러 구현체를 등록할 때 @Bean
을 사용하면 좋은 이유는 한 눈에 파악하여 유지보수하기 좋기 때문이다. 예를 들어 여러 구현체를 빈으로 등록할 때 어떠한 구현체들이 빈으로 등록되는지를 파악하려면 소스 코드를 찾아볼 필요 없이 해당 @Configuration
클래스만 보면 되기 때문이다.
하지만 수동으로 직접 빈을 등록하는 방식은 빈으로 등록할 객체가 많아질 수록 비효율적이다. 그래서 스프링에서는 특정 어노테이션이 있는 클래스를 찾아서 빈으로 등록해주는 컨포넌트 스캔 기능을 제공한다. 스프링은 컨포넌트 스캔(Component Scan)을 사용해 @Component
어노테이션이 있는 클래스들을 찾아 자동으로 빈 등록을 해준다. 스프링은 기본적으로 컴포넌트 스캔을 이용한 자동 빈 등록 방식을 권장한다.
@Component
public class SirubongResource {
...
}
번외로 스프링에서는 @Controller
, @Service
, @Repository
어노테이션은 모두 @Component
가 내재되어 있다. 따라서 이 어노테이션이 붙어있는 클래스들도 빈으로 등록된다.
@RequestMapping
어노테이션같은 어노테이션은 해당 어노테이션 밑에서만 사용할 수 있다. (웹 요청과 응답 처리)@Component
에 추가된 기능은 없다. 그러나 추후 스프링에서 추가적인 Exception Handing을 해줄 수 있으니 비즈니스 로직에는 해당 어노테이션을 사용한다. (서비스 레이어, 내부에서 자바 로직 처리)본 글은 아래 링크를 기반으로 정리하였습니다.