Spring의 ComponentScan 이해하기: @ComponentScan의 동작 원리와 활용법
Spring Framework에서 의존성 주입(Dependency Injection)을 자동으로 처리해주는 강력한 기능 중 하나가 바로 **컴포넌트 스캔(Component Scan)**이다. 컴포넌트 스캔을 통해 개발자는 빈(Bean) 등록을 간소화하고, 코드의 의존성 관리도 효율적으로 처리할 수 있다. 이번 포스팅에서는 @ComponentScan의 동작 원리, 기본 대상, 그리고 관련된 중요한 개념들을 정리해보겠다.
1. @ComponentScan 이란?
@ComponentScan은 특정 패키지를 스캔하여, 해당 패키지와 하위 패키지에 있는 @Component, @Service, @Repository, @Controller 같은 애노테이션이 붙은 클래스를 자동으로 스프링 빈(Bean)으로 등록해주는 역할을 한다.
이 과정에서 스프링은 의존성을 자동으로 관리하고, 빈이 필요한 곳에 @Autowired를 통해 주입(Injection)한다.
2. @ComponentScan의 기본 설정
컴포넌트 스캔을 사용하려면, @ComponentScan 애노테이션을 클래스 위에 붙이고 스캔할 패키지를 설정해야 한다. 다음은 컴포넌트 스캔의 기본 설정 예제이다.
@Configuration
@ComponentScan(basePackages = "com.example.demo") // 이 패키지와 하위 패키지를 스캔
public class AppConfig {
}
- basePackages 속성: basePackages로 지정된 경로부터 시작하여 하위 패키지를 모두 스캔한다. 예를 들어, 위 코드에서는 com.example.demo와 그 하위 패키지(com.example.demo.sub1, com.example.demo.sub2 등)를 모두 스캔한다.
- 하위 패키지 스캔 원리: basePackages로 지정한 패키지에 속하는 클래스뿐만 아니라 그 하위 모든 패키지를 대상으로 스캔한다. 따라서 프로젝트 구조를 설계할 때 계층 구조를 잘 설계하는 것이 중요하다.
3. 컴포넌트 스캔의 기본 대상
Spring은 다음의 애노테이션이 붙은 클래스를 기본적으로 컴포넌트 스캔 대상으로 설정한다.
애노테이션 | 역할 |
@Component | 일반적인 스프링 빈 등록 |
@Service | 서비스 레이어에서 사용되는 빈 등록 |
@Repository | 데이터 접근 레이어에서 사용되는 빈 등록 |
@Controller | 웹 컨트롤러(웹 레이어)로 사용되는 빈 등록 |
@Configuration |
위 애노테이션들은 모두 내부적으로 @Component를 포함하고 있다. 예를 들어, @Service 애노테이션은 사실상 @Component의 확장으로, 특정 역할(서비스 레이어)이라는 의미를 부여한 것이다. 그렇기 때문에 별도로 @Service, @Repository, @Controller, @Configuration 등을 지정하지 않아도 @ComponentScan의 대상이 된다.
4. Spring Boot와 ComponentScan
Spring Boot 애플리케이션에서는 별도로 @ComponentScan을 명시하지 않아도 기본적으로 컴포넌트 스캔이 동작한다. 이는 @SpringBootApplication에 이미 @ComponentScan이 포함되어 있기 때문이다.
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootApplication 내부 구조:
- @SpringBootApplication에는 @ComponentScan이 포함되어 있으며, 기본적으로 해당 클래스가 위치한 패키지와 그 하위 패키지를 스캔한다.
- 예를 들어, DemoApplication 클래스가 com.example.demo 패키지에 위치하면, com.example.demo와 그 하위 패키지가 자동으로 컴포넌트 스캔 대상이 된다.
5. @ComponentScan과 @Autowired의 의존성 주입
컴포넌트 스캔을 통해 등록된 빈들은 @Autowired를 이용해 자동으로 의존성 주입이 가능하다. @Autowired는 주로 생성자, 필드, 또는 Setter 메서드에 붙여서 의존성을 주입한다.
예제: 생성자 주입
@Component
public class MyService {
public void doSomething() {
System.out.println("Service is working!");
}
}
@Component
public class MyController {
private final MyService myService;
// 생성자 주입
@Autowired
public MyController(MyService myService) {
this.myService = myService;
}
public void handleRequest() {
myService.doSomething();
}
}
- @ComponentScan은 MyService와 MyController를 빈으로 등록한다.
- @Autowired를 통해 MyController의 생성자에 MyService가 자동으로 주입된다.
- 생성자 주입 방식은 객체 불변성을 보장하기 때문에 권장되는 방식이다.
6. ComponentScan 사용 시 주의할 점
- basePackages 설정:
- 컴포넌트 스캔 대상이 되는 패키지를 명확히 지정해야 한다.
- basePackages를 명시하지 않으면 @ComponentScan이 선언된 클래스의 패키지를 기준으로 스캔한다.
- 패키지 구조 설계:
- 패키지 구조를 계층적으로 설계하여, 스캔 범위를 체계적으로 관리해야 한다.
- 예를 들어, 서비스는 service 패키지에, 데이터 레이어는 repository 패키지에, 컨트롤러는 controller 패키지에 배치하는 방식이 좋다.
- 중복 정의:
- @SpringBootApplication에 포함된 기본 스캔 범위와 별도로 @ComponentScan을 선언하면, 스캔 범위가 중복되거나 충돌할 수 있다. 따라서 기본 스캔 범위로 충분한 경우, 추가로 @ComponentScan을 선언할 필요는 없다.
총 정리
- **@ComponentScan**은 특정 패키지와 하위 패키지를 스캔하여 @Component 계열 애노테이션이 붙은 클래스를 빈으로 등록한다.
- Spring Boot에서는 @SpringBootApplication에 이미 @ComponentScan이 포함되어 있어 기본적으로 컴포넌트 스캔이 활성화된다.
- 컴포넌트 스캔 대상은 @Component, @Service, @Repository, @Controller, @Configuration과 같은 애노테이션을 포함한다.
- 스캔 범위를 체계적으로 관리하기 위해 프로젝트의 패키지 구조를 잘 설계해야 한다.
컴포넌트 스캔은 스프링 애플리케이션의 핵심 기능으로, 빈 등록과 의존성 관리의 복잡성을 크게 줄여준다. 적절한 설정과 패키지 구조를 통해 효율적인 애플리케이션을 설계할 수 있다.
'JAVA > Spring' 카테고리의 다른 글
Spring 의존성 주입: 생성자 주입과 수정자 주입의 동작 원리 (1) | 2024.12.21 |
---|---|
Spring @ComponentScan의 includeFilters와 excludeFilters 완벽 이해 (0) | 2024.12.21 |
DI(의존관계 주입, Dependency Injection)란 무엇인가? (1) | 2024.12.20 |
Spring에서 생성자에 @Autowired 어노테이션을 사용하는 이유와 장점 (0) | 2024.12.20 |
[스프링 싱글톤] : 왜 @Bean은 한 번만 호출될까? (0) | 2024.12.20 |
댓글