본문 바로가기
Java/[스프링 5 프로그래밍 입문]

[Spring] 컴포넌트 스캔 - @Component, @ComponentScan 사용하기

2021. 8. 2.
반응형

이전까지는 설정 클래스에서 수동으로 빈 객체를 등록하고 사용하는 방법을 배웠다. 이번 포스트에서는 @Component와 @ComponentScan 애노테이션을 사용하여 스프링이 스캔할 대상을 설정하고 자동으로 빈을 등록하는 컴포넌트 스캔 기능에 대해 알아볼 것이다.

 

@Component 애노테이션을 이용한 컴포넌트 스캔

컴포넌트 스캔스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능이다. 따라서 설정 클래스에 별도로 빈으로 등록하지 않아도 된다. 즉 설정 클래스 코드가 크게 줄어드는 장점이 있다. 클래스에 @Component 애노테이션을 붙이면 스프링이 검색해서 빈으로 등록할 수 있다. 해당 클래스를 스캔 대상으로 표시하는 것이다.

@Component
public class ExDao {
	...
}
@Component("sample")
public class SampleDao{
	...
}

위의 두 코드는 빈 객체로 등록할 클래스에 @Component 애노테이션을 붙인 예제이다. @Component 애노테이션이 붙음으로써 이 클래스들은 스프링에 의해 직접 빈으로 등록될 것이다.

 

@Component에 값을 주었는지에 따라 빈으로 등록할 때 사용할 이름이 결정된다. 첫 번째 코드는 값을 주지 않았기 때문에 클래스 이름의 첫 글자를 소문자로 바꾼 "exDao"가 빈의 이름이 된다. 두 번째 코드는 값을 주었기 때문에 주어진 값이 빈의 이름으로 사용된다.

 

@ComponentScan 애노테이션으로 스캔 설정

@Component 애노테이션이 붙은 클래스를 스캔해서 빈으로 등록하려면 설정 클래스에서 @ComponentScan 애노테이션을 적용해야 한다.

@Configuration
// @Component 애노테이션을 붙인 클래스를 스캔해서 빈으로 등록하도록 한다.
// basePackages 속성은 스캔 대상 패키지 목록을 지정한다. 해당 패키지와 그 하위 패키지에 속한 클래스를 스캔 대상으로 설정한다.
// 스캔 대상 중 @Component 애노테이션이 붙은 클래스의 객체를 생성해서 빈으로 등록한다.
@ComponentScan(basePackages= {"spring"})
public class AppCtx {
	@Bean
	@Qualifier("example")
	public ExService exService(){
		return new ExService();
	}
	
	@Bean
	public SampleService sampleService(){
		return new SampleService ();
	}
}

AppCtx 설정 클래스에 @ComponentScan 애노테이션을 붙인 예제다. 애노테이션의 basePackages 속성은 스캔할 패키지의 목록을 지정한다. 쓰인 패키지와 그 하위 패키지에 속한 클래스들을 스캔 대상으로 설정하고 스캔 대상 중 @Component 애노테이션이 붙은 클래스의 객체를 생성해서 빈으로 등록한다.

 

@Component 애노테이션 외에도 @Controller, @Service, @Repository, @Aspect, @Configuration 애노테이션이 붙은 클래스가 스캔 대상에 포함된다. 이들은 컴포넌트 스캔 대상이 될 뿐만 아니라 스프링에서의 특수한 기능과 연관이 있는 애노테이션이다.

 

컴포넌트 스캔의 충돌

컴포넌트 스캔 기능을 사용해서 자동으로 빈을 등록할 때는 충돌에 주의해야 한다. 크게 빈 이름 충돌과 수동 등록에 따른 충돌이 발생할 수 있다.

 

빈 이름 충돌

a 패키지와 b 패키지에 ExDao클래스가 존재하고 두 클래스 모두 @Component 애노테이션을 붙인 뒤 @ComponentScan 애노테이션을 사용하면 익셉션이 발생한다. 먼저 스캔된 클래스를 exDao라는 이름으로 등록하고, 다음으로 스캔된 클래스를 등록할 때도 이름을 exDao로 등록해야 하는데 b.ExDao와 일치하지 않는 a.ExDao 타입의 빈 이름 exDao와 충돌이 난다는 메시지가 출력된다. 즉 서로 다른 타입인데 같은 빈 이름을 사용하는 경우가 있다면 둘 중 하나는 명시적으로 이름을 지정해주어야 충돌을 막을 수 있다.

 

수동 등록에 따른 충돌

컴포넌트 스캔 시 부여되는 빈 이름수동 등록한 이름같을 경우에는 수동 등록한 빈이 우선한다. 즉 해당 빈 객체는 설정 클래스에서 정의한 하나만 존재한다. 반면 스캔 시의 이름과 수동 등록한 이름이 다를 경우에는 두 이름 각각에 대한 빈 객체가 생성된다. 즉 같은 타입에 대해 두 개의 빈 객체가 존재하게 된다. 따라서 해당 타입의 빈을 자동 주입해서 사용할 때에는 @Qualifier 애노테이션을 이용해 이름을 지정해 주어야 한다.

 

 

참고 서적: <초보 웹 개발자를 위한 스프링 5 프로그래밍 입문>

 

초보 웹 개발자를 위한 스프링5 프로그래밍 입문

COUPANG

www.coupang.com

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.


Spring Framework 시리즈

  1. 스프링 프로젝트 시작하기 (Maven)
  2. 스프링 컨테이너(Container) 의미
  3. Dependency, DI, Assembler (의존, 의존 주입, 주입기) 개념 정리
  4. 스프링에서의 의존 주입(DI)의 의미와 사용법
  5. 스프링 애노테이션을 사용한 의존 주입(DI)
  6. 의존 자동 주입(1) - @Autowired 애노테이션
  7. 의존 자동 주입(2) - 빈 이름과 한정사
  8. 의존 자동 주입(3) - @Autowired의 필수 여부, 자동 주입과 명시적 의존 주입
728x90
반응형

댓글