본문 바로가기
Spring/스프링 핵심 원리 - 기본편

6-1. 컴포넌트 스캔

by hk27 2022. 1. 7.
설정 정보 클래스에서 객체를 만들어 의존 관계를 주입하는 것보다 간단한 방법이 없을까요?

 

안녕하세요.

오늘은 컴포넌트 스캔에 대해 알아보겠습니다.

 

앞서 스프링 빈을 등록하기 위해서 설정 정보 클래스를 만들고, 싱글톤을 보장하기 위해 @Configuration을 붙이며, method 위에는 @Bean을 붙인다는 것을 학습하였습니다.

 

공부를 위해 간단한 코드를 작성할 때는 설정 정보 클래스를 만들어서 의존 관계를 직접 주입할 수 있지만, 서비스가 커지면 하나하나 의존 관계를 주입해주고 관리하기 어려울 것입니다. 

게다가 빈 객체를 만들기 위해 객체 생성 메소드 위에 @bean을 각각 붙여줘야 하는데, 붙여주는 것도 귀찮습니다. 

따라서 설정 정보 클래스를 간소화하고, 의존 관계를 자동으로 주입하는 방법을 알아보겠습니다. 

이를 위해서 @ComponentScan과 @Autowired를 사용할 수 있습니다.

 

@ComponentScan(컴포넌트 스캔)

먼저 @ComponentScan을 알아봅시다. 

@Component Scan을 쓰면, 빈으로 등록될 준비를 마친 클래스(@Component, @Controller, @Service, @Repository 어노테이션을 붙인 클래스)들을 스캔하여 빈으로 등록합니다[2]. 

 

Component Scan을 사용하려면 설정 정보 클래스에 @ComponentScan을 붙여주면 됩니다. 사용 예시 코드를 봅시다.

@Configuration
@ComponentScan(excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = Configuration.class))
public class AutoAppConfig {
}

@Configuration과 @ComponentScan 어노테이션이 붙어있습니다. @Configuration은 싱글톤을 보장하기 위해 붙인 것이고(https://passionate.tistory.com/13 참고) @ComponentScan은 '@Component'가 붙은 클래스를 scan하라는 의미입니다. 

눈에 띄는 것은, 설정 정보 클래스가 비어있다는 것입니다. 앞서 사용한 AppConfig 설정 정보 클래스에는 객체를 생성하는 메소드들이 있었고, 그 위에 @Bean이 붙어있었는데 그런 코드를 작성하지 않아도 됩니다.

참고로 @ComponentScan 옆의 소괄호에 excludeFilter 정보가 있는데, 이는 이후 알아보겠습니다.

 

클래스가 컴포넌트 스캔의 대상이 되려면 @Component 어노테이션을 붙여야 합니다.

bean에 등록할 4개의 클래스에 @Component를 붙입니다. 

 

스프링 빈에 객체가 잘 등록되었는지 확인해봅시다.

스프링 컨테이너를 사용할 때는, 기존 방식과 그대로 ApplicationContext를 사용하면 됩니다.

public class AutoAppConfigTest {
    @Test
    void basicScan() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
        MemberService memberService = ac.getBean(MemberService.class);
        assertThat(memberService).isInstanceOf(MemberService.class);
    }
}

 

기존에 AppConfig 클래스를 활용하여 @Bean을 달아서 객체를 생성하였을 때는 아래 코드처럼 생성자를 부를 때 의존관계를 주입해주었습니다. 

@Configuration
public class AppConfig {
	@Bean
	public MemberService memberService() {
		return new MemberServiceImpl(memberRepository());
	}
    ...
}

그런데 이제는 이런 코드가 없죠.

그렇다면 의존 관계를 어떻게 주입할까요?

'@Autowired'를 사용하여 주입할 수 있습니다. 

 

@Autowired(의존관계 자동 주입)

@Autowired는 의존 관계를 자동으로 주입하는 기능입니다. 

MemberServiceImpl 클래스를 살펴봅시다.

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

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

