컴포넌트 스캔(@ComponentScan)에 대해 알아보자

2024. 6. 4. 23:00·BackEnd/Spring

스프링에서 빈을 등록하는 방법으로 아래 두 가지 방법이 있었습니다.

  • @Configuration 클래스 내의 메소드에 @Bean 을 명시해 주는 방법
  • XML <bean> 을 이용해 명시하는 방법

그러나 스프링 에서는 위 두가지 정보가 없어도 스프링 빈을 등록하는 방법이 있습니다.

 

컴포넌트 스캔이란?

컴포넌트 스캔은 이름 그대로 @Component 어노테이션이 붙은 클래스를 찾아 스프링 빈으로 등록해 주는 것입니다. 이 컴포넌트 스캔 기능을 사용하기 위해서는 @ComponentScan 어노테이션을 설정 정보 클래스에 붙여주면 됩니다.

 

간단한 테스트를 해보겠습니다.

 

1. 두개의 컴포넌트 클래스를 작성

FruitRepository.class

 @Component
 public class FruitRepository {

     public void save(Fruit fruit) {
         System.out.println("fruit = " + fruit.getName());
     }
 }

FruitService.class

@Component
public class FruitService {

    private final FruitRepository fruitRepository;

    public FruitService(FruitRepository fruitRepository) {
        this.fruitRepository = fruitRepository;
    }

    public void saveFruit(Fruit fruit) {
        fruitRepository.save(fruit);
    }
}

2. 컴포넌트 클래스를 스캔할 수 있는 설정 클래스  @Component 클래스를 작성
내부에는 아무런 내용도 작성하지 않았으며 클래스에  @ComponentScan 어노테이션을 작성하였습니다.

@Configuration
@ComponentScan
public class ComponentInfo {
}

3. 확인을 위한 테스트 코드를 작성

class ComponentInfoTest {

    @Test
    void componentScanTest() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ComponentInfo.class);
        FruitService fruitService = ac.getBean(FruitService.class);
        FruitRepository fruitRepository = ac.getBean(FruitRepository.class);

        System.out.println("fruitRepository = " + fruitRepository);
        System.out.println("fruitService = " + fruitService);

        Assertions.assertThat(fruitService).isInstanceOf(FruitService.class);
        Assertions.assertThat(fruitRepository).isInstanceOf(FruitRepository.class);
    }
}

4. 테스트 결과 확인

- 테스트 성공 확인

- componentInfo, fruitRepository, fruitService 세개의 클래스가 싱글톤 빈으로 등록된 로그 확인

 

기존에 @Configuration 클래스에 메서드를 직접 작성하여 @Bean 을 등록했었습니다. 그러나 이번 테스트에서는 아무런 내용을 작성하지 않고 @Component 와 @ComponentScan 을 이용하여 자동으로 빈을 등록했습니다. 이때 스프링 빈의 이름은 클래스명의 맨 앞글자만 소문자로 변경되어 사용하는 것을 로그를 통해 확인할 수 있습니다.

  • FruitRepository → fruitRepository
  • FruitService → fruitService

기본으로 설정되는 빈 이름이 아닌 다른 이름을 사용하고 싶다면 @Component("빈이름") 으로 이름을 부여해줄 수 있습니다.

 

 

컴포넌트 스캔 범위

기본적으로 컴포넌트 스캔은 해당 설정 클래스 패키지부터 하위 패키지까지를 스캔합니다.

그러나 항상 전체 범위를 다 스캔하면 시간이 오래걸리며 특정 클래스 범위에 대해서만 설정하고 싶을 수 있습니다. 그럴 때는 컴포넌트 스캔의 basePackages옵션을 사용하여 설정할 수 있습니다. FruitRepository를 repository 패키지 내로 이동시켜서 테스트 해보겠습니다.

 

1. 기존 ComponentInfo 클래스의 컴포넌트 스캔에 옵션을 설정

@ComponentScan(basePackages = “hello.core2.component.repository”)

@Configuration
@ComponentScan(basePackages = "hello.core2.component.repository")
public class ComponentInfo {
}

2. FruitService 는 repository 패키지 내에 존재하지 않으므로 빈으로 등록되지 않을 것입니다. 등록되지 않은 빈을 조회 시 NoSuchBeanDefinitionException 예외가 발생하게 됩니다. assertThrows를 이용하여 예외 테스트를 해보겠습니다.

