JAVA/Spring

Spring의 ComponentScan 이해하기: @ComponentScan의 동작 원리와 활용법

min민 2024. 12. 21.

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 사용 시 주의할 점

  1. basePackages 설정:
    • 컴포넌트 스캔 대상이 되는 패키지를 명확히 지정해야 한다.
    • basePackages를 명시하지 않으면 @ComponentScan이 선언된 클래스의 패키지를 기준으로 스캔한다.
  2. 패키지 구조 설계:
    • 패키지 구조를 계층적으로 설계하여, 스캔 범위를 체계적으로 관리해야 한다.
    • 예를 들어, 서비스는 service 패키지에, 데이터 레이어는 repository 패키지에, 컨트롤러는 controller 패키지에 배치하는 방식이 좋다.
  3. 중복 정의:
    • @SpringBootApplication에 포함된 기본 스캔 범위와 별도로 @ComponentScan을 선언하면, 스캔 범위가 중복되거나 충돌할 수 있다. 따라서 기본 스캔 범위로 충분한 경우, 추가로 @ComponentScan을 선언할 필요는 없다.

 

 

 

 

 

 

 

총 정리

  • **@ComponentScan**은 특정 패키지와 하위 패키지를 스캔하여 @Component 계열 애노테이션이 붙은 클래스를 빈으로 등록한다.
  • Spring Boot에서는 @SpringBootApplication에 이미 @ComponentScan이 포함되어 있어 기본적으로 컴포넌트 스캔이 활성화된다.
  • 컴포넌트 스캔 대상은 @Component, @Service, @Repository, @Controller, @Configuration과 같은 애노테이션을 포함한다.
  • 스캔 범위를 체계적으로 관리하기 위해 프로젝트의 패키지 구조를 잘 설계해야 한다.

컴포넌트 스캔은 스프링 애플리케이션의 핵심 기능으로, 빈 등록과 의존성 관리의 복잡성을 크게 줄여준다. 적절한 설정과 패키지 구조를 통해 효율적인 애플리케이션을 설계할 수 있다.

 

 

 

 

 

댓글