생성자 위에 @Autowired가 있습니다. 스프링은 Autowired 어노테이션을 보면, 자동으로 해당 스프링 빈을 찾아서 주입합니다. getBean(MemberRepository.class)와 동일하게 작동합니다.

 

 

컴포넌트 스캔과 의존관계 주입이 어떻게 동작하는지 그림으로 알아봅시다.

1. @ComponentScan

@ComponentScan은 @Component가 붙은 모든 클래스를 스프링 빈으로 등록합니다.

빈 이름은 클래스명의 맨 앞글자를 소문자로 바꿔서 사용합니다.

 

2. @Autowired 

생성자에 @Autowired를 지정하면, 스프링 컨테이너가 자동으로 해당 스프링을 찾아서 주입합니다. 

예를 들어서 위의 예시에서는 MemberRepository 객체가 필요합니다. 스프링 컨테이너는 memberRepository와 같은 타입, 혹은 자식 타입을 찾아서 의존관계를 자동으로 주입합니다. 

참고로 1->2로 단계가 완전히 구분되어 작동하는 것은 아닙니다. ComponentScan으로 스프링 빈을 등록하면서 의존관계 주입이 동시에 일어나기도 합니다. 두 사이클이 존재한다는 점을 이해하면 됩니다. 

 

탐색 위치 

@ComponentScan이 적용된 설정 정보 클래스를 포함한 하위 패키지는 모두 컴포넌트 스캔의 대상이 됩니다.

이런 설정 정보는 프로젝트를 대표하는 정보이기 때문에 프로젝트의 시작 루트 위치에 두는 것이 좋습니다.

그렇게 하면 프로젝트의 모든 파일이 컴포넌트 스캔의 대상이 됩니다. 

이것이 기본값인데, 탐색 위치를 바꿀 수도 있습니다. 아래 코드처럼 @ComponentScan 어노테이션에 괄호로 패키지를 설정하면 됩니다. 

@ComponentScan(basePackages = "hello.core", ... )
@ComponentScan(basePackages = {"hello.core", "hello.service"}, ... )

 

컴포넌트 스캔 대상

컴포넌트 스캔의 대상은 기본적으로 @Component이고, @Controller, @Service, @Repository, @Configuration도 지원합니다. 이들 클래스의 소스 코드를 보면 @Component가 포함되고 있습니다.

@Component
public @interface Controller {}
@Component
public @interface Service {}
@Component
public @interface Configuration {}

참고로 어노테이션에는 상속 관계라는 개념은 없어서 자바에서 지원하는 기능이 아니고, 스프링에서 지원하는 기능입니다.

 

어노테이션에 따라서 스프링에서 부가 기능을 지원하기도 합니다.

사용 용도와 부가 기능을 표로 정리해보았습니다. 

 

Annotation 사용 용도 스프링에서 수행하는 부가 기능
@Component 컴포넌트 스캔  
@Controller 스프링 MVC 컨트롤러 스프링 MVC 컨트롤러로 인식
@Service 스프링 비즈니스 로직 특별한 처리는 없으나, 개발자들이 핵심 비즈니스 로직이 있음을 인식하는 데 도움이 됨
@Repository 스프링 데이터 접근 계층 스프링 데이터 접근 계층으로 인식하고, 데이터 계층의 예외를 스프링 예외로 변환
@Configuration 스프링 설정 정보 스프링 설정 정보로 인식하고, 스프링 빈이 싱글톤을 유지하도록 추가 처리

 

 

 

인프런  '스프링 핵심 원리 - 기본편' 강의를 듣고 공부하며 정리한 자료입니다. 

잘못된 부분은 피드백 주시면 감사하겠습니다. 

글 읽어주셔서 감사합니다 :-)

 

참고자료

[1] 스프링 핵심 원리 - 기본편, 섹션 6. 컴포넌트 스캔 https://www.inflearn.com/course/스프링-핵심-원리-기본편

[2] https://velog.io/@hyun-jii/%EC%8A%A4%ED%94%84%EB%A7%81-component-scan-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EB%8F%99%EC%9E%91-%EA%B3%BC%EC%A0%95

 

 

 

 

 

댓글