Bean과 Component 차이
미니 프로젝트를 통해 스프링 시큐리티를 사용할 때 Bean
과 Component
를 다룰 일이 있었다. 이 둘의 차이를 모르기 때문에 간략하게 정리하고자 한다.
선언 위치의 차이
Configuration + Bean과 Component 어노테이션이 사용되면 모두 스프링의 IoC 컨테이너에 객체로 관리되며 어플리케이션 전역적으로 의존성 주입에 활용될 수 있다.
Bean과 Component 어노테이션의 첫 번째 차이는 선언 위치다. Component
는 class level에 선언되고 Bean
은 메소드 레벨에 선언된다.
가령 패스워드 암호화를 위해 Bcrypt를 사용하는 모듈을 Component
로 제공한다고 하면 아래와 같이 class level에 component를 선언할 수 있다.
@Component
public class PasswordEncoder {
public String encode(String seed) {
return new BCryptPasswordEncoder().encode(seed);
}
public boolean matches(String seed, String password) {
return new BCryptPasswordEncoder().matches(seed, password);
}
}
만약 위 코드에서 Component
위치에 Bean
을 사용한다면 IDE가 오류를 표시한다. 보면 Target이 METHOD만 지정하는 것을 확인할 수 있다.
아래는 위에서 표기되는 ElementType의 내부인데 Class에 사용되려면 TYPE 으로 선언되어야 함을 알 수 있다.
public enum ElementType {
/** Class, interface (including annotation interface), enum, or record
* declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
아래 코드는 스프링 시큐리티를 사용한다면 많이 볼 수 있는 코드인데 메소드레벨에 @Bean
을 선언해서 IoC 컨테이너의 빈으로 등록할 수 있다.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
사용법의 차이
Bean
은 외부 라이브러리가 제공하는 객체를 사용할 때 활용하고 Component
는 내부에서 직접 접근 가능한 클래스를 사용하면 된다. 위 예시에서 활용했던 코드를 다시보자.
@Component
public class PasswordEncoder {
public String encode(String seed) {
return new BCryptPasswordEncoder().encode(seed);
}
public boolean matches(String seed, String password) {
return new BCryptPasswordEncoder().matches(seed, password);
}
}
위 코드에서 Component 어노테이션을 쓸 수 있는 이유는 PasswordEncoder라는 class를 내가 직접 만들었기 때문이다. 만약 이 코드가 라이브러리에 있는 코드라면 나는 이 클래스에 Component를 추가할 수 없다. 따라서 라이브러에 있는 객체를 사용할 때는 Bean을 활용할 수 있다.
Bean과 Configuration
Bean을 사용시 Configuration 어노테이션을 꼭 사용해야 한다. 만약 아래와 같이 Bean만 선언했을 경우.
public class MyBean {
@Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
이 Bean을 다른 곳에서 의존성 주입하는데 활용할 수 없다.
Configuration 어노테이션을 사용하면 정상적으로 IoC 컨테이너에 등록되어 의존성 주입을 할 수 있는데 사실 Configuration 내부에 Component 어노테이션이 있다.