3 minute read


컴포넌트 스캔과 의존 관계 자동 주입 이란?

  • 기존 스프링 빈 등록 시에 @Bean 어노테이션 이나, XML 과 같은 설정파일의 <bean> 태그를 사용하여 일일히 스프링 빈을 등록 해주어야 했다.
  • 시스템이 거대해질수록 등록해야할 스프링 빈이 그에 비례하여 많아지고 이에 누락 및 오타와 같은 문제가 발생하기 쉬워지며, 유지보수에 어려움이 생긴다.
  • 이에 설정 정보가 없더라도 자동으로 스프링 빈을 등록해주는 컴포넌트 스캔이라는 기능이 존재한다.
  • 의존관계 역시 자동으로 주입해주는 @Autowired 어노테이션 또한 존재한다.



@ComponentScan

import org.springframework.context.annotation.ComponentScan;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.context.annotation.FilterType;  
  
@Configuration  
@ComponentScan(  
        excludeFilters = @ComponentScan.Filter(type= FilterType.ANNOTATION, classes = Configuration.class)  
)  
public class AutoAppConfig {  
  
}
  • 컴포넌트 스캔 사용 방법: @ComponentScan 어노테이션을 설정 정보 클래스 (@Configuration) 에 적용.
    • 컴포넌트 스캔을 적용한 설정정보 클래스 내에 @Bean 을 통해 스프링 빈으로 등록한 클래스가 없는 것을 확인할 수 있다.
    • 컴포넌트 스캔은 말 그대로 @Component 어노테이션이 적용된 클래스를 스캔하여 스프링 빈으로 등록한다.
    • 설정 정보 클래스가 여러 개 존재하는 경우와 같이 필터를 통해 컴포넌트 스캔에서 제외 할 수 도 있다.



@Autowired

@Configuration  
public class AppConfig {  

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

	...
	
}
  • ComponentScan 을 사용하기 전에는 위처럼 설정 정보 클래스에서 의존 관계 주입을 해주었다.
  • 하지만 ComponentScan 을 사용한 후, 설정 정보 클래스 내에서 빈을 직접 등록하지 않고, 각 @Component 어노테이션이 적용된 클래스를 스프링 빈으로 자동 등록하기 때문에 의존 관계 주입 또한 @Autowired 메서드를 통해 해당 클래스 내에서 진행해 주어야 한다.



import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Component;  
  
@Component  
public class MemberServiceImpl implements MemberService {  
  
    private final MemberRepository memberRepository;  
  
    @Autowired  
    public MemberServiceImpl(MemberRepository memberRepository) {  
        this.memberRepository = memberRepository;  
    }  
  
    @Override  
    public void join(Member member) {  
        memberRepository.saver(member);  
    }  
  
    @Override  
    public Member findMember(Long memberId) {  
        return memberRepository.findById(memberId);  
    }  
  
    // test  
    public MemberRepository getMemberRepository() {  
        return memberRepository;  
    }  
}
  • 위와 같이 구현 클래스의 생성자에 @Autowired 어노테이션을 적용하여 여러 의존관계 또한 한번에 주입받을 수 있다.



컴포넌트 스캔과 자동 의존관계 주입 동작 과정

@ComponentScan

  • 컴포넌트 스캔을 사용하는 경우 자동 등록되는 스프링 빈의 기본 이름 (Default) 은 해당 클래스명을 사용하되, 가장 앞글자를 소문자로 변경하여 등록되며, 직접 지정 또한 가능하다.
    • Default: MemberServiceImpl(클래스 명) -> memberServiceImpl(스프링 빈 이름)
    • Custom: @Component("memberServiceCustom") 과 같이 직접 빈 이름 부여 가능.



@Autowired

  • 생성자에 @Autowired 를 적용하면, 스프링 컨테이너가 해당 스프링 빈을 찾아 자동 주입한다.
  • 기본 조회 전략은 “타입 조회” 를 통한 동일 타입 빈을 조회하여 주입한다.
    • getBean(MemberRepository.class) 와 동일한 기능을 수행.



컴포넌트 스캔의 탐색 위치 및 기본 스캔 대상

탐색 대상 패키지의 루트 경로 지정

@Configuration  
@ComponentScan(  
        basePackages = "hello.core.member",  
        excludeFilters = @ComponentScan.Filter(type= FilterType.ANNOTATION, classes = Configuration.class)  
)  
public class AutoAppConfig {  
}
  • @ComponentScan 을 설정 파일에 적용 후, basePackages 옵션을 설정해주지 않으면, 라이브러리를 포함한 해당 프로젝트 내 모든 자바 클래스를 스캔하게 되며, 이는 오랜 시간이 걸릴 수 있다.
  • 따라서, 위와 같이 basePackages 옵션을 적용하여 필요한 위치에서부터 그 하위를 탐색하도록 해주자.
    • 이를 지정하지 않으면, @ComponentScan 이 적용된 설정 정보 클래스의 패키지가 시작 위치가 된다.

@ComponentScan TIP

  • @ComponentScan 에 패키지 위치를 지정하지 않고, 설정 정보 클래스의 위치를 프로젝트 최상단에 두고 쓰면 좋다.
  • 스프링 부트 사용 시에는 스프링 부트의 시작 설정 정보인 @SpringBootApplication 을 프로젝트의 시작 루트 경로에 두고 사용하게 되며 해당 설정 내부에 @ComponentScan 이 존재한다.



컴포넌트 스캔의 기본 대상

  • 앞서 언급했듯, 컴포넌트 스캔은 @Component 어노테이션이 적용된 클래스를 대상으로 하며, 아래와 같은 어노테이션 또한 내부적으로 @Component 어노테이션을 가지고 있으므로 컴포넌트 스캔의 대상이 되고, 그에 따른 부가 기능도 수행한다.
    • @Controller : 스프링 MVC 컨트롤러로서 인식.
    • @Service : 스프링 비즈니스 로직 구현.
    • @Repository : 스프링 데이터 접근 계층으로서 인식 및 데이터 계층의 예외를 스프링 예외로 변환.
    • @Configuration : 스프링 설정 정보로서 인식 및 스프링 빈의 싱글톤 유지를 위한 처리 수행.

참고로, 자바 어노테이션에는 상속 관계가 존재하지 않는다.

  • 특정 어노테이션 하위에 존재하는 어노테이션을 인식하는 것은 스프링이 지원하는 기능.



참고:Inflearn - 김영한님_강의(스프링 핵심 원리 기본편)



혹시 이해가 안가거나 추가적인 설명이 필요한 부분, 오류 등의 피드백은 언제든지 환영합니다!

긴 글 읽어주셔서 감사합니다. 포스팅을 마칩니다.

처음으로~

Task Lists

  • 컴포넌트 스캔과 의존 관계 자동 주입 이란?
  • @ComponentScan
  • @Autowired
  • 컴포넌트 스캔과 자동 의존관계 주입 동작 과정
  • 컴포넌트 스캔의 탐색 위치 및 기본 스캔 대상
  • 탐색 대상 패키지의 루트 경로 지정
  • @ComponentScan TIP
  • 컴포넌트 스캔의 기본 대상

Comments