엔지니어로 가는 길

Spring의 @Conditional과 Spring Boot의 AutoConfiguration 본문

프로그래밍/Spring

Spring의 @Conditional과 Spring Boot의 AutoConfiguration

탐p슨 2021. 10. 1. 21:39
728x90

Contents

1. Introduction

 

2. @Conditional

        모든 Spring 프로젝트의 Configuration에서 공통되는 부분이 있다면?

        Configuration이 공유될 때 발생할 수 있는 문제

        @Conditional

        @Conditional을 이용한 개선

 

3. AutoConfiguration

        Spring Boot 애플리케이션을 실행하면 일어나는 일

        Spring Boot의 핵심적인 특징 세 가지

        톰캣이 뜨는 과정(Spring Boot의 AutoConfiguration이 적용되는 과정)

 

4. Reference

 

Introduction

Spring Boot는 Spring 플랫폼과 써드 파티 라이브러리에 대한 *주관을 가지고 있기에 *요란한 동작 없이 Spring Boot로 애플리케이션 개발을 시작할 수 있다.

* 주관이란 opinionated view를 말한다.
* 요란한 동작이란 대부분의 경우 똑같은 따분한 설정을 말한다.

지금부터 Spring Boot가 어떻게 수많은 자동 설정을 지원하는지(예를 들어, Spring Boot 프로젝트를 만들고 main 메소드를 실행시켰을 때, 아무것도 설정한 게 없는데 어떻게 톰캣 서버가 뜨는지) 살펴보자.

 

@Conditional

Spring Boot를 알아보기 앞서 먼저 Spring의 @Conditional에 대해 알아야 한다.

모든 Spring 프로젝트의 Configuration에서 공통되는 부분이 있다면?


우리가 ReallyBigCompany라는 회사에서 일하고 있다고 생각해보자. 이 회사의 여러 팀은 서로 다른 Spring 프로젝트를 진행하고 있다. 모든 Spring 프로젝트에서 공유하는 공통의 bean들이 있어서 이러한 공통 bean들을 하나의 Configuration으로 추출하고 싶다고 가정해보자.

 

 

(1) 회사 내의 모든 Spring 프로젝트는 ReallyBigCompanySharedContextConfiguration을 포함하는 프로젝트의 .jar 파일을 import 해서 쓰면 된다.


(2) 회사 내의 모든 프로젝트는 관계형 데이터베이스를 사용하고 있다고 가정하자. Flyway는 데이터베이스를 초기화하고 관리할 때 사용되는 것으로 이 역시 모든 프로젝트의 공통 bean이다. (이 글에서는 Flyway가 무엇인지는 크게 중요하지 않다.)

실제 프로젝트의 Configuration은 다음과 같은 모습일 것이다.

 

 

(1) 모든 회사 프로젝트는 ReallyBigCompanySharedContextConfiguration을 import한다.


(2) 해당 프로젝트에서만 사용하는 bean이 있다면 명시하면 된다.

 

이렇게 공통되는 설정을 분리해내고 이를 공유하도록 할 때 어떤 문제가 있을 수 있을까?

Configuration이 공유될 때 발생할 수 있는 문제


회사에서 신규 Spring 프로젝트를 시작해야 하는데, 대부분의 bean은 역시 공통되므로 공유되는 Configuration을 사용하고 싶으나 신규 프로젝트에서는 관계형 데이터베이스를 사용하지 않아서 ReallyBigCompanyProprietaryFlywayClone은 빼고 싶을 수 있다.

이럴 때 바로 Spring의 @Conditional이 사용된다.

@Conditional


Spring 4.0(released on 2013)부터 @Conditional을 제공한다. @Bean, @Component, @Configuration와 함께 쓰일 수 있다.

 

@Conditional에는 Condition 클래스를 주어야 한다. Condition 클래스는 “matches”라는 메소드를 가지고 있는데, 이 메소드의 리턴 타입은 불린이다. 리턴이 true일 경우 조건 통과를 의미하고 bean이 만들어진다. (@Configuration이라면 @Configuration이 적용된다.)

 

@Conditional을 이용한 개선

 

 

(1) IsRelationalDatabaseCondition이라는 클래스의 matches 메소드가 true를 리턴해야만 ReallyBigCompanyProprietaryFlywayClone이 bean으로 등록된다.

@Conditional 덕분에 특정 프로퍼티 값에 따라 bean이 생성되게 할 수도 있고, 클래스패스에 특정 라이브러리가 있느냐에 따라 bean이 생성되도록 할 수도 있다.

(원문에는 Spring Condition의 구현에 대한 내용이 있으나 여기서는 생략한다.)

 

AutoConfiguration

Spring Boot 애플리케이션을 실행하면 일어나는 일

 

Spring Boot 애플리케이션의 main 메소드는 아래와 같이 생겼다.

 

 

main 메소드를 실행하면 톰캣 서버가 뜨고, application.properties 파일이 읽히고, 즉시 @RestController를 작성할 수 있다.

어떻게 이게 가능할까?

Spring Boot의 핵심적인 특징 세 가지

 

SpringApplication을 실행하면 많은 일들이 벌어지는데 그중에서도 아래의 세 가지 특징을 알아야 어떻게 이런 마법이 가능한지 알 수 있다.

1. @PropertySources를 등록한다
Spring Boot는 자동으로 커맨드 라인, OS 환경 변수, application.properties와 같은 애플리케이션 프로퍼티를 포함한 17개의 경로에서 프로퍼티를 읽어온다. (경로는 우선순위가 정해져 있어서 서로 다른 경로에서 같은 프로퍼티를 갖는 경우 높은 우선순위의 경로에 있는 값이 낮은 우선순위의 값을 덮어쓴다.)

