Spring

Spring Boot AutoConfiguration: 작동 원리와 성능 최적화 방법

백엔드 유성 2023. 7. 30. 19:20

AutoConfiguration을 사용하는 Class는 다음과 같은 것들이 있습니다.

DataSource, TransactionManager, jdbcTemplate 등

우리가 흔이 사용하는 것들이죠?

 

이 글에서는 AutoConfiguration의 작동 원리에 대해 배우고, 이를 사용해 개발 과정을 어떻게 최적화할 수 있는지에 대해 다루겠습니다.

 

글 순서

  1. AutoConfiguration 등록 순서
  2. AutoConfiguration 작동 원리
  3. AutoConfiguration 활용하기(라이브러리 제작)
  4. AutoConfiguration 성능 최적화
  5. AutoConfiguration 사용 시 주의사항


1. AutoConfiguration 등록 순서

우선, Spring Boot는 애플리케이션 시작 시 @ComponentScan이 실행되어, Spring Bean으로 등록될 수 있는 클래스를 찾습니다.

 

첫 번째로 main메서드가 존재하는 패키지의 하위 패키지들을 찾습니다. @Bean, @Service, @Controller 등이 이에 포함됩니다.

그 후, classpath 내의 jar파일을 스캔하여 spring.factories 파일을 찾고, 이 파일 내에 명시된 모든 AutoConfiguration 클래스를 로드합니다.

 

AutoConfiguration은 Spring 프레임워크가 설정 파일을 읽어 들여 개발자가 직접 의존성 주입을 하지 않아도 인스턴스를 생성해서 빈으로 등록해주는 편리한 기능입니다.

이러한 기능의 원리는 다음과 같습니다.

 


2. AutoConfiguration 작동 원리

AutoConfiguration에서 중요하게 보아야 할 클래스 두 가지는 SpringFactoriesLoaderAutoConfigurationImportSelector입니다.

 

우선 SpringFactoriesLoaderspring.factories 파일을 찾아 파일내에 명시된 클래스들을 로드하는 역할을 합니다.

그리고 AutoConfigurationImportSelector는 로드된 클래스들 중 필요한 클래스들만 선택합니다.

선택된 클래스는 Spring Container가 인스턴스화 합니다. (Bean으로 등록합니다)

 

아래는 예시로 가져온 data-jpa의 spring.factories 파일입니다.

data-jpa 라이브러리 spring-data-jpa-3.1.1.jar/META-INF/spring.factories

 

현재 인프런 강사로 활동 중이신 김영한 님의 말을 빌려

개발자는 코드로 보는 게 이해가 빠르니 코드로 보시죠.

 

AutoConfiguration 클래스를 로드하기 위한, Spring Framework의 SpringFactoriesLoader 클래스를 살펴보겠습니다.

값을 읽어 들일 파일 경로가 존재하고 "META-INF/spring.factories"으로 설정되어 있습니다.

값을 읽어들일 경로

아래에서는 SpringFactoriesLoader를 생성합니다.

SpringFactoriesLoader는 META-INF/spring.factory 에 적혀있는 클래스들(팩토리 구현체)을 로드하고 빈으로 등록(인스턴스화)하기 위한 클래스입니다.

  여기서 "인스턴스화한다"는 클래스(객체)를 메모리에 올려 "인스턴스"로 만든다입니다.

읽어들인 값을 인스턴스로 만들기 위해 SpringFactoriesLoader를 만드는 코드

SpringFactoriesLoader가 spring.factories 파일에서 EnableAutoConfiguration 키에 해당하는 모든 클래스를 찾았으면,

 

이제 AutoConfigurationImportSelector에게 역할이 넘어갑니다.

AutoConfigurationImportSelector는 찾은 클래스 들 중에서 빈으로 등록할 클래스들을 결정하는 역할을 합니다.

 

등록을 결정하기 위해서 필요한 조건들을 확인하는데, 이 조건들은 @Conditional 어노테이션이 붙은 조건 클래스들에 의해 결정됩니다.

Conditional은 아래와 같이 value에  특정 Class가 존재하면 등록하고, 존재하지 않으면 등록하지 않겠다는 if문으로 보시면 됩니다.

+ 추가로 Conditional의 구현클래스들이 여러 개가 있고 대표적으로 "OnClassCondition"이 있습니다.

 

 

이제, SpringFactoriesLoader를 이용해서 클래스를 불러오고

AutoConfigurationImportSelector를 이용해서 Conditional 조건에 해당하는 객체만 추출하는 과정까지 알아보았습니다.

SpringContainer가 해당 객체를 인스턴스로 만드는 과정은 생략하겠습니다.

 

그림으로 보시면 다음과 같습니다.


3. 사용자 정의 AutoConfiguration 만들기 (라이브러리 만들기)

 

예제 링크 -> https://youseong.tistory.com/6

사용자 정의 AutoConfiguration을 만들기 위해서는 다음의 단계를 거쳐야 합니다:

@Configuration 어노테이션을 붙인 설정 클래스를 생성합니다.
필요한 빈을 @Bean 어노테이션을 사용하여 정의합니다.
해당 설정 클래스를 META-INF/spring.factories 파일에 등록합니다. 

이때, org.springframework.boot.autoconfigure.EnableAutoConfiguration 키와 함께 클래스의 전체 경로를 입력해야 합니다.

 

 

4. 성능 최적화

이전에 설명한 바와 같이, @Condition 어노테이션과 그 하위의 특정 어노테이션들 (@ConditionalOnBean 등)이 붙은 클래스만 인스턴스로 등록된다는 점을 이용할 수 있습니다.
이를 활용하면, 특정 조건이 만족되지 않는 경우 해당 클래스를 인스턴스로 만들지 않고 건너뛸 수 있습니다. 이렇게 되면 애플리케이션의 부하를 줄일 수 있고, 이는 결과적으로 성능 향상을 이끌어낼 수 있습니다.
따라서, 적절한 조건 설정을 통해 필요하지 않은 빈의 생성을 방지하고, 이를 통해 불필요한 메모리 사용을 최소화하는 것이 중요합니다.

 

 

5. 주의사항

AutoConfiguration을 효율적으로 사용하기 위해서는 몇 가지 주의사항을 염두에 두어야 합니다.
먼저, AutoConfiguration은 기본적으로 ApplicationContext에서 빈이 등록되지 않은 상황에서만 활성화됩니다.

즉, 개발자가 수동으로 빈을 등록하였다면, AutoConfiguration은 그 빈을 덮어쓰지 않습니다.

예를 들어, JPA를 사용하면서 DataSource를 개발자가 직접 빈으로 등록하였다면, 이로 인한 충돌 없이 개발자가 등록한 빈이 사용되는 것과 같은 맥락입니다.

다음으로, @AutoConfigureBefore 또는 @AutoConfigureAfter와 같은 어노테이션을 활용하면 AutoConfiguration의 실행 순서를 조정할 수 있습니다.