스프링(엄밀히 말해서는 스프링 컨테이너)이 개발자 대신 객체를 관리하기 위해서는 객체가 Bean 으로 등록이 되어있어야한다. 과거에는 이 Bean 을 등록하기 위해 xml 파일을 작성하였는데, 최근에는 어노테이션으로 편리하게 등록할 수 있게 바뀌었다.
스프링 MVC 패턴에서는 @Controller @Service @Repository 으로 손쉽게 스프링 컨테이너에 빈으로 저장할 수 있고, configuration 관련 객체들은
@Bean @Component 로 저장할 수 있다.
가장 눈에 띄는 차이는 @Bean 은 메소드레벨의 annotation 이며, 메소드의 return 객체가 Bean 으로 등록된다.
메소드 레벨에 작성이 가능하다는 것은 외부의 객체를 불러와서 Bean 으로 등록할 수 있다는 것이다.
가령 우리가 수정 불가능한(단 instance 는 생성가능) B 라는 객체가 있으면 메소드 내부에서 객체를 생성해서 반환하는 형태의 메소드를 작성할 수 있을 것이다.
이제 우리가 원하는 외부 객체를 Bean 으로 등록을 하였다!
이와 다르게 Component 는 클래스레벨에 사용되어 해당 class 자체가 런타임에서 ComponentScan 을 통해 Bean 객체로 등록된다.
즉 개발자가 수정가능한(보통은 개발자가 만든) class 를 bean 객체로 등록시킬 때 사용가능하다.
물론 @Bean 으로도 개발자가 생성한 class 를 bean 으로 등록할 순 있지만, annotation 을 구분해놓은 의도를 생각해보면 전자가 바람직한 방법이 될 것이다.
여기서 한가지 의문점이 들 수 있다. 메소드 레벨에 존재하는 @Bean 을 어떻게 spring 이 알고 실행시킬 수 있을까?
이 때 spring 에게 이 class 는 bean 을 등록하고있어요~ 라고 알리는 것이 @Configuration 이다. 사실 해당 annotation 은 내부적으로 @Component 를 포함하고 있기 때문에 spring 이 인식할 수 있는 것이다.
최종적으로 형태를 나타내보면 위와 같다. 위 코드는 spring security 의 BCryptPasswordEncoder 와 같은 개발자가 class 수정이 불가능한 객체에 대해 @Configuration 과 @Bean 조합으로 bean 으로 등록하는 과정을 보여주는 것이다.
Springboot 를 사용한다면 @Component 는 class 레벨에 적어주기만 해도 springapplication 하위에 있는 class 들이 ComponentScan 범위에 들어오기 때문에 추가적으로 신경쓸 필요는 없다.