본문 바로가기
백엔드(Back End)/Spring

[TIL]20230708 - 스프링 컴포넌트 스캔

by tjsdn9803 2023. 7. 9.

컴포넌트 스캔

스프링 빈을 등록하는 방법으로는 수동적으로 @Bean이나 XML의<bean>등을 통해서 설정 정보에 직접 등록할 스프링 빈을 나열하는 방법이 있지만 이 방법은 등록해야할 빈의 갯수가 많아 질수록 일일히 등록하기 귀찮고 누락에 대한 걱정도 있다.

그래서 스프링은 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다.

@ComponentScan을 설정 정보에 붙혀 주면 컴포넌트 스캔기능을 사용가능하다.

package hello.core;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import static org.springframework.context.annotation.ComponentScan.*;
@Configuration
@ComponentScan(
 excludeFilters = @Filter(type = FilterType.ANNOTATION, classes =
Configuration.class))
public class AutoAppConfig {
 
}

즉 기존 @Configuration설정 정보클래스 안에서 @Bean을 통해 지정해주지 않아도 컴포넌트 스캔이 @Component어노테이션이 붙은 클래스를 스캔하여 스프링 빈으로 등록한다.

@Component
public class MemoryMemberRepository implements MemberRepository {}

컴포넌트 스캔의 탐색 위치와 기본 스캔 대상

모든 자바 클래스를 다 컴포넌트 스캔하면 시간이 오래 걸린다. 그래서 꼭 필요한 위치부터 탐색하도록 시작 위치를 지정할 수 있다.

@ComponentScan(
    basePackages = "hello.core",
}

basePackeges옵션을 사용해 탐색할 패키지의 시작위치를 지정한다. 이 패키지를 포함하여 하위 패키지를 모두 탐색한다.

@ComponentScan(
 basePackages = {"hello.core", "hello.service"}
}

이런 방식으로 여러 시작 위치를 지정할 수도 있다.

권장 탐색 시작 위치는 프로젝트 최상단이다. 스프링 부트도 이 위치를 기본적으로 제공한다.

실제로 스프링 부트의 애플리케이션 위치에 가보면 @SpringBootApplication 어노테이션이 있는데 어노테이션을 클릭하면 @ComponentScan이 있다.(그렇기 떄문에 스프링 부트는 따로 설정 정보 클래스 @Configuration이 없어도 스프링 빈 등록이 가능하다)

컴포넌트 스캔 기본 대상

  • @Component : 컴포넌트 스캔에서 사용
  • @Controller : 스프링 MVC 컨트롤러에서 사용
  • @Service : 스프링 비즈니스 로직에서 사용
  • @Repository : 스프링 데이터 접근 계층에서 사용
  • @Configuration : 스프링 설정 정보에서 사용

@Component어노테이션외의 다른 어노테이션들 또한 소스코드에 @Component를 포함하고 있기 때문에 컴포넌트 스캔대상이다.

그렇다면 왜 굳이 @Component가 아닌 @Controller, @Repository등을 사용할까?

특정 어노테이션이 있으면 스프링은 부가 기능을 수행하기 떄문이다.

  • @Controller : 스프링 MVC 컨트롤러로 인식
  • @Repository : 스프링 데이터 접근 계층으로 인식하고, 데이터 계층의 예외를 스프링 예외로 변환해준다.
  • @Configuration : 앞서 보았듯이 스프링 설정 정보로 인식하고, 스프링 빈이 싱글톤을 유지하도록 추가 처리를 한다.
  • @Service : 사실 @Service 는 특별한 처리를 하지 않는다. 대신 개발자들이 핵심 비즈니스 로직이 여기에 있겠구나 라고 비즈니스 계층을 인식하는데 도움이 된다.

의존관계 주입

기존에는 @Configuration 설정 정보를 통해 빈을 등록하고 의존관계를 주입할 수 있었는데 자동 컴포넌트 스캔을 사용하면 어떻게 할까?

@ComponentScan은 @Component가 붙은 모든 클래스를 스프링 빈으로 등록한다.
(※ 이때 스프링 빈의 이름은 기본적으로 클래스 명을 사용하되 맨 앞글자만 소문자를 사용한다. 직접 지정하고 싶다면 @Component("memberService2")와 같이 직접 이름을 지정할 수 있다.)

@Autowired

생성자에 @Autowired를 지정하면 스프링 컨테이너가 자동으로 해당 스프링 빈을 찾아서 주입한다.
(※ 의존 관계 주입방법은 생성자를 통한 주입외에도 필드 주입, setter주입등 다른 방법도 있지만 생성자를 통한 의존관계 주입이 가장 많이 사용된다.)

이때 기본 조회 전략은 타입이 같은 빈을 찾아서 주입한다.
(※ 이때 타입이 같은 빈이 두개 이상이라면? 일단 오류가 발생한다. 하지만 Qualified, Primary, 직접 빈 이름 등록등을 통해 해결할 수 있다.)

생성자에 파라미터가 많아도 다 찾아서 자동으로 주입한다.