-
SpringBoot 기초 배우기 #4 (자동 환경 설정 이해하기)back-end/SpringBoot 2022. 2. 22. 10:07728x90
자동 환경 설정은 스프링 부트의 장점이며 매우 중요한 역할을 수행한다.
Spring Boot auto-configuration은 Web, JDBC 등을 비롯해 약 100여가지 자동 설정을 제공한다.
그리고 새롭게 추가되는 라이브러리(JAR)은 스프링 부트 자동-설정 의존성에 따라서 설정이 자동 적용된다.
기존의 스프링 프레임워크에서는 의존성을 일일이 빈으로 설정했다.
스프링부트에서는 관련 의존성을 스타터로 제공하며 수동적으로 설정할 수 있다.
@EnableAutoConfiguration 또는 이를 포함한 @SpringBootApplication 중 하나를 사용하면 된다.(@EnableAutoConfiguration 은 반드시 @Configuration과 함께 사용해야 한다.)
어떻게 스타터에 있는 자동 설정이 적용되는지 원리를 알아보자.
@SpringBootApplication의 내부 코드는 다음과 같다.
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration // 1 @EnableAutoConfiguration // 2 @ComponentScan(excludeFilters = { // 3 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { ... }
@SpringBootConfiguration : 스프링 부트의 설정을 나타내는 어노테이션. 예를 들어 테스트 어노테이션(@SpringBootTest)를 사용할 때 찾기 알고리즘을 사용하여 계속 @SpringBootConfiguration을 찾는다.
@EnableAitoConfiguration : 자동 설정의 핵심 어노테이션. 클래스 경로에 지정된 내용을 기반으로 설정 자동화를 수행한다. 특별한 설정값을 추가하지 않으면 기본값으로 작동한다.
@ComponentScan : 특정 패키지 경로를 기반으로 @Configuration에서 사용할 @Component 설정 클래스를 찾는다.
@ComponentScan의 basePackages 프로퍼티 값에 별도의 경로를 설정하지 않으면 @ComponentScan이 위치한 패키지가 루트경로로 설정된다.
@SpringBootAppication은 위 세가지 어노테이션의 조합이다.
@EnableAutoConfiguration 살펴보기
자동 설정을 관장하는 어노테이션 내부를 살펴보자.
다음은 @EnableAutoConfiguration의 코드이다.
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) //자동 설정 지원 public @interface EnableAutoConfiguration { ... }
자동 설정을 지원해주는 어노테이션은 @Import(AutoConfigurationImportSelector.class) 이다.
클래스명을 보면 '임포트할 자동 설정을 선택한다.' 정도로 해석할 수 있다.
그렇다면 AutoConfigurationImportSelector 클래스를 살펴보자
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { // ... @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { // if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } ... AnnotationAttributes attributes = getAttributes(annotationMetadata); List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// configurations = removeDuplicates(configurations); // Set<String> exclusions = getExclusions(annotationMetadata, attributes); // checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); // configurations = getConfigurationClassFilter().filter(configurations); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions);
작동 설정 방식을 좀 더 상세히 확인해보자.
AutoConfigurationImportSelector 클래스는 DeferredImportSelector 인터페이스를 구현한 클래스로 오버라이드받은 selectImports() 메서드가 자동 설정할 빈을 결정한다.
모든 후보 빈을 getCandidateConfigurations() 메서드를 사용해 불러온다. 대략 100여 개 정도의 설정이 미리 정의되어 있다.
스프링 부트 스타터를 여러 개 등록하여 사용할 경우 내부에 중복된 빈이 설정될 경우가 빈번하다.
이러한 경우를 위해 getExclusions() 메서드에서 제외할 설정을, removeDuplicates() 메서드에서 중복된 설정을 제외시킨다.
그 중 프로젝트에서 사용하는 빈만 임포트할 자동설정 대상으로 선택된다.
빈의 등록과 자동 설정에 필요한 파일은 아래와 같다.
- META-INF/spring.factores : 자동 설정 타깃 클래스 목록. 이곳에 선언되는 클래스들이 @EnableAutoConfiguration 사용시 자동 설정 타깃이 된다.
- META-INF/spring-configuration-metadata.json : 자동 설정에 사용할 프로퍼티 정의 파일. 미리 구현되어 있는 자동 설정에 프로퍼티만 주입시켜주면 된다.
- org/springframework/boot/autoconfugure : 미리 구현해놓은 자동 설정 리스트
예를 들어 H2를 자동 설정한다고 하자(H2는 초경량 로컬DB이다. 주로 테스트용)
spring.factores에서 자동 설정 대상에 대항되는지 확인하고, spring-configuration-metadata.json에서 주요 프로퍼티 값들은 무엇이고 어떤 타입으로 설정할 수 있는지 확인해야한다.
spring-configuration-metadata.json
... { "name": "spring.h2.console.path", "type": "java.lang.String", "description": "Path at which the console is available.", "sourceType": "org.springframework.boot.autoconfigure.h2.H2ConsoleProperties", "defaultValue": "\/h2-console" }, ...
H2 경로의 기본값은 /h2-console이고 String형인 것을 확인할 수 있다.
다른 경로로 변경하기 위해서는 application.properties나 application.yml에 프로퍼티 값을 추가해야한다.
//application.properties에서 변경 spring.h2.console.path=/h2-test //application.yml에서 변경 spring: h2: console: path: /h2-test
위와 같이 프로퍼티 값을 추가하는 것만으로도 앞서 살펴본 자동 환경 설정으로 적용이 되어 애플리케이션이 실행된다.
스프링 공식사이트에서 프로퍼티에 대한 정보들을 제공한다.
스프링 부트는 자동 설정이 적용되는 조건, 시점 등에 따라 다양한 어노테이션을 지원한다.
(많아서 따로 적지는 않겠다.)
자동 설정 관련 어노테이션이 실제로 어떻게 쓰이는지 확인해보자.
H2 자동 설정을 위한 H2ConsoleAutoConfiguration 클래스를 살펴보자.
... @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) //웹 어플리케이션일 때 @ConditionalOnClass(WebServlet.class) //WebServlet.class가 클래스 경로에 있을 때 @ConditionalOnProperty(prefix = "spring.h2.console", name = "enabled", havingValue = "true") //spring.h2.console.enabled 값이 true일 때 @AutoConfigureAfter(DataSourceAutoConfiguration.class) @EnableConfigurationProperties(H2ConsoleProperties.class) ...
주석으로 설명해놓은 다음 세가지 조건에 부합할 때 H2ConsoleAutoConfiguration 클래스가 적용이된다.
스프링 프레임워크에서는 일일이 설정해야 했는데, 스프링 부트에서는 이처럼 스프링 캐발자가 미리 설정한 방식대로 애플리케이션에 적용하게끔 정의되어있다.
지금까지 H2 내부 구성을 대략적으로 살펴보았다.
이제 직접 H2 프로퍼티 값을 사용하여 H2 콘솔 창을 띄워보자.
gradle에 컴파일해도 되고, 빈을 등록해도 된다.
하지만 스프링 부트답게 설정하려면 즉, 자동 설정의 기능을 느끼려면 단순히 설정 프로퍼티의 값을 바꾸기만 하면된다.
우선, 스프링 부트 자동 설정 프로퍼티 문서를 살펴보면 다음과 같은 값들을 확인할 수 있다.
# H2 Web Console (H2ConsoleProperties) spring.h2.console.enabled=false spring.h2.console.path=/h2-console spring.h2.console.settings.trace=false spring.h2.console.settings.web-allow-others=false
프로퍼티의 값을 살펴보니 spring.h2.console.enabled가 콘솔 사용 여부를 설정하는 값이다.
false가 기본값이기 때문에 사용하지 못했던 것
따라서 해당 프로퍼티만 true로 바꿔주면 이미 만들어져있는 h2Console() 빈이 적용된다. 중복된 코드를 작성할 필요가 없는것이다.
application.yml에 해당 코드를 작성하자.
#H2 메모리 DB를 사용하기 위한 설정 datasource: url: jdbc:h2:mem:testdb spring: h2: console: enabled: true
H2 의존성을 설정하였다. 이번에는 런타임 시점에서만 의존하도록 build.gradle을 수정하자.
dependencies { ... compileOnly('com.h2database:h2') ... }
우리가 앞서 살펴보았던 환경 설정에 관한 원리들은 다른 관점에서는 불필요하게 느껴질 수도 있다.
하지만 강조했듯 자동 설정은 스프링 부트에서 매우 중요하다.
환경 설정만큼은 내부를 이해하는 것이 좋다. 그래야 앞으로 다양한 자동화 설정을 적용할 때 무엇이 적용되었는지 확인하고 원하는 최적의 설정을 반영할 수 있을테니.
728x90'back-end > SpringBoot' 카테고리의 다른 글
SpringBoot 게시판 구현 #1 (스프링 부트 웹) (0) 2022.02.22 SpringBoot 기초 배우기 #5 (스프링 부트 테스트) (0) 2022.02.22 SpringBoot 기초 배우기 #3 (환경설정 - 2) (0) 2022.02.22 SpringBoot 기초 배우기 #2 (환경설정 - 1) (0) 2022.02.21 SpringBoot 기초 배우기 #1 (0) 2022.02.21