본문 바로가기
WEB/Spring

[Spring] @ComponentScan, Bean 객체 관리하기

by 정권이 내 2023. 12. 14.

[Spring] @ComponentScan 개념, Bean 객체 관리하기

 

Spring ApplicationContext

Spring Boot 기반의 웹 애플리케이션을 개발할때 클래스 상단에 여러가지 어노테이션을 설정하는데 @Component, @Service, @Controller 등등 이러한 어노테이션을 등록하는 목적과 메서드에 적용하는 @Bean 어노테이션의 차이점에 대해서 알아보겠습니다.

@Component 를 이해하기 전에 먼저 스프링 어플리케이션 컨텍스트(Spring ApplicationContext)에 대한 이해가 필요합니다.

Spring ApplicationContext는 Spring이 Bean 객체를 자동으로 관리, 배포할수 있도록 보관하는 장소입니다. SpringBoot에서 Bean객체에 등록하고 관리하기 위해서는 @Autowired, @Component 두 종류의 어노테이션이 있습니다.

 

@Autowired

Spring에 등록된 Bean객체를 불러올때 주로 사용했지만 Spring 4.3 버전 이후부터는 Bean객체 주입을 위한 @Autowired 어노테이션을 명시적으로 사용하지 않아도 됩니다. 4.3 버전부터는 클래스에 단일 생성자만 존재할 경우 @Component 어노테이션 만으로도 Bean 객체 주입을 할수 있기 때문입니다.

 

@Component

@Component는 사용자가 생성한 객체를 Spring에 자동으로 등록해주는 어노테이션입니다. Spring은 @Component 어노테이션이 등록된 클래스를 탐색하여 인스턴스로 만들고 해당 클래스를 필요로하는곳에 의존성을 주입할수 있게됩니다.

실무에서는 @Component 대신 역할에 따라 직관적으로 구분할수있도록 @Controller, @Service, @Repository 등을 사용합니다. 이러한 어노테이션들 내부에@Component 가 어노테이션으로 등록되있기 때문에 스프링에서 Bean 객체로 관리할수 있게 됩니다.

 

@Controller

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    ...
}

 

@Service

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
    ...
}

 

@Repository

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
    ...
}

 

@ComponentScan

@ComponentScan은 프로젝트 내부에 있는 모든 @Component 들을 ApplicationContext 로 수집하는 역할을 하는어노테이션 입니다. SpringBoot 기반의 어플리케이션을 만들고 있다면 기본적으로 @SpringBootAplication 이라는 어노테이션이 선언되는데 해당 어노테이션 내부에 @ComponentScan이 등록되있는것을 확인할수 있습니다.

 

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{
	...
	...
}

 

@ComponentScan 탐색범위 명시적 선언

하지만 일반적으로 @ComponentScan은 선언된 위치를 기준으로 하위 패키지들에 있는 @Component만 스캔이 가능합니다. 예를들어 @SpringBootApplication이 com.spring.inrange 패키지를 기준으로 선언이 되어있다면 com.spring.inrange 하위 패키지들에 대해서만 @Component을 찾게되고 만약 외부 패키지에 대해서도 탐색을 하고 싶다면 명시적으로 @ComponentScan을 선언해야 합니다.

 

외부 패키지 (com.spring.outrange)

package com.spring.outrange;

@Component
public class OutRangeTest{
    ...
}

 

메인 패키지 (com.spring.inrange)

package com.spring.inrange;

@SpringBootApplication
@ComponentScan({"com.spring.inrange", "com.spring.outrange"}) // 명시적 선언
public class SpringApplication{
    ...
}

 

@Component, @Bean 차이점

@Component와 마찬가지로 @Bean 어노테이션도 Bean 객체를 관리하기 위해 사용합니다. 차이점은 @Component는 클래스 단위로 설정하고 @Bean은 메서드단위로 설정할수 있는데 메서드에 @Bean 선언시 메서드가 위치하는 클래스에 @Configuration어노테이션을 선언해야 합니다.

 

연관 포스팅

반응형

댓글