안녕하세요. 개발자 Jindory입니다.
오늘은 Component Scan이란 무엇인지 알아보고 Component Scan 과정에 대해서 글을 작성해보려고 합니다.
[ 글 작성 이유 ]
ControllerAdvice 어노테이션 동작 과정을 공부하다 Component Scan 과정에 대해서 이해하지 못한것 같아, Component Scan이 무엇인지, 어떤 동작 과정이 있는지 알아보기 위해 글을 작성하게 되었습니다.
1. Component Scan이란?
Component Scan이란 "Spring framework에서 사용되는 기능으로 어플리케이션 내에 존재하는 @Component 어노테이션이 붙은 클래스들을 자동으로 Bean으로 등록해주는 역할을 의미합니다. Component Scan이라는 단어에서 Component를 검색해서 찾아내다라는 의미임을 유추 할 수 있습니다. Srping Container에서 사용 할 Bean을 자동으로 등록하여 개발자가 일일히 Bean 등록 및 관리하기 보다는 기능 개발에 집중할 수 있도록 제공하는 기능입니다.......
저는 위 설명에 대해서 이해하기 위해서 아래와 같은 궁금증을 먼저 해결해야 했습니다
(과거에 공부하지 않은 나의 눈물 ㅠnㅠ)
- Component Scan을 하는 이유가 뭐지?
- Class를 Bean으로 등록해주는 이유가 뭐야?
- @Component 어노테이션을 붙혀야만 Component Scan이 되는건가....?
1-1 Component Scan을 하는 이유가 뭘까?
Component Scan을 하는 이유는 기존에는 @Bean을 통해서 수동적으로 스프링 Bean을 등록했지만, 등록 해야 할 Bean 개수가 증가 할수록 관리가 어려워짐에 따라서 Bean을 자동으로 등록해야할 필요성이 생겨서 입니다.
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
[ 기존 Bean 등록 방법 ]
(여기서 Bean을 등록해야하는 이유가 바로 궁금해 졌지만, 일단 Component Scan을 하는 이유를 마저 정리하고 가겠습니다....)
Component Scan은 아래와 같이 @Configuration을 선언한 Class에서 @ComponentScan 어노테이션을 통해 Scan할 Bean의 대상 범위를 지정하여 해당 범위에 있는 Bean을 자동으로 등록해 주는 역할을 합니다.
@Configuration
@ComponentScan(basePackages = "com.example.myapp")
public class AppConfig {
// 다른 설정 및 Bean 정의
}
그렇다면 Component Scan을 함으로써 얻을 수 있는 이점은 무엇일까요?
- 자동으로 Bean 등록
- Component Scan을 통해 개발자가 직접 Bean을 등록하지 않아도 Spring 컨테이너가 자동으로 관리할 수 있습니다. 이를 통해 개발자의 수작업 부담을 줄일 수 있습니다.
- 의존성 자동 주입
- Component Scan으로 등록된 Bean들 간의 의존성을 자동으로 주입할 수 있습니다.
- @Autowired 어노테이션을 통해 편리하게 의존성을 주입받을 수 있습니다.
- 유연한 구조
- Component Scan을 통해 어플리케이션 구조를 유연하게 구성할 수 있습니다.
- 새로운 기능 추가시 해당 클래스에 @Component 어노테이션만 추가하면 자동으로 Bean등록 및 의존성 관계를 자동 주입해 줍니다.
- 확장성 향상
- Component Scan은 Spring의 Inversion of Control(IoC) 및 Dependency Inject(DI) 원칙을 구현하는 핵심 기능입니다.
- 이를 통해 어플리케이션의 확장성과 유지보수성이 향상됩니다.
위와 같은 이유로 Spring에서 Component Scan 과정을 통해 Bean을 자동으로 등록 및 관리하는 기능을 제공하는 것입니다.
1-2 Java 객체를 Bean으로 등록해 주는 이유는 뭘까요....?
우리가 만드는 Class(객체)를 효율적으로 사용하기 위해서 Spring에서는 Spring Container라는 공간을 통해 Java 객체를 관리합니다. Spring에서는 관리되는 Java 객체를 Bean이라고 하는데, 스프링 컨테이너에서 이 Bean의 생성부터 소멸까지 개발자를 대신하여 관리해준다고 생각하면 됩니다.
클래스를 Bean으로 Spring Container에 등록했을 경우 아래와 같은 이점을 얻을 수 있습니다.
- 의존성 관리 및 제어
- Bean으로 등록하면 Spring Container가 Bean의 생성, 관리, 주입 등을 담당하게 됩니다.
- 이를 통해 어플리케이션 내 클래스 간 의존성을 효과적으로 관리할 수 있습니다.
- 유연성 및 확장성 향상
- Bean으로 등록하면 Class 간 결합도가 낮아져 유연성과 확장성을 높일 수 있습니다.
- 필요에 따라서 Bean의 구현체를 쉽게 변경할 수 있습니다.
- 테스트 용이성 증대
- Bean으로 등록된 클래스를 독립적으로 테스트 할 수 있습니다.
- 의존성 주입을 통해 테스트 환경을 쉽게 구축할 수 있습니다.
- 관심사 분리
- Bean으로 등록하면 클래스의 생성, 관리, 주입 등의 관심사를 Spring 컨테이너가 담당하게 됩니다.
- 이를 통해 클래스 자체의 핵심 기능에 집중할 수 있습니다.
- 설정의 재사용성
- Bean으로 등록된 클래스는 다른 Bean에서 쉽게 재사용할 수 있습니다.
- 이를 통해 개발 생산성을 높일 수 있습니다.
- Bean 생명주기 관리
- Bean의 초기화, 생성, 소멸 등의 작업을 개발자가 하지 않고, Spring Container에서 관리해 줍니다.
- 이로써 개발자는 비즈니스 로직 구현에 집중할 수 있게 됩니다.
결국 Spring Framework에서 객체를 편리하게 관리하기 위해서 Bean 등록이 필요한것이며, 이러한 Bean 등록을 편하게 해주는 작업이 Component Scan이라는것을 알 수 있습니다.
1-3 그렇다면 Component Scan을 하기 위해서 Bean으로 등록하고 싶은 Class에 @Coponent 어노테이션을 선언해야만 하는가?
Component Scan을 설정하는 방법은 Java 파일로 설정하는 방법과 XML로 설정하는 방법 이렇게 2가지가 있습니다.
- Java Configuration 클래스
- @Configuration 어노테이션이 붙은 클래스에서 @Bean 메서드를 통해서 직접 Bean을 등록
@Configuration @ComponenScan(basePackages = "com.base.package") public class AppConfig { @Bean public MyBean myBean() { return new MyBean(); } }
- @Configuration 어노테이션이 붙은 클래스에서 @Bean 메서드를 통해서 직접 Bean을 등록
- XML 설정
- XML 설정 파일에 <bean> 태그를 사용하여 직접 Bean을 등록
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="myBean" class="com.example.MyBean" /> </beans>
- XML 설정 파일에 <bean> 태그를 사용하여 직접 Bean을 등록
Component Scan에 대해서 알아봤으니, 다음으로 Component Scan 과정에 대해서 알아보도록 하겠습니다.
2. Component Scan 과정
Component Scan은 Component Scan 지점을 설정하고, 대상 범위를 지정하여, 해당 범위에 존재하는 Java Class를 Bean으로 등록 및 의존성 관계를 맺어주는 단계입니다. Component Scan 과정은 아래와 같습니다.
- 시작 지점 설정
- Spring 애플리케이션은 특정 패키지나 클래스에서 시작하여 컴포넌트 스캔을 진행합니다.
- @ComponentScan 애노테이션을 사용하여 스캔 시작 지점을 지정할 수 있습니다.예: @ComponentScan(basePackages = "com.example.myapp")
- 위와같이 basPackage나 basePackageClasses를 사용한다면 해당 패키지부터 하위 패키지까지 스캐닝을 할 수 있습니다.
- 클래스 스캔
- Spring 컨테이너는 지정된 시작 지점부터 재귀적으로 하위 패키지를 스캔합니다.
- 스캔 중 @Component, @Service, @Repository, @Controller 등의 애노테이션이 붙은 클래스를 찾습니다.
- Bean 등록
- 스캔된 클래스 중 애노테이션이 붙은 클래스는 Spring Bean으로 자동 등록됩니다.
- 이때 클래스 이름의 첫 글자를 소문자로 하여 Bean의 이름이 지정됩니다.
- 예: @Component class MyService → Bean 이름 myService
- 의존성 주입
- 등록된 Bean 간의 의존성은 자동으로 주입됩니다.
- @Autowired 애노테이션을 사용하여 의존성을 명시적으로 표현할 수 있습니다.
- 추가 설정
- @ComponentScan에 다양한 옵션을 지정하여 스캔 범위를 조정할 수 있습니다.
- 예: @ComponentScan(excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ExcludedClass.class))
이처럼 Component Scan 과정을 통해 Spring 컨테이너는 애플리케이션 내 Bean을 자동으로 등록하고 의존성을 관리할 수 있습니다. 이는 개발자의 생산성을 높이고 애플리케이션의 유연성과 확장성을 향상시키게 됩니다.
참고로 SpringBoot를 사용하면 @SpringBootApplication 어노테이션 안에 @ComponentScan 어노테이션이 포함되어 있어서 @ComponentScan을 따로 설정해주지 않아도 Component Scan을 할 수 있습니다.
@SpringBootApplication
public class RestfulServiceApplication {
public static void main(String[] args) {
ApplicationContext ac = SpringApplication.run(RestfulServiceApplication.class, args);
String[] allBeanNames = ac.getBeanDefinitionNames();
}
}
@SpringBootApplication 어노테이션 내부
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
... 생략 ...
}
이렇게 Component Scan에 대해서 알아봤습니다.
혹시라도 정정할 내용이나 추가적으로 필요하신 정보가 있다면 댓글 남겨주시면 감사하겠습니다.
오늘도 Jindory 블로그에 방문해주셔서 감사합니다.
[ 참조 ]
https://docs.spring.io/spring-framework/reference/core/beans/classpath-scanning.html
'개발 > Spring' 카테고리의 다른 글
[Spring] Controller에서 Exception 처리(@ExceptionnHandler와 @ControllerAdvice) (0) | 2024.05.28 |
---|---|
[Spring] Transaction Propagation Model과 Isolation Level (0) | 2024.02.11 |
[Spring] Spring 초기 데이터베이스 데이터 설정 방법 (0) | 2022.07.03 |
[Spring] 의존성 주입의 정의 및 의존성 주입 3가지 방식 (생성자 주입, 수정자 주입, 필드 주입) (0) | 2022.04.30 |
[Spring Boot] Thymeleaf 사용하기 (0) | 2022.03.06 |