스프링 부트 - 자동구성 1
- Spring/Spring
- 2023. 9. 14.
요약
스프링 부트는 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)
- https://docs.spring.io/spring-boot/docs/current/reference/html/auto-configuration-classes.html
- 스프링 부트는 수많은 자동 구성을 제공하고, spring-boot-autoconfigure 라이브러리에 자동 구성을 모아둠.
- 스프링부트 프로젝트를 사용하면 spring-boot-autoconfigure 라이브러리는 기본적으로 사용된다.
Auto Configuration - 용어, 자동 설정? 자동 구성?
Auto Configuration은 주로 다음 두 용어로 번역되어 사용된다.
- 자동 설정
- 환경 설정이라는 뜻으로 자주 사용됨.
- Auto Configuration은 빈들을 자동으로 등록해서 스프링이 동작하는 환경을 자동으로 설정해 줌. 그래서 자동 설정이라는 용어도 맞음.
- 자동 구성
- Configuration은 구성, 배치라는 뜻을 가짐.
- CPU, 메모리 등을 배치해야 컴퓨터가 동작한다. 마찬가지로 스프링도 스프링 실행에 필요한 빈들을 적절하게 배치해야한다.
- 즉, 자동 구성은 스프링 실행에 필요한 빈들을 자동으로 배치해주는 것이다.
'Spring > Spring' 카테고리의 다른 글
스프링 부트 - 자동구성 2 (0) | 2023.09.17 |
---|---|
스프링 부트 - 자동구성 3 (2) | 2023.09.17 |
Spring : EventPublishing을 통한 객체 간 결합 약화 (0) | 2023.08.27 |
스프링 조회수 구현하기 (0) | 2023.08.13 |
Spring Tomcat 관련 테스트 (0) | 2023.07.30 |