스프링 부트 - 자동구성 1

    요약

    스프링 부트는 AutoConfiguration 기능을 제공함. 

    스프링부트가 제공하는 자동 구성 기능을 이해하려면 다음 두 가지 개념을 이해해야함.

    • @Conditional : 특정 조건에 맞을 때 설정이 동작하도록 함. 
    • @AutoConfiguration : 자동 구성이 어떻게 동작하는지 내부 원리 이해.  
    • 스프링부트가 제공하는 자동 구성 기능을 이해하려면 다음 개념을 이해해야 함.
      • @Conditional : 특정 조건에 맞을 때 설정이 동작하도록 함. 
      • @AutoConfiguration : 자동 구성이 어떻게 동작하는지 내부 원리 이해 

     

     

    자동구성 - 예제 만들기

    @Slf4j
    @Configuration
    public class DBConfig {
    
        @Bean
        public DataSource dataSource() {
            log.info("datasource 빈 등록");
            HikariDataSource dataSource = new HikariDataSource();
            dataSource.setDriverClassName("org.h2.Driver");
            dataSource.setJdbcUrl("jdbc:h2:mem:test");
            dataSource.setUsername("sa");
            dataSource.setPassword("");
            return dataSource;
        }
    
        @Bean
        public TransactionManager transactionManager() {
            log.info("transactionManager 빈 등록");
            return new JdbcTransactionManager(dataSource());
        }
    
        @Bean
        public JdbcTemplate jdbcTemplate() {
            log.info("jdbcTemplate 빈 등록");
            return new JdbcTemplate(dataSource());
        }
    
    }
    • 위 코드는 DB와 통신하기 위해서 DataSource / TransactionManager / JDBCTemplate을 스프링 빈으로 등록하는 과정

    그런데 생각해보면 이런 과정들은 항상 반복되는 과정들 일 것이다. 왜냐하면 DB마다 다른 통신 규약을 추상화해서 나온 것이 DataSource인데, DB에 접근하기 위해서는 대부분은 추상화된 DataSource / TransactionManager 등을 사용할 것이기 때문이다. 그리고 등록하는 과정을 보면 꽤 설정할 값들이 많고, 이런 메서드들을 외우고 있을 수는 없다. 

    정리해보면 '똑같은 코드가 반복되지만, 외우기는 어렵고, 설정은 쉬운 코드'가 반복된다. 이것을 개발자가 계속 반복하는게 맞을까? 


    자동구성  - 자동 구성 확인 

    • 이 챕터에서는 스프링 빈을 수동으로 등록하고, 자동으로 등록하는 것을 확인한다.
    • JdbcTemplate, DataSource, TransactionManager는 스프링부트가 자동 등록(AutoConfiguration) 해주는 것을 확인할 수 있다. 

     

    빈 등록 확인

    JdbcTemplate, Datasource, TransactionManager가 스프링 컨테이너에 잘 등록되었는지 간단히 확인해보자.

    @Slf4j
    @SpringBootTest
    class DBConfigTest {
    
        @Autowired DataSource dataSource;
        @Autowired TransactionManager transactionManager;
        @Autowired JdbcTemplate jdbcTemplate;
    
        @Test
        void checkBean() {
            log.info("Datasource = {}", dataSource);
            log.info("TransactionManager = {}", transactionManager);
            log.info("JdbcTemplate = {}", jdbcTemplate);
    
            assertThat(dataSource).isNotNull();
            assertThat(transactionManager).isNotNull();
            assertThat(jdbcTemplate).isNotNull();
        }
    }
    • 해당 스프링 빈들은 DbConfig 설정을 통해 스프링 컨테이너에 등록했기 때문에 null이면 안된다.
    • 테스트 결과 해당 스프링 빈들은 의존관계 주입이 정상 처리된 것을 알 수 있다. 

     


    빈 등록 제거

    위의 스프링 빈 3개는 DbConfig 클래스에서 넣어주고 있다. 여기서 빈 등록을 제거해보면, 어떻게 될까? 

    @Slf4j
    @SpringBootTest
    class DBConfigTest {
    
        @Autowired DataSource dataSource;
        @Autowired TransactionManager transactionManager;
        @Autowired JdbcTemplate jdbcTemplate;
    
        @Test
        void checkBean() {
            log.info("Datasource = {}", dataSource);
            log.info("TransactionManager = {}", transactionManager);
            log.info("JdbcTemplate = {}", jdbcTemplate);
    
            assertThat(dataSource).isNotNull();
            assertThat(transactionManager).isNotNull();
            assertThat(jdbcTemplate).isNotNull();
        }
    }
    • 제거를 해도 이 테스트 코드는 성공한다. 이것은 해당 스프링 빈 3개가 의존성 주입이 완료되었다는 것을 의미한다. 
    • 수동으로 스프링 빈을 등록하지 않았는데 어떻게 된 것일까?
      • 스프링 부트가 이 3개의 스프링 빈을 자동으로 등록해주었다. (Auto Configuration) 

     


    스프링 부트의 자동 구성

    • 스프링 부트는 자동 구성(Auto Configuration) 기능을 제공하는데, 일반적으로 자주 사용하는 스프링 빈들을 자동으로 등록해주는 기능임. 
      • 스프링 부트의 Auto Configuration이 JdbcTemplate, DataSource, TransactionManager를 등록해주었음. 

    • 외부 라이브러리의 상태를 보면 spring-boot-autoconfigure:3.0.2가 설치된 것을 볼 수 있음. 

    gradle 상태를 보면 spring-boot-stater에 spring-boot-autoconfigure가 들어와있는 것을 볼 수 있음. 

    // JDBC 등록해주는 거.
    package org.springframework.boot.autoconfigure.jdbc;
    
    @AutoConfiguration(after = DataSourceAutoConfiguration.class)
    @ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
    @ConditionalOnSingleCandidate(DataSource.class)
    @EnableConfigurationProperties(JdbcProperties.class)
    @Import({ DatabaseInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class,
    		NamedParameterJdbcTemplateConfiguration.class })
    public class JdbcTemplateAutoConfiguration {
    
    }
    • @AutoConfiguration : 자동 구성을 사용하려면 이 어노테이션을 사용해야 함.
      • @AutoConfiguration 어노테이션 안에 @Configuration 어노테이션이 있음. 즉, 이것도 스프링 컨테이너 설정 정보로  등록함. 
      • after: 스프링 빈을 등록할 때도 순서에 의존적인 경우도 있음. 이 때는 DataSourceAutoConfiguration 끝난 후 나를 스프링 빈으로 등록해라!라는 의미임.
    • @ConditionalOnClass({ DataSource.class, JdbcTemplateConfiguration.class })
      • If 문과 유사한 기능을 제공함. 이런 클래스가 있는 경우에만 설정이 동작함. 만약 없으면 여기 있는 설정들이 모두 무효화 되고, 빈도 등록되지 않는다.
      • @ConditionalXxx 시리즈가 있다. 자동 구성의 핵심임
      • JdbcTemplate은 DataSource, JdbcTemplate이라는 클래스가 있어야 동작할 수 있음.
    • @Import 스프링에서 자바 설정을 추가할 때 사용함. 

    위의 JdbcTemplateConfiguration.class는 어떻게 설정되어 있을까?

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnMissingBean(JdbcOperations.class)
    class JdbcTemplateConfiguration {
    
       @Bean
       @Primary
       JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
          JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
          JdbcProperties.Template template = properties.getTemplate();
          jdbcTemplate.setFetchSize(template.getFetchSize());
          jdbcTemplate.setMaxRows(template.getMaxRows());
          if (template.getQueryTimeout() != null) {
             jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
          }
          return jdbcTemplate;
       }
    
    }
    • @Configuration : 자바 설정 파일로 사용됨. 
    • @ConditionalOnMissingBean(JdbcOperations.class)
      • JdbcOperation 빈이 없을 때 동작한다. JdbcTemplate의 상위 인터페이스가 JdbcOperation임. → JdbcTemplate이 빈으로 등록되어 있지 않은 경우에만 동작함. 
      • 이런 기능이 없으면 내가 등록한 JdbcTemplate과 자동 구성이 등록하는 JdbcTemplate이 중복 등록되는 문제가 발생할 수 있음. 
      • 보통 개발자가 직접 빈을 등록하면 개발자가 등록한 빈을 사용하고, 자동 구성은 동작하지 않는다.
    • JdbcTemplate이 몇 가지 설정을 거쳐서 빈으로 등록되는 것을 확인할 수 있다. 

     


    자동 등록 설정 요약

    • JdbcTemplateAutoConfiguration : JdbcTemplate
    • DataSourceAutoConfiguration : DataSource
    • DataSourceTransactionManagerAutoConfiguration : TransactionManager 

    그래서 결국은 JdbcTemplate, TransactionManager, DataSource는 스프링 부트가 자동 설정을 통해서 등록해준 것이다.

     


    스프링부트가 제공하는 자동 구성(AutoConfiguration)

     


    Auto Configuration - 용어, 자동 설정? 자동 구성? 

    Auto Configuration은 주로 다음 두 용어로 번역되어 사용된다.

    • 자동 설정
      • 환경 설정이라는 뜻으로 자주 사용됨.
      • Auto Configuration은 빈들을 자동으로 등록해서 스프링이 동작하는 환경을 자동으로 설정해 줌. 그래서 자동 설정이라는 용어도 맞음. 
    • 자동 구성 
      • Configuration은 구성, 배치라는 뜻을 가짐. 
      • CPU, 메모리 등을 배치해야 컴퓨터가 동작한다. 마찬가지로 스프링도 스프링 실행에 필요한 빈들을 적절하게 배치해야한다. 
      • 즉, 자동 구성은 스프링 실행에 필요한 빈들을 자동으로 배치해주는 것이다. 

    댓글

    Designed by JB FACTORY