본문 바로가기
Spring

[Spring] 컴포넌트 스캔

by 당코 2022. 12. 27.

지금까지 @Configuration와 @Bean을 이용하여 수동으로 스프링 컨테이너에 스프링 빈을 등록하는 방법을 사용하였다.

하지만 등록해야 할 빈의 개수가 너무 많다면 하나하나 수동으로 등록하기 쉽지 않을 수 있다.

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

 

컴포넌트 스캔

컴포넌트 스캔을 하기 위해서는 @ComponentScan을 설정 정보에 붙여주면 된다.

@Configuration
@ComponentScan
public class AutoAppConfig {
}

 

앞서 봤던 AppConfig와 달리 컴포넌트 스캔을 이용하면 @Bean을 등록하지 않아도 된다.

자동으로 @Component가 붙은 클래스를 스캔해서 스프링 빈으로 등록한다.

@Component
public class MemoryMemberRepository implements MemberRepository {}

 

스프링 빈으로 등록하고 싶은 클래스에 @Component를 붙여주면 컴포넌트 스캔의 대상이 된다.

하지만 여기서 살펴봐야 할 부분이 있다.

@Component
public class MemberServiceImpl implements MemberService {
	private final MemberRepository memberRepository;

	public MemberServiceImpl(MemberRepository memberRepository) {
 		this.memberRepository = memberRepository;
 	}
}

 

위와 같은 클래스를 컴포넌트 스캔을 하려고 할 때 기존의 수동 빈 등록에서는 @Bean으로 직접 설정정보를 작성하고, 의존관계를 직접 명시했다.

하지만 지금의 경우 의존관계 주입을 해주는 정보 자체가 없기 때문에 추가적인 방법이 필요하다.

이때 사용되는 것이 @Autowired이다.

@Component
public class MemberServiceImpl implements MemberService {
	private final MemberRepository memberRepository;
    
	@Autowired
	public MemberServiceImpl(MemberRepository memberRepository) {
 		this.memberRepository = memberRepository;
 	}
}

 

@Autowired를 사용하면 스프링 컨테이너가 해당 스프링 빈을 찾아서 주입한다.

의존관계 주입에 대해서는 다른 포스팅에서 자세하게 다루겠다.

 

탐색 위치와 기본 스캔 대상

컴포넌트 스캔의 탐색 시작 위치를 직접 지정해 줄 수 있다.

@ComponentScan(
	basePackages = "hello.core"
}

 

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

만약 지정하지 않으면 @ComponentScan이 붙은 설정 정보 클래스의 패키지가 시작 위치가 된다.

권장하는 방법은 패키지 위치를 지정하지 않고, 설정 정보 클래스의 위치를 프로젝트 최상단에 두는 것이다. 

그렇게 하면 시작 위치를 지정하지 않고 자동으로 모든 프로젝트의 패키지를 탐색할 수 있다.

 

컴포넌트 스캔은 다음 어노테이션 모두를 탐색대상에 포함을 한다.

- @Component : 컴포넌트 스캔에서 사용

- @Controller : 스프링 MVC 컨트롤러에서 사용

- @Service : 스프링 비즈니스 로직에서 사용

- @Repository : 스프링 데이터 접근 계층에서 사용

- @Configuration : 스프링 설정 정보에서 사용

내부적으로 소스코드를 살펴보면 @Component를 포함하고 있는 것을 알 수 있다.

 

중복 등록과 충돌

컴포넌트 스캔을 할 때 중복된 빈 이름이 등록되면 어떻게 될까?

상황은 두 가지가 있다.

1. 컴포넌트 스캔을 통해 등록된 두 개의 빈의 이름이 중복일 경우

2. 컴포넌트 스캔을 통해 등록된 빈의 이름과 수동으로 등록한 빈의 이름이 중복일 경우

 

컴포넌트 스캔을 통해 등록된 두 개의 빈의 이름이 중복일 경우

ConflictingBeanDefinitionException 예외가 발생되어 오류가 발생한다.

 

컴포넌트 스캔을 통해 등록된 빈의 이름과 수동으로 등록한 빈의 이름이 중복일 경우

수동으로 등록한 빈이 우선권을 가진다.

하지만 현실은 개발자가 의도하여 빈 이름을 중복하게 하는 경우보다, 의도치 않게 발생하는 경우가 대부분이다.

따라서 빈 이름을 중복하지 않게 주의하는 것이 중요하다.

이런 경우를 막기 위해 최근 스프링 부트에서는 수동 빈 등록과 자동 빈 등록이 충돌이 나면 오류가 발생하도록 기본 값을 바꾸었다.

 

출처 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard