jhhan의 블로그

스프링 코어(8) - 컴포넌트 스캔_1 본문

Spring

스프링 코어(8) - 컴포넌트 스캔_1

jhhan000 2021. 5. 11. 23:56

이번 포스트에서는 컴포넌트 스캔에 대해서 알아보겠습니다.

 

지금까지 배운 내용으로는

스프링 빈을 등록할 때는 자바 코드의 @Bean 을 통해 설정 정보에 직접 등록했습니다.
(혹은 XML의 <bean>을 통해서도 가능)

이렇게 등록하는 것은 등록할 것이 적을 때는 가능합니다.

근데 여기서 조금만 확장을 해보면 10개 등록하는 것이 어려운 일이 아니게 될 것입니다.

그러면 실무에서는 이것보다 훨씬 더 많은 빈이 등록되어야 할텐데

그걸 일일이 등록해야 할까요?

그건 비효율적이라고 생각하고, 아마 중복 등록이나 미등록 같은 오류가 일어날 확률도 높습니다.

 

그래서 스프링에서는 설정 정보가 없어도 자동으로 스프링 빈을 등록할 수 있게 합니다.

바로 '컴포넌트 스캔' 이라는 기능입니다.

(그리고 의존관계 자동 주입으로 @Autowired를 사용합니다.)

아마 스프링을 조금 혹은 그 이상 사용해 보신 분이라면 @Autowired라는 어노테이션은 자주 보셨을 것 같습니다. ㅎㅎ

 

기존의 코드에 새로운 코드를 덧붙이면서 진행할 수도 있지만,

옛날에 썼던 코드와 지금 쓰는 코드를 비교해가면서 코딩을 하는 것도 초보의 입장에서는 필요하다고 생각합니다.

그래서 기존의 코드는 가능한 남기면서 진행합니다.

 

AppConfig.java라는 파일이 이미 있으므로

AutoAppConfig.java라는 파일을 만들어서 진행합니다.

위치는 저기에 합니다.

다음과 같이 작성합니다.

@Configuration
@ComponentScan( // 이 애노테이션이 있어야 자동적으로 컴포넌트 스캔이 가능
        excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)
)
public class AutoAppConfig {
    
}
  • 자동으로 등록을 할 예정이기 때문에 특별히 작성할 코드는 없습니다.
  • 대신 @ComponentScan 어노테이션을 붙입니다.
  • @ComponentScan이라는 어노테이션을 사용하면 @Configuration이 붙은 정보들이 자동 등록이 되기 때문에,
       기존에 등록했던 정보들도 등록됩니다.
  • 이럴 경우 중복 등록이 될 수도 있기 때문에 excludeFilters를 사용해서 컴포넌트 스캔 대상에서 제외합니다.
  • 혹은 기존 예제 코드를 지우고 진행하셔도 됩니다. ㅎㅎ

 

[

참고사항 : @Configuration의 어노테이션을 살펴보면 @Component 어노테이션이 붙어있기 때문에 

              컴포넌트 스캔의 대상이 됩니다.

]

 

이제 컴포넌트 스캔의 대상이 될 녀석들한테 @Component 어노테이션을 붙이면 됩니다.

MemoryMemberRepository.java
RateDiscountPolicy.java
MemberServiceImpl.java
OrderServiceImpl.java

MemoryMemberRepository, RateDiscountPolicy, MemberServiceImpl 클래스에 어노테이션을 추가했습니다.

그리고 AppConfig.java 파일에서 설정했던 의존관계 주입도 클래스 안에서 따로 해야합니다.

그래서 @Autowired 라는 어노테이션을 사용했습니다.

그리고 @Autowired를 사용하면 여러 의존관계를 한번에 주입받는 것이 가능합니다.

 

그럼 이제 컴포넌트 스캔이 제대로 되었는지 테스트를 해봅니다.

scan이라는 패키지를 생성하고 그 밑에 AutoAppConfigTest.java를 추가했습니다.

import static org.assertj.core.api.Assertions.*;

public class AutoAppConfigTest {

    @Test
    void BasicScan() {
        // 반드시 AutoAppConfig를 사용할 것
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);

        MemberService memberService = ac.getBean(MemberService.class);
        assertThat(memberService).isInstanceOf(MemberService.class);
    }
}
  • 설정정보는 AutoAppConfig 클래스를 사용해야 정확한 테스트가 이루어집니다.
  • 실행을 하면 잘 동작하는 것을 알 수 있습니다.

로그 창에 기존에 등록한 빈들이 모두 나타나는 것을 확인할 수 있습니다.

 

 

이제 다른 부분을 한번 고려해보겠습니다.

'컴포넌트 스캔'을 모든 자바 클래스에 적용하면 시간이 오래 걸릴 것입니다.

그래서 이런 시간낭비를 줄이기 위해 컴포넌트 스캔의 시작위치를 지정할 수도 있습니다.

@ComponentScan( // 이 애노테이션이 있어야 자동적으로 컴포넌트 스캔이 가능
        basePackages = "hello.core.member"
)
  • basePackages: 탐색할 패키지의 시작위치를 지정합니다.
  • 시작 위치부터 하위 패키지까지 모두 탐색
@ComponentScan( // 이 애노테이션이 있어야 자동적으로 컴포넌트 스캔이 가능
        basePackages = {"hello.core.member", "hello.core.order"}
)
  • 이런 식으로 시작위치가 여러 개 일수도 있습니다.

 

만약 basePackages 같은 옵션을 사용하지 않는다면

@ComponentScan이 붙은 설정 정보의 패키지가 시작위치가 됩니다.

(사실 basePackages 옵션을 잘 사용하는 편은 아니라고 합니다.)

 

요즘에 권장하는 방법으로는

설정 정보 클래스의 위치가 프로젝트 최상단에 있게 하는 것입니다.

그렇기 때문에 AutoAppConfig 생성을 hello.core 내 최상단에 위치하게 했습니다.

그리고 스프링 자체적으로 이런 설정을 기본으로 제공합니다.

CoreApplication 파일을 열어보겠습니다.

@SpringBootApplication이라는 어노테이션을 볼 수 있습니다.

그러면 이 어노테이션에 대해서 자세히 알아보죠.

@ComponentScan 어노테이션을 가지고 있습니다.

이런 식으로 스프링 자체적으로 설정을 해주고 있는 것을 알 수 있습니다.

 

 

컴포넌트 스캔의 대상이 되게 하기 위해 @Component 어노테이션을 사용했는데, 그 이외에도 다른 것들이 있습니다.

  • @Component: 컴포넌트 스캔에서 사용. 기본
  • @Configuration: 스프링 설정 정보에서 사용
  • @Controller: 스프링 MVC 컨트롤러에서 사용
  • @Service
    • 이 어노테이션은 특별한 처리를 하지는 않음
    • 대신 이 어노테이션을 사용하면 개발자들이 핵심 비즈니스 로직이 여기에 들어있다고 인식함
  • @Repository: 스프링 데이터 접근 계층으로 인식하게 함

[

참고: 어노테이션 사이에는 상속관계가 없습니다. 그런데도 저런 상속같은 관계로 로직이 돌아갈 수 있는 이유는

       스프링에서 지원하기 때문에 가능한 부분입니다.

       자바 자체로는 어노테이션의 상속은 이루어지지 않습니다.

]

 

 

이렇게 컴포넌트 스캔에 대해서 알아봤습니다.

다음 포스트에서는 나머지에 대해 더 알아보겠습니다.

 

여기서 마치겠습니다.

 

 

 

출처: 인프런 - 스프링 핵심원리(기본편) by 김영한