@SpringBootApplication // 내부에 @ComponentScan 포함
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
이전 편에서는 @ComponentScan을 통해 빈을 자동 등록하는 기본 기능과 @Autowired를 통한 생성자 주입까지 살펴봤다. 이번 편에서는 컴포넌트 스캔의 탐색 위치, 스테레오타입 어노테이션, 필터 사용법, 빈 충돌 처리 방식까지 더 깊게 들어가본다.
1. 컴포넌트 스캔의 탐색 위치
@ComponentScan은 어디서부터 클래스를 스캔할지를 정할 수 있다.
@ComponentScan(basePackages = "hello.core.member")
- basePackages를 지정하면 해당 패키지부터 하위 패키지까지 스캔
- 여러 개 지정도 가능: basePackages = {"hello.core", "hello.service"}
기본값은?
basePackages를 지정하지 않으면, @ComponentScan이 붙은 클래스의 패키지부터 시작된다.
그래서 일반적으로 설정 클래스(AutoAppConfig 등)는 최상단 루트 패키지에 두는 게 관례다.
@SpringBootApplication // 내부에 @ComponentScan 포함
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2. 스테레오타입 어노테이션
@Component 외에도 스프링은 특정 용도에 맞춘 어노테이션들을 제공한다.
어노테이션 | 설명 |
@Controller | 웹 MVC 컨트롤러 역할로 인식 |
@Service | 비즈니스 로직 계층으로 인식 (실제로는 기능 없음) |
@Repository | 데이터 계층으로 인식, 예외 변환 처리 |
@Configuration | 설정 정보로 인식, CGLIB을 이용한 싱글톤 보장 처리 |
이들은 모두 내부에 @Component가 포함된 메타 어노테이션이기 때문에 컴포넌트 스캔의 대상이 된다.
@Service
public class MyService {
...
}
※ 어노테이션은 상속이 안 되지만, 메타 어노테이션 덕분에 스프링이 인식할 수 있는 것이다.
3. 필터 기능
스캔 대상 중 일부만 포함하거나 제외하고 싶을 때는 필터를 사용할 수 있다.
@Configuration
@ComponentScan(
includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class),
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = MyExcludeComponent.class)
)
public class ComponentFilterAppConfig {
}
- includeFilters: 특정 조건을 만족하는 클래스만 포함
- excludeFilters: 특정 조건을 만족하는 클래스는 제외
테스트 예시
@Test
void filterScan() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ComponentFilterAppConfig.class);
BeanA beanA = ac.getBean("beanA", BeanA.class);
assertThat(beanA).isNotNull();
assertThrows(NoSuchBeanDefinitionException.class, () ->
ac.getBean("beanB", BeanB.class));
}
4. 자동 등록과 수동 등록 충돌
컴포넌트 스캔으로 자동 등록한 빈과 개발자가 직접 등록한 수동 빈이 이름이 겹칠 경우 충돌이 발생한다.
자동 빈 vs 자동 빈
- 동일한 이름의 자동 등록 빈이 두 개 이상이면 오류 발생
수동 빈 vs 자동 빈
- 과거에는 수동 빈이 자동 빈을 무시하고 덮어씀
- 현재는 오류를 발생시켜 애플리케이션이 실행되지 않도록 기본값이 바뀌었다
Consider renaming one of the beans or marking one of them as @Primary.
설계 원칙 정리
- 컴포넌트 스캔은 @Component 계열 어노테이션이 붙은 클래스를 자동으로 등록
- @Autowired로 의존성 자동 주입
- @Controller, @Service, @Repository, @Configuration 등도 컴포넌트 대상
- basePackages 지정 시 탐색 위치를 명시적으로 관리할 수 있음
- 필터 기능을 통해 포함/제외 대상 설정 가능
- 자동/수동 빈 충돌 시, 스프링 부트는 오류를 발생시킴
'Spring' 카테고리의 다른 글
[Spring 완전 정복 시리즈] 18편 - 의존관계 자동 주입 방식 완전 정리 (0) | 2025.07.30 |
---|---|
[Spring 완전 정복 시리즈] 17편 - 다양한 의존관계 자동 주입 방식 (1) | 2025.07.29 |
[Spring 완전 정복 시리즈] 15편 - 컴포넌트 스캔의 시작 (0) | 2025.07.29 |
[Spring 완전 정복 시리즈] 14편 - @Configuration과 바이트코드 조작의 마법 (1) | 2025.07.28 |
[Spring 완전 정복 시리즈] 13편 - 싱글톤 컨테이너의 원리와 설계 주의점 (1) | 2025.07.28 |