스프링 빈(Bean)에 대한 얘기와 빈 등록방법
스프링에서 사용할 객체를 위해 클래스를 만들어줬다고 해도 그 녀석을 사용하려면 스프링 빈으로 등록을 해야 한다. 만약 빈으로 등록하지 않으면, 스프링에서 사용할 수 없게 된다. 근데 빈이란 것이 도대체 무엇일까?
스프링 빈(Bean)
스프링 컨테이너가 관리하는 Java객체. 즉 스프링에 의해 생성되고 관리되는 Java 객체라고 보면 된다. 스프링 컨테이너가 일종의 바구니 같은 느낌이라면, 빈은 그 바구니에 담기는 콩들이라고 생각할 수 있다. 한마디로 이 콩으로 등록을 해야 스프링에서 이용가능하게 된다는 것..! 원래는 개발자가 직접 코드를 통해 new연산자나 팩토리 패턴 등으로 객체를 생성하고 소멸시키는데, 스프링은 컨테이너라는 바구니가 이 역할들을 대신해준다고 생각할 수 있다.
예를 들어 내가 MemberController를 만들고, 이 컨트롤러가 MemberService를 통해 회원가입이나 회원조회를 할 수 있게끔 만들려고 한다면 내가 만든 MemberController와 MemberService를 빈으로 등록을 해야 스프링에서 이용 가능하다. 이 때 다음과 같은 2가지 방법으로 스프링 빈 등록이 가능하다.
1. 어노테이션을 통한 등록
빈으로 등록할 클래스에 @Component라는 어노테이션을 멕이면 된다. 이렇게 해두면 스프링으 컴포넌트 스캔을 통해 지가 알아서 Bean으로 등록해준다. @Controller, @Service, @Repository등과 같이 @Component를 포함하는 어노테이션들도 컴포넌트 스캔을 통해 Bean으로 등록된다. 근데 그렇다고 아무데서나 저런 어노테이션 멕인다고 죄다 Bean으로 등록되는건 아니고, 컴포넌트 스캔을 하는 범위가 따로 있다. 기본적으론 @ComponentScan 어노테이션이 있는 파일의 패키지 아래를 모두 스캔하며, @SpringBootApplication(scanBasePackages ={{경로설정}}) 옵션으로 컴포넌트 스캔 시작 범위를 직접 설정할 수 있다. (이 경우 설정한 경로 기준으로 그 하위 애들만 스캔)
암튼 어노테이션을 통한 등록법의 예시는 다음과 같다.
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
@Autowired : 이 어노테이션이 보시다시피 생성자에 있으면 스프링에 컨테이너에 있는 memberService 빈을 찾아서 자동으로 연결해주게 한다(즉 이를 위해서 MemberService가 당연히 빈으로 등록돼있어야 한다). 이렇게 의존관계를 갖는 객체를 외부에서 넣어주는 이런 모습을 DI(Dependency Injection)이라고 한다. 여기서는 개발자가 직접 코드를 통해 주입하는 게 아니라 @Autowired 어노테이션에 의해 스프링에 알아서 주입해준다.
2. 자바 코드로 직접 등록
하나하나 직접 Bean으로 등록하는 방식이다. ~~Config라는 자바 파일을 만들고 거기에 다음과 같이 빈을 등록한다.
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
참고로 MemberService가 MemberRepository에 의존하기 때문에 MemberService의 경우 생성자에서 memberRepository를 넣어주는 모습.
@Bean이란 어노테이션을 보고 스프링이 이 객체들을 Bean으로 등록해준다.
두 방법 중 그런 어떤 방법이 더 좋은 것일까?
상황에 따라 다르다.
주로 정형화된 컨트롤러나 서비스, 리포지토리 같은 경우는 어노테이션을 통한 등록이 편하다.
그러나 정형화되지 않았거나 상황에 따라 구현 클래스를 변경해야 하는 경우 등엔 코드로 직접 등록하는 게 더 편할 것이다. 왜냐하면 어노테이션을 통한 등록의 경우 변경할 때마다 새로 어노테이션을 작성해줘야 하는 번거로움이 있지만 직접 등록하는 경우는 1번만 바꾸면 되기 때문.