보통 Spring 서버가 동작하면서 @Controller나 @Service와 같은 어노테이션이 선언된 클래스나 인터페이스는 자동적으로 빈으로 생성하지만, 우리가 서비스를 구현하기 위하여 만든 객체들을 빈으로 생성해주어야하는 경우도 발생합니다.
이러한 경우에 우리는 @Bean 어노테이션, 혹은 @Component 어노테이션을 사용하곤 합니다.
두 어노테이션 모두 선언된 대상을 빈으로 만든다고는 대충 알고 있었으나, 정확히 어떠한 차이가 존재하는지는 알지 못하고 있었기에, 오늘 @Bean과 @Component 어노테이션 사이의 차이에 대하여 알아보았습니다.
먼저, @Bean 어노테이션입니다.
@Bean 어노테이션의 경우, 우리는 보통 메소드 위에 선언된 모습을 많이 보아왔습니다.
public class SecurityConfig{
@Bean
public SecurityFilterChain configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers("/api/hello").permitAll()
.anyRequest().authenticated();
return http.build();
}
}
다음과 같이 configure 메소드 상단에 @Bean이 사용된 것을 볼 수 있는데,
@Bean 어노테이션의 경우에는 메소드의 반환형을 빈으로 등록하기 위하여 사용한다고합니다.
그럼, 반환형이 void인 경우에는 어떻게 될까요?
솔직히 오류나는걸 기대했지만, 아쉽게도 오류는 아닌 모양입니다...
@Bean에대해서 좀 더 자세히 알아보면,
다음과 같이 Bean 인터페이스 상단에 @Target 어노테이션이 선언된 것을 확인할 수 있는데, 이를 자세히 보면 대상이 메소드로 지정된 것을 확인할 수 있습니다.
그럼 @Component 어노테이션의 특징을 살펴보자면, @Component 어노테이션의 경우에는 @Bean 어노테이션과는 다르게 클래스 상단에 위치되어 있던 모습을 많이 보았을 것입니다.
간단하게 설명하자면, 클래스 전체를 대상으로 하는 어노테이션이라고 볼 수 있겠습니다.
@Bean 혹은 @Component 어노테이션을 사용하여 빈을 생성하게 된다면, 스프링 컨테이너에 의하여 빈이 관리되게 됩니다.
이러한 빈들은 각자의 이름을 부여받게 되는데, 빈의 이름은 @Bean 어노테이션을 통하여 생성된 빈의 경우에는 메소드의 이름이 빈의 이름이 되고, @Component로 생성된 빈의 경우에는 클래스 이름이 빈의 이름이 됩니다.
만약 이름이 동일한 빈이 생성된다면, 추후에 빈을 호출할 경우에 충돌이 발생하여 오류가 발생할 수 있으므로, 가능하면 빈 이름이 충돌되지 않게끔 설정해주는 것이 중요합니다.
그게 아니라면, 빈의 이름은 @Bean 어노테이션을 통하여 지정할 수도 있으므로, 다음과 같이 빈 이름 지정 방식을 활용하여 동일한 빈 이름으로 인한 충돌을 막을 수 있습니다.