2. META-INF/spring.factories를 읽는다
모든 Spring Boot 프로젝트는 org.springframework.boot:spring-boot-autoconfigure라는 라이브러리에 의존한다. 이는 단순한 .jar 파일로 수많은 Spring Boot의 마법(자동 설정)을 담고 있다.

 

 

 

#Auto configure 섹션을 보면 백 개가 넘는 AutoConfiguration들이 명시되어 있다. 각각의 AutoConfiguration은 평범한 Spring의 Configuration으로, 수많은 @Conditional 어노테이션을 가지고 있다. Spring Boot는 이들을 읽고, 애플리케이션이 실행될 때마다 Condition을 검사하여 각각의 AutoConfiguation을 적용한다.

 

참고로 @EnableAutoConfiguartion은 @SpringBootApplication에 메타 어노테이션으로 붙어있다.

 


3. @Conditional의 확장을 제공한다
@ConditionalOnBean(.class)
@ConditionalOnClass(.class)
@ConditionalOnCloudPlatform(.class)


대부분의 condition의 경우 직접 작성할 필요 없이 다양한 Conditional의 확장을 이용하여 손쉽게 작성할 수 있다.

 

톰캣이 뜨는 과정(Spring Boot의 AutoConfiguration이 적용되는 과정)

 

main 메소드가 실행이 되면 정해진 17개의 경로에서 수많은 프로퍼티들을 읽는다. 이 중에는 org.springframework.boot:spring-boot-autoconfigure의 META-INF/spring.factories도 있는데, @SpringBootApplication에는 @EnableAutoConfiguration 어노테이션이 붙어 있으므로 spring.factories의 모든 AutoConfiguration을 읽어들인다.

 

 

AutoConfiguration 중에 ServletWebServerFactoryAutoConfiguration가 있다.

 

 

이 클래스는 ServletWebServerFactoryConfiguration의 EmbeddedTomcat을 import한다.

 

 

EmbeddedTomcat도 @Configuration이며, @Conditional의 확장인 @ConditionalOnClass와 @ConditionalOnMissingBean으로부터 Servlet.class와 Tomcat.class 그리고 UpgradeProtocol.class가 클래스패스에 있고, ServletWebServerFactory가 bean으로 등록되어 있지 않아야 @Configuration이 적용된다는 것을 알 수 있다.

 

(spring-boot-starter-web이 spring-boot-starter-tomcat을 가지고 있다)

 

EmbeddedTomcat은 TomcatServletWebServerFactory를 bean으로 등록한다.

 

 

TomcatServletWebServerFactory의 getWebServer를 보면 톰캣을 만드는 코드가 보인다.

 

정리하자면 톰캣이 뜨는 이유는 Spring Boot가 자동 설정을 지원하기 때문이고, Spring Boot가 톰캣 자동 설정을 적용하는 과정은 대략적으로 다음과 같다.

 

1. main 메소드 실행

2. spring.factories 파일 읽기

3. *evaluate ServletWebServerFactoryAutoConfiguration

        3-1. @ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })

        3-2. @ConditionalOnMissingBean(value = ServletWebServerFactory.class,

                                                    search = SearchStrategy.CURRENT)

4. EmbeddedTomcat(@Configuration) 적용

                            -> TomcatServletWebServerFactory가 bean으로 등록

 

* evaluate이란 @ConditionalXXX을 검사하고 조건이 참일 경우 등록하는 과정을 말한다.

 

사이사이에 다른 과정이 끼어있을 수도 있고, 누가, 언제 TomcatServletWebServerFactory의 getWebServer 메소드를 호출하는지는 더 살펴봐야 알겠지만 이 글에서는 Spring Boot의 AutoConfiguration가 핵심이므로 톰캣은 나중에 다시 살펴보는 게 좋을 것 같다.

 

중요한 점은 이제 Spring Boot 애플리케이션을 실행시켰을 때 어떤 일이 일어나길래 수많은 자동 설정들이 이루어지는지, 특정 자동 설정이 어떻게 일어나는지 확인하고 싶으면 어디를 살펴보면 되는지 알게 되었다는 것이다.

 

Reference

 

https://www.marcobehler.com/guides/spring-boot

 

How Spring Boot’s Autoconfigurations Work

You can use this guide to get an in-depth understanding of what Spring Boot's Autoconfigurations are and how they work.

www.marcobehler.com

 



Spring이 로봇 청소기라면, Spring Boot도 역시 로봇 청소기는 로봇 청소기인데, 수많은 사용자의 데이터를 통해 많은 경우에 필요하고 편리한 설정이 되어 있는 로봇 청소기인 것 같다. 가령 바닥에 전선이 깔려 있다면 이렇게 행동하고, 물기가 있다면 이렇게 행동해야 한다는 것이 설정되어 있는 셈이다.

Spring Boot에서 자동 설정 못지않게 중요한 것이 바로 얼마든지 이러한 설정을 자신의 집에 맞게 커스터마이징 할 수 있다는 점이라고 생각한다. 물기가 있을 때, 닦지 않고 알림음을 내서 어디에 물기가 있는지 알리고 싶다면 손쉽게 설정을 변경할 수 있다. 이번에 AutoConfiguration에 대해 살펴봤으니 다음에는 어떻게 Spring Boot의 설정을 커스터마이즈 할 수 있는지 살펴보면 좋을 것 같다.

 

728x90
Comments