본문 바로가기
스프링/스프링부트

스프링 부트 AutoConfigure가 작동하는 원리

by 책 읽는 개발자_테드 2021. 10. 26.
반응형

스프링 부트 AutoConfigure는 클래스 경로에 있는 의존성을 기반으로 스프링 애플리케이션을 자동으로 구성한다. 

스프링 부트는 클래스 경로에서 클래스를 감지하고, AutoConfigure 매커니즘은 필요한 빈을 생성하고 연결한다. 

이것은 스프링 부트의 가장 강력한 기능 중 하나이고, 대부분의 작업은 백그라운드에서 자동으로 발생한다.

 

Auto-Configuration Report

스프링 부트의 application.properties 파일에서 debug=true를 설정하면, 스프링 부트 애플리케이션에 대한 Auto-Configureation Report를 활성화할 수 있다.

 

그리고 애플리케이션을 실행하면, 다음과 같은 출력을 확인할 수 있다.

============================
CONDITIONS EVALUATION REPORT
============================

Positive matches:
-----------------
   CodecsAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.http.codec.CodecConfigurer' (OnClassCondition)

   ErrorMvcAutoConfiguration.WhitelabelErrorViewConfiguration#defaultErrorView matched:
      - @ConditionalOnMissingBean (names: error; SearchStrategy: all) did not find any beans (OnBeanCondition)

   JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration matched:
      - @ConditionalOnClass found required class 'com.fasterxml.jackson.databind.ObjectMapper' (OnClassCondition)
      - @ConditionalOnProperty (spring.http.converters.preferred-json-mapper=jackson) matched (OnPropertyCondition)
      - @ConditionalOnBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) found bean 'jacksonObjectMapper' (OnBeanCondition)

...............................................................................................................................................................................

Negative matches:
-----------------
   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

   AopAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.aspectj.lang.annotation.Aspect' (OnClassCondition)
         
...............................................................................................................................................................................
Exclusions:
-----------
   None

Unconditional classes:
----------------------
    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
    org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration

 

위의 출력에서 알 수 있듯이 스프링 부트는 모든 설정이 1.매칭되는 항목과 2.그렇지 않은 항목 및 3.해당 작업에 대한 세부 정보를 제공한다.

이러한 매칭을 기반으로 스프링 부트 Auto-Configureation이 시작되고, 설정을 로그하며 연결한다.

 

위의 출력에서 "Positive match" 섹션의 JacksonHttpMessageConvertersConfiguration을 예로 들면,

스프링 부트는 클래스 경로에서 ObjectMapper를 찾고, 이 매칭을 기반으로 스프링 부트 Auto-Configureation 애플리케이션에 대한 Jackson 구성을 로드한다.

 

Understanding @Conditional Annotation

@Conditional 주석은 기본 주석이며, 스프링 부트 Auto-Configureatio에서 사용되는 대부분의 주석은 이 주석을 확장한 것이다. 스프링 4에 스프링 프로필 기능의 개선 사항으로 도입되었다.

 

이는 개발자에서 다음과 같이 여러 조건에 따라 빈을 등록할 수 있는 유연성을 선사한다.

   1. @Configuration 클래스를 포함하여 @Component로 직접 또는 간접적으로 주석이 달린 모든 클래스의 타입 레벨 애노테이션

   2. 사용자 정의 스테레오타입 애노테이션을 빌드하기 위한 메타 애노테이션

   3. 모든 @Bean 메서드에 대한 메서드 레벨 애노테이션

 

▶ 예시 - 사용자 국가에 따른 서로 다른 세율을 제공하는 서비스

 

public interface TaxCalculationService{
  Double getTaxRate();
}

 

public class USTaxCalculationService implements TaxCalculationService{
    @Override
    public Double getTaxRate(){
      // Tax rate for US
    }
}

public class CATaxCalculationService implements TaxCalculationService{
    @Override
    public Double getTaxRate(){
      // Tax rate for Canada
    }
}

 

@Configuration
public class AppConfig {

 @Bean 
 @Conditional(USTaxCalculationTypeCondition.class)
 public TaxCalculationService usTaxCalculationService() {
  return new USTaxCalculationService();
 }

 @Bean 
 @Conditional(CATaxCalculationTypeCondition.class)
 public TaxCalculationService caTaxCalculationService() {
  return new CATaxCalculationService();
 }
}

 

애플리케이션을 실행하면 스프링은 국가를 기반으로 올바른 빈을 로드한다.

 

이제 부터 스프링 부트가 Auto-configuration을 위해 @Conditional 애노테이션 기능을 사용하는 방법을 알아보자.

 

Understanding Auto-configuration

내부적으로 자동 구성은 @Congifuration 주석으로 달성된다. 추가적인 이해를 위해 기본 JacksonAutoConfiguration을 살펴보자.

@Configuration
@ConditionalOnClass({ObjectMapper.class})
public class JacksonAutoConfiguration {
  // auto-configuration stuff
}

 

스프링 부트에서 @Conditional 주석을 사용하여 구성에 대한 Auto-configuration 설정이 필요한지 여부를 결정한다. 일반적으로 Auto-configuration 클래스들은 다음의 조건부 애노테이션을 사용한다.

   1. @ConditionalOnClass

   2. @ConditionalOnMissingBean

 

스프링에서 제공하는 다른 조건부 애노테이션: reference documentation  

 

 

The @ConditionalOnClass Annotation

클래스 조건은 감지를 위한 Auto-configuration에서 가장 일반적으로 사용된다. 이것을 사용하면 특정 클래스를 기반으로 하는 설정 클래스를 포함할 수 있다. 다음은 JacksonAutoConfiguration 설정 클래스다.

@Configuration
@ConditionalOnClass({ObjectMapper.class})
public class JacksonAutoConfiguration {
  // auto-configuration stuff
}

 

위 예제에서 스프링 부트 Auto-configuration은 클래스 경로에서 Object 매퍼를 찾으면 @ConditionalOnMissingBean 애노테이션을 사용하여 클래스 경로에서 누락된 경우 설정을 활성화할 수 있다.

 

The @ConditionalOnMissingBean Annotation

이 주석을 사용하면, 특정 빈이 없는지 확인할 수 있다.

 

@Configuration
@ConditionalOnClass({ObjectMapper.class})
public class JacksonAutoConfiguration {
 
    // additional configuration code 
    @Bean
    @Primary
    @ConditionalOnMissingBean
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        return builder.createXmlMapper(false).build();
    }
}

 

위 예제에서 ApplicationContext에 ObjectMapper 유형의 빈이 이미 포함되어 있지 않으면, ObjectMapper 빈을 생성한다. 

@ConditionalOnBean은 @ConditionalOnMissingBean 애노테이션과 반대로 작동한다.

 

Spring Boot Auto-Configuration

Auto-configuration을 활성화하기 위해 스프링 부트는 @EnableAutoConfiguration 주석을 사용한다. 일반적으로 @EnableAutoConfiguration 주석을 포함하는 @SpringBootApplication 주석을 사용한다.  @EnableAutoConfiguration 애노테이션은 클래스패스 컴포넌트를 스캔하여 Spring ApplicationContext의 자동 설정을 가능하게 하고 다양한 조건과 일치하는 빈을 등론한다.

TODO: Locating Auto-configuration Classes

TODO: Custom Auto-Configuration

 

출처

https://www.javadevjournal.com/spring-boot/how-spring-boot-auto-configuration-works/

 

반응형

댓글