Spring @Component @Bean 알고 쓰기

Composite·2020년 5월 27일
19

단도직입적으로 말하겠다. 알고 써라. 이 둘의 차이만 알아도 당신은 스프링이 어떻게 돌아가는지 반은 알고 들어간다고 봐도 좋다.

알다시피 스프링은 폭망한 EJB 방식을 대체한다. 그리고 어노테이션 기반은 개발생산성에 엄청난 향상을 불러와줬다.

자, 이제 알아보자. 두 어노테이션의 차이를!

@Component

싱글톤 클래스 빈을 생성하는 어노테이션이다. 물론 @Scope("Prototype") 어노테이션을 통해 싱글톤이 아닌 빈을 생성할 수도 있다. 또한 @Service, @Repository 어노테이션 또한 이에 포함된다.

이 어노테이션은 선언적(Declarative)인 어노테이션이다. 즉, 패키지 스캔 안에 이 어노테이션은 "이 클래스를 정의했으니 빈으로 등록해줘." 라는 뜻이 된다.

이 어노테이션은 질리도록 쓰기 때문에 이상 설명을 마치도록 하겠다.

@Bean

이녀석은 주로 @Configuration 어노테이션이 들어간 Spring 을 설정하는 클래스 내에 들어가는 메소드에서 선언한다. 만약 이를 @Component 로 따지면, 스프링은 스캔할 패키지를 검색해서 @Component 어노테이션을 발견하면 이렇게 등록하는 꼴이 된다.

@Component
public class MyBean {
    // ...
}

// 스프링 내부 처리를 이해하기 쉽게 표현하면?

@Bean
public MyBean myBean() {
    return new MyBean();
}

물론 생성자에 인자가 있다면 그 빈이 있는지 확인 후 넣는다. 물론 없으면 스프링은 오류를 뱉으며 앱을 끝내버린다.

자, 그럼 이녀석의 존재 이유는?

예전 스프링은 XML 설정만 가능했으며, 3.0 부터 본격적인 어노테이션 지원이 시작되었다.
물론 최신 버전인 5.2 에서도 XML 설정은 지원한다. XML 으로 설정할 때 장점이라면?
바로 넣었다 뺐다, 클래스 바꾸는 등의 유연한 설정이 가능하다는 이점이다. 그냥 XML 파일 편집하고 앱을 재시작하면 끝이다. 정말 간단하다. 필요없는 빈은 주석처리하면 된다. 어자피 XML 이나 클래스나 수정하면 앱 재시작 해야 하는건 매한가지다.
또한 스캔할 필요 없이 빈 등록이 빠르게 이루어진다. XML 설정을 고수하는 시니어 개발자들이 이런 매력 때문에 XML 설정을 빠져나가려 하지 않는 것이다.
위 빈 설정을 클래스 기반에서는 @Bean 어노테이션 또한 이런 유연한 작업을 가능하게 해준다. 예를 들면,

// prop 정의 안하면 빈 문자열로. null 받으면 switch 문에서 NullPointerException 발생함
@Value("${my.prop.animal:}")
private String animal;

@Bean
public Animal animal() {
    switch(animal) {
        case "dog": return new Dog();
        case "cat": return new Cat();
        case "cow": return new Cow();
        default: throw new InvalidStateException("동물 정의하고 다시 실행할 것!");
    }
}

이런 식으로 프로퍼티 값을 읽어들여 여기에 맞는 구현 클래스를 인터페이스 기반 빈에 등록해주는 유연한 처리가 가능하다는 것.
또한, @Component 어노테이션 넣기 곤란한 타사 라이브러리 클래스를 빈에 등록할 때도 @Bean 어노테이션을 통한 메소드를 통해 등록할 수 있다.

정리

일반적인 당신의 빈 등록은 간편하게 @Component 어노테이션으로, 유연한 빈 등록이 필요하다면 @Configuration 어노테이션이 들어간 클래스 내 @Bean 어노테이션 메소드 선언으로!
아, Spring Boot의 경우 @SpringBootApplication 어노테이션이 들어간 스프링 실행부에서도 @Bean 어노테이션이 깃든 메소드 등록이 가능하다는 것도 잊지 말자.

profile
지옥에서 온 개발자

2개의 댓글

comment-user-thumbnail
2020년 8월 26일

좋은정보 감사합니다.

답글 달기
comment-user-thumbnail
2021년 10월 15일

두 개념이 헷갈렸는데 감사합니다!

답글 달기