@Test
void notFoundComponentTest() {
    ApplicationContext ac = new AnnotationConfigApplicationContext(ComponentInfo.class);
assertThrows(NoSuchBeanDefinitionException.class, () -> ac.getBean(FruitService.class));

    FruitRepository fruitRepository = ac.getBean(FruitRepository.class);
    System.out.println("fruitRepository = " + fruitRepository);
assertThat(fruitRepository).isInstanceOf(FruitRepository.class);
}

3. 테스트 결과 확인

테스트가 성공하는 것을 확인하여 해당 예외가 발생했다는 것을 알 수 있습니다.
또한, 로그를 통해 FruitRepository는 정상적으로 빈에 등록되어 호출되는 것을 확인할 수 있었습니다.

위에서 사용했듯이 대상 패키지를 정하는 방법은 basePackages를 사용하여 탐색 패키지를 직접 지정할 수 있고 basePackageClasses를 사용하여 해당 클래스가 포함된 클래스 패키지를 기준으로 정할 수도 있습니다.

 

설정 정보 위치

보편적으로 설정정보는 클래스의 최상단에 둡니다. 주로 사용하는 스프링 부트에서는 @SpringBootApplication 를 이 프로젝트 시작 루트 위치에 두는 것이 관례로, 이 어노테이션 내부에 @ComponentScan이 들어있어 대표 시작 클래스에서 자동으로 컴포넌트들을 스캔해준다는 것을 알 수 있습니다.

 

컴포넌트 스캔 대상

스프링 부트 개발을 하다보면 @Component 보다는 @Controller , @Service , @Repository 등과 같은 계층을 나타내는 어노테이션을 주로 사용합니다. 이 클래스들의 내부를 보면 모두 @Component 이 붙어있는 것을 확인할 수 있습니다.

사실 자바 자체에서는 어노테이션은 상속 관계가 없습니다. 이처럼 어노테이션이 어떤 어노테이션의 속성을 가지고 있는지 알 수 있는 것은 자바 자체가 아닌 스프링에서 지원되는 기능임을 알아야합니다. 이외에도 어떤 어노테이션이 컴포넌트 대상이 되는지 확인해보겠습니다.

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

 

필터

SpringbootApplication 내의 @ComponentScan 을 보면 무언가 많은 옵션들이 존재하는 것을 볼 수 있습니다. 위 옵션들이 어떤 정보를 가지고 있는지 알아보겠습니다.

  • includeFilters : 컴포넌트 스캔 대상을 추가로 지정
  • excludeFilters : 컴포넌트 스캔에서 제외할 대상을 지정

FilterType 옵션

  • ANNOTATION : 기본값, 애노테이션을 인식해서 동작한다.
  • ASSIGNABLE_TYPE : 지정한 타입과 자식타입을 인식해서 동작한다.
  • ASPOECTJ : AspectJ패턴 사용
  • REGEX : 정규 표현식
  • CUSTOM : TypeFilter라는 인터페이스를 구현해서 처리

 

 

'BackEnd > Spring' 카테고리의 다른 글

[Spring] 빈 스코프(BeanScope)  (0) 2024.06.17
싱글톤 컨테이너(Singleton Container)란 무엇인가  (0) 2024.06.03
[스프링] SpringContainer, BeanFactory, ApplicationContext  (0) 2024.05.21
'BackEnd/Spring' 카테고리의 다른 글
  • [Spring] 빈 스코프(BeanScope)
  • 싱글톤 컨테이너(Singleton Container)란 무엇인가
  • [스프링] SpringContainer, BeanFactory, ApplicationContext
hwa2
hwa2
  • hwa2
    나도! 기억하고싶었어!
    hwa2
  • 전체
    오늘
    어제
    • 분류 전체보기 (27)
      • 공부 (4)
        • 네트워크 (2)
        • 알고리즘 (2)
        • 자료구조 (0)
      • 디자인패턴 (1)
      • DevOps (1)
        • 데이터베이스 (1)
      • BackEnd (11)
        • JAVA (7)
        • Spring (4)
      • FrontEnd (6)
        • Javascript (6)
      • 코딩테스트 풀어보자! (1)
      • 해결해보자. (1)
      • 플젝..해보자.. (2)
      • 우테코 7기 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    우테코 7기
    프리코스
    자바스크립트
    회고
    FunctionalInterface
    readline
    우테코
    nodejs
    싱글톤패턴
    멋쟁이사자처럼후기
    TemplateMethodPattern
    jdk8
    싱글톤컨테이너
    우테코7기
    함수형인터페이스
    Java
    JS
    node.js
    스레드 동기화
    JavaScript
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
hwa2
컴포넌트 스캔(@ComponentScan)에 대해 알아보자
상단으로

티스토리툴바