이번 포스팅에서는 Spring에서 자주 사용되는 @Component, @Configuration, @ComponentScan, @Bean의 차이에 대해서 정리해보려고 합니다.
@Component가 작성된 class를 Component라고 알리는 어노테이션입니다. 이 클래스들은 어노테이션 기반의 Configuration과 classpath를 통한 스캐닝에서 자동으로 인식되는 클래스들입니다.(ComponentScan의 후보가 됩니다.) 다른 어노테이션인 @Repository, @Service 등과 같은 어노테이션도 Component로 인식됩니다.
@Bean 어노테이션의 경우 개발자가 직접 제어 하지 못하는 외부 library 등을 Bean으로 등록할 때 주로 사용되는 어노테이션입니다. 이와 달리, @Component는 개발자가 직접 작성한 Class를 Bean으로 등록할 때 주로 사용되는 어노테이션입니다.
@Bean은 method-level에서의 어노테이션으로 @Configuration 어노테이션이 붙은 class에서 주로 사용됩니다. 반면, @Component는 class-level에서의 어노테이션입니다.
@Component은 class 자체가 spring container에 의해 관리되지만, @Bean은 method가 return하는 instanace가 spring container에 의해 관리됩니다. @Bean은 즉 application context 단에서 정의되는 것이 아니라 third-party인 bean을 explicitly declare하기 위해 사용되는 것입니다.
@Bean이 @Component보다 더 유연하게 동작합니다.
Q) @Bean이 왜 @Component보다 더 유연하게 동작하나요?
A) method-level에서 동작하므로 custom logic 등을 추가할 수 있지만, @Component는 ComponentScan을 통해서만 Bean으로 등록됩니다.
예시코드
@Bean
public MyBean myBean() {
if (someCondition) {
return new MyBean();
} else {
return null; // or throw an exception, return a different bean, etc.
}
}
단순히 Bean을 등록하기 위한 것이 아니라 Bean을 등록할 때 Singleton이 될 수 있도록 보장해준다. 이를 코드로 알아보자.
설정파일
@Configuration
public class AppConfig {
@Bean
public CustomBean customBean() {
return new CustomBean();
}
@Bean
public CustomBeanConsumer customBeanConsumer() {
return new CustomBeanConsumer(customBean());
}
}
기타class
CustomBean.class
public class CustomBean {
public CustomBean() {
System.out.println("CustomBean Created()");
System.out.println("this.hashCode() = " + this.hashCode());
}
}
CustomBeanConsumer.class
public class CustomBeanConsumer {
public CustomBeanConsumer(CustomBean customBean) {
System.out.println("CustomBeanConsumer Created()");
System.out.println("customBean = " + customBean.hashCode());
}
}
아래는 출력 결과입니다.

Bean이 한번만 출력되었고, 그 hashCode가 같음을 알 수 있습니다. 즉 Singleton이 보장되는 것입니다.
내부적으로는 Spring이 CGLIB라는 바이트코드 조작 라이브러리를 사용해 AppConfig를 상속받은 임의의 Proxy 클래스를 만들어 그 클래스를 Bean으로 등록한 것입니다. 이러한 과정을 통해 싱글톤을 보장하게 됩니다.
이렇게 @Component, @Bean, @Configuration의 차이를 알아보았습니다.
참고
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Component.html
https://medium.com/javarevisited/what-is-difference-between-component-and-bean-annotation-in-spring-bffdad0ab899
