Spring Boot (Chapter 1~2)[스프링 부트 시작하기, 의존성 관리와 자동설정]
By Bys on April 13, 2022
1. 스프링 부트의 등장
1.1 스프링 프레임워크
1.1.1 프레임워크란?
사전적 의미는 ‘뼈대’ 혹은 ‘구조’이다. 소프트웨어 관점에서 해석해보면, 프레임워크는 어플리케이션의 아키텍처에 해당하는 골격 코드라고 할 수 있다. 어플리케이션을 개발할 때 가장 중요한 것은 어플리케이션 전체 구조를 결정하는 아키텍처.
1.1.2 스프링 프레임워크
스프링 프레임워크는 로드 존슨(Road Johnson)이 집필판 ‘EJB 없는 J2EE(J2EE Development without EJB)’라는 책에서 처음 소개되었으며 EJB라는 무겁고 복잡한 플랫폼에서 벗어나 POJO를 기반으로 하는 경량의 환경을 제공한다.
스프링 프레임워크는 다양한 프레임워크와 기술들을 지원하면서 동시에 개발자가 처리해야하는 설정도 많아지고 복잡해졌다. 초급 개발자 입장에서는 이런 복잡하고 방대한 설정에 대해 부담을 느낄 수밖에 없으며, 복잡한 설정에서 발생한 문제를 수정하는데 많은 시간과 노력을 들일 수 밖에 없다. 이런 문제들을 해결하려는 노력의 일환으로 스프링 부트라는 서브 프로젝트가 진행되었다.
1.2 스프링 부트의 등장
1.2.1 스프링 부트의 등장 배경
스프링과 비슷한 시기에 등장한 루비 온 레일즈나 노드의 익스프레스는 처음부터 웹 어플리케이션 개발을 목적으로 만들어졌다. 따라서 웹 어플리케이션을 개발하는데 있어서 스프링처럼 많은 설정이 필요하지도 않고 개발자들이 좀 더 쉽게 접근할 수 있다. 자연스럽게 시장에서도 어플리케이션을 빠르게 제작하여 출시할 수 있는 이런 경량의 오픈소스 프레임워크를 선호하게 되었다.
스프링 팀에서는 이런 변화에 대응하기 위해 스프링 부트를 만들게 된 것이다.
1.2.2 스프링 부트의 장점
-
라이브러리 관리 자동화
기존에도 자바 프로젝트에서는 Maven이나 Gradle을 이용해서 라이브러리 의존성을 관리해왔다. 하지만 스프링 부트에서는 스타터(Starter)라는 것을 이용해 특정 기능에 필요한 라이브러리 의존성을 더욱 간단하게 처리할 수 있다. -
설정의 자동화
스프링 부트에서는 프로젝트에 추가된 라이브러리를 기반으로 실행에 필요한 환경을 자동으로 설정해준다. -
라이브러리 버전 자동 관리 스프링을 사용하여 개발할 때 가장 신경 쓰이는 것이 라이브러리와 버전 관리다. 스프링은 스프링 라이브러리만 사용하여 개발할 수 없으며, 의존관계에 있는 서드파티 라이브러리들도 사용한다. 스프링 부트를 이용하면 스프링 부트 버전에 해당하는 스프링 라이브러리뿐만 아니라 서드파티 라이브러리들도 호환되는 버전으로 다운로드해준다.
-
테스트 환경과 내장 톰캣
스프링 부트로 생성한 프로젝트에는 Junit을 비롯한 테스트 관련 라이브러리들이 기본적으로 포함되어 있다. 따라서 컨트롤러를 비롯한 다양한 계층의 클래스들에 대해서 테스트 케이스를 쉽게 작성할 수 있다. 그리고 Tomcat서버를 내장하고 있어서 단지 main() 메서드를 가진 클래스를 실행하는 방식으로 서버를 구동하기 때문에 빠르게 실행 결과를 볼 수 있다. -
독립적으로 실행 가능한 JAR 어플리케이션을 개발하고 테스트까지 마쳤으면 어플리케이션을 실제 운영 서버에 배포하기 위해서는 패키징(Packaging)을 해야 한다. 프로젝트가 웹 프로젝트라면 WAR파일로 패키징 해야 한다. 스프링 부트는 독립적으로 실행 가능한 어플리케이션을 빠르게 개발하는 것을 목표로 하기 때문에 웹 어플리케이션도 WAR가 아닌 JAR파일로 패키징하여 사용할 수 있다.
1.3 스프링 부트 퀵스타트
1.3.2 스프링 부트 프로젝트 구조 및 실행
- src/main/java 에는 일반적인 자바 소스를 등록
- src/main/resource 에는 XML이나 프로퍼티 파일들을 등록
- src/main/resource/static 폴더는 HTML과 같은 정적인 웹리소스가 저장 됨
- src/main/resource/templates 폴더에는 Thymeleaf 같은 템플릿 기반의 웹리소스가 저장 됨
- src/test/java 에는 Junit 기반의 테스트 케이스
build.gradle 파일에서 가장 중요한 설정은 의존관계에 해당하는 dependencies 설정이다. 여기에 ‘spring-boot-starter-XXX’ 형태의 의존관계 두 개가 추가되어 있다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
모듈(스타터) | 설명 |
---|---|
spring-boot-starter-web | 웹 어플리케이션 개발에 필요한 스프링 MVC 관련 라이브러리 |
spring-boot-starter-test | Junit을 비롯한 테스트관련 라이브러리 |
pom.xml 파일에서는 <parent>를 이용하여 또 다른 POM설정을 상속할 수 있다. 따라서 눈에 보이지 않지만 부모 설정 파일로부터 수많은 dependency 설정을 상속받아 가지게 된다. (spring-boot-starter-parent)
Gradle 사용 시, io.spring.dependency-management 플러그인을 적용하면 자동으로 spring-boot-starter-parent을 import 한다.
스프링 부트로 만든 어플리케이션을 실행하기 위해서는 메인 클래스를 작성해야 한다. 하지만 이미 src/main/java 폴더에 [프로젝트이름 + Application.java] 형태로 메인 클래스가 작성되어 있는데 이 파일이 main() 메서드를 가진 실행 파일이다.
@SpringBootApplication
public class Chap01Application {
public static void main(String[] args) {
SpringApplication.run(Chap01Application.class, args);
}
}
@SpringBootApplication 어노테이션이 설정되어있다. 이는 이 클래스가 스프링 부트로 만든 어플리케이션의 시작 클래스임을 의미한다. 그리고 유일하게 구현된 main() 메서드는 SpringApplication 객체의 run() 메서드를 정적(static) 메서드 호출 방식으로 호출한다.
-
웹 어플리케이션으로 실행하기 이 어플리케이션을 실행하면 톰캣이 구동된다. spring-boot-starter-web 의존성에 의해 톰캣 라이브러리도 같이 다운로드되었으며, 어플리케이션 실행 시 이 내장 톰캣이 구동된 것이다.
-
자바 어플리케이션으로 실행하기 웹 어플케이션이 아닌 일반 자바 어플리케이션으로 실행하고자 한다면 아래와 같이 수정하고 다시 실행한다.
@SpringBootApplication public class Chap01Application { public static void main(String[] args) { SpringApplication application = new SpringApplication(Chap01Application.class); application.setWebApplicationType(WebApplicationType.NONE); application.run(args); } }
SpringApplication 객체의 run() 메서드를 정적 메서드 호출 방식이 아닌 정상적인 객체 생성 방식을 사용했다. 그리고 run() 메서드를 호출하기 전에 SpringApplication의 WebApplicationType을 NONE으로 설정했다. 이렇게 하면 현재 어플리케이션이 웹 어플리케이션이 아닌 일반 자바 어플리케이션으로 실행되며, 톰캣 서버도 구동되지 않는다.
원래와 같이 웹 어플리케이션으로 실행하려면 소스를 원래 상태로 되돌리거나 아래와 같이 WebApplicationType을 SERVLET으로 변경하면 된다.
application.setWebApplicationType(WebApplicationType.SERVLET);
WebApplicationType으로 설정할 수 있는 어플리케이션 타입은 세 가지다. 먼저 NONE은 웹으로 동작하지 않도록 설정한 것이다. 그리고 SERVLET은 기존의 스프링 MVC를 기반으로 웹 어플리케이션을 구동하겠다는 설정이다. 마지막으로 REACTIVE는 스프링 5.0에서 추가된 비동기(Asynchronous) 처리와 논블로킹 입출력(non-blocking I/O)을 지원하는 웹플럭스(WebFlux)를 적용할 때 사용한다.
application.properties파일을 아래와 같이 설정하여서도 적용이 가능하다.
spring.main.web-application-type=none
그리고 확인 해보면 자바 소스보다 application.properties설정이 우선순위가 높다는 것도 확인할 수 있다. application.setWebApplicationType(WebApplicationType.SERVLET)로 설정했어도 프로퍼티 설정이 우선순위가 높기 때문에 none 설정이 적용되는것도 알 수 있다.
1.3.3 스프링 부트 프로젝트 둘러보기
Banner
- 배너 감추기
@SpringBootApplication public class Chap01Application { public static void main(String[] args) { SpringApplication application = new SpringApplication(Chap01Application.class); application.setBannerMode(Banner.Mode.OFF); // 배너 감추기 application.setWebApplicationType(WebApplicationType.SERVLET); application.run(args); }
application.properties
spring.main.banner-mode=console
-
사용자 정의 배너 적용하기
사용자가 정의한 배너를 적용하고 싶으면 src/main/resource 폴더에 banner.txt라는 이름으로 배너 파일을 작성한다. 스프링 부트는 src/main/resource에 banner.txt 파일이 있으면 해당 파일을 읽어서 배너를 적용하고 없으면 스프링 부트가 사용하는 기본 배너를 출력한다.###################################################### SPRING BOOT START ${spring-boot.formatted-version} ######################################################
현재 사용중인 스프링 부트의 버전을 출력하려면 위와 같이 ‘spring-boot.formatted-version’ 변수를 배너에 추가하면 된다.
-
배너 위치 변경하기
원하는 위치로 파일을 이동하고 application.properties 설정에 배너 위치를 설정한다.application.properties
spring.main.banner-mode=console spring.banner.location==banner/banner.txt
1.3.4 웹 어플리케이션 작성하기
컨트롤러 빈
@RestController
public class BoardController {
@GetMapping("/hello")
public String hello(String name){
return "Hello: " + name;
}
}
@Controller 어노테이션 대신 @RestController를 사용하면 REST방식의 응답을 처리하는 컨트롤러를 구현할 수 있다. 만약 @Controller를 사용했다면 hello() 메소드의 리턴 타입으로 문자열을 사용했을 때, 문자열에 해당하는 View를 만들어야 한다. 하지만 컨트롤러를 REST 컨트롤러로 등록하면 리턴되는 문자열이 브라우저에 그대로 출력되기 때문에 별도로 View화면을 만들 필요가 없다.
http://localhost:8080/hello?name=test 를 호출하면 브라우저에 실행 결과과 출력된다.
Hello: test
자동 컴포넌트 스캔 (ComponentScan)
스프링 문법에 비추어보면 @RestController 어노테이션을 설정했다 하더라도 XML 설정 파일에
비밀은 메인 클래스 위에 선언된 @SpringBootApplication 어노테이션에 있다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
@SpringBootApplication이 포함하는 어노테이션들은 매우 복잡하다. 이 중에서 낯설지 않게 보이는 @ComponentScan 어노테이션이 있다. 이 어노테이션이 기본적으로 main()메서드가 포함된 [프로젝트 + Application] 클래스가 속해 있는 패키지를 베이스 패키지로 하여 빈 등록을 처리하는 것이다.
package com.bys.sample;
@SpringBootApplication
public class Chap01Application {
}
<context:component-scan base-package="com.bys.sample">
Chap01Application의 위치가 com.bys.sample에 위치하기 때문에 위의 component-scan base-package 설정과 동일하다.
RestController 사용하기
@RestController는 JSP 같은 뷰를 별도로 만들지 않는 대신에 컨트롤러 메서드가 리턴한 데이터 자체를 클라이언트로 전달한다. 클라이언트에 전달되는 데이터는 대부분 문자열이거나 VO(Value Object)나 컬렉션 형태의 자바 객체인데, 자바 객체가 전달되는 경우에는 자동으로 JSON으로 변환하여 처리하게 된다.
Lombok 라이브러리 사용하기
롬복을 사용하면 자바 파일을 컴파일할 때, 자동으로 생성자, Getter, Setter, toString() 같은 코드들을 자동으로 추가해준다.
어노테이션 | 기능 설명 |
---|---|
@Getter | Getter 메서드를 만들어준다. |
@Setter | Setter 메서드를 만들어준다. |
@RequiredArgsConstructor | 모든 멤버 변수를 초기화하는 생성자를 만들어준다. |
@ToString | 모든 멤버 변수의 값을 문자열로 연결하여 리턴하는 toString() 메서드를 만들어준다. |
@EqualsAndHashCode | equals(), hashCode() 메서드를 만들어준다. |
@Data | 위의 어노테이션을 모두 포함한다. |
2. 의존성 관리와 자동 설정
2.1 스프링 부트의 의존성 관리
스프링 부트를 구성하는 핵심 요소는 스타터(Starter), 자동설정(AutoConfiguration), 액추에이터(Actuator)다.
요소 | 기능 설명 |
---|---|
스타터(Starter) | 스프링이 제공하는 특정 모듈을 사용할 수 있도록 관련된 라이브러리 의존성을 해결한다. |
자동설정(AutoConfiguration) | 스타터를 통해 추가한 모듈을 사용할 수 있도록 관련된 빈 설정을 자동으로 처리해준다. |
액추에이터(Actuator) | 스프링 부트로 개발된 시스템을 모니터링할 수 있는 다양한 기능을 제공한다. |
2.1.1 스타터로 의존성 관리하기
스프링과 JPA를 연동하기 위해서는 하이버네이트 말고도 spring-orm.jar나 spring-data-jpa.jar 같은 라이브러리들이 추가로 필요하다. 그런데 어떤 라이브러리가 더 필요하고, 어떤 버전을 사용해야 하는지 미리 알기는 쉽지가 않다. 이런 문제를 효과적으로 해결하기 위해서 제공하는 것이 바로 스프링 부트의 스타터다.
스타터는 필요한 라이브러리들을 관련된 것끼리 묶어서 마치 패키지처럼 제공한다. 따라서 프로젝트에서 사용하고 싶은 모듈이 있으면, 그 모듈에 해당하는 스타터만 의존성으로 추가하면 된다. 그러면 관련된 라이브러리 의존성 문제가 자동으로 해결된다.
스프링 부트는 다양한 스타터들을 제공하며 ‘spring-boot-start-모듈명’ 형태의 이름을 갖는 파일들이 바로 이런 스타터다.
2.2 스프링 부트의 자동 설정
스타터를 이용하여 프로젝트에 필요한 라이브러리들을 효과적으로 관리할 수 있다는 것도 확인했다. 하지만 문제는 라이브러리만 추가한다고 해서 추가된 모듈을 바로 사용할 수 있는 것은 아니다.
라이브러리들이 추가되고 나면 추가된 모듈을 사용할 수 있도록 스프링 설정 파일에 빈 등록도 해야 하고 의존성 주입도 적절히 처리해야 한다. 개발자들이 라이브러리 관리 못지않게 어려워하는 부분도 바로 이 복잡한 설정이다. 하지만 스프링 부트는 이런 복잡한 설정도 자동으로 처리해준다.
2.2.1 자동설정 이해하기
스프링 부트로 만든 프로젝트에는 어플리케이션 실행을 위한 메인 클래스가 기본적으로 제공된다. 이 메인 클래스를 실행하면 내장 톰캣이 구동되고 스프링 기반의 웹 어플리케이션이 잘 동작하는 것도 확인할 수 있다. 스프링 MVC를 이용하여 웹 어플리케이션을 한 번이라도 개발해본 경험이 있는 개발자라면 아무리 간단한 웹 어플리케이션이라 하더라도 기본적으로 여러 가지 설정이 필요하다는 것을 알고있다.
하지만 지금까지 우리는 이런 복잡한 설정 없이도 웹 어플리케이션을 만들고 실행할 수 있었다. 이런 것이 가능한 이유는 스프링 부트가 제공하는 자동설정 기능이 동작하여 수많은 빈들이 등록되고 동작했기 때문이며, 그 비밀은 메인 클래스 위에 선언된 @SpringBootApplication에 있다.
어떻게 스프링 부트는 메인 클래스의 @SpringBootApplication 하나만으로 복잡한 설정들을 대신할 수 있었던 것일까? 사실은 @SpringBootApplication 어노테이션이 아닌 @SpringBootApplication이 포함하고 있는 @EnableAutoConfiguration 어노테이션 때문이다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
}
@SpringBootApplication은 복잡한 설정들로 구성되어있다. @SpringBootApplication 가지고 있는 어노테이션 중에서 @Target, @Retention, @Documented, @Inherited는 별로 중요하지도 않을뿐더러 의미도 단순하다. 이 중에서 실제로 중요한 것은 @SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan 세 개다.
실제로 메인클래스의 @SpringBootApplication 어노테이션을 삭제하거나 주석처리하고 @SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan 어노테이션으로 대체해도 의미는 같다.
이 중에서 @SpringBootConfiguration은 기존에 환경설정 빈 클래스를 표현하기 위해 사용했던 @Configuration과 동일하다. 이 클래스가 일반적으로 사용하는 환경설정 클래스가 아닌 스프링 부트 환경설정 클래스임을 표현하기 위해 이름만 @SpringBootConfiguration으로 변경한 것이다. 따라서 실제로 @SpringBootConfiguration어노테이션을 @Configuration으로 대체해서 실행해도 결과는 같다.
@ComponentScan은 앞에서 살펴본 대로 @Configuration, @Repository, @Service, @Controller, @RestController가 붙은 객체를 메모리에 올리는 역할을 한다. 위에 설정된 @ComponentScan은 TypeExcludeFilter와 AutoConfigurationExcludeFilter를 제외하고 나머지 객체들을 스캔해서 초기화하도록 설정한 것이다. 이렇게 하면 몇개의 필터를 제외하고 메인 클래스가 있는 패키지를 기준으로 우리가 만든 클래스들을 컴포넌트 스캔하여 빈으로 등록한다.
@EnableAutoConfiguration이 자동설정과 관련된 어노테이션이다. 스프링 부트는 스프링 컨테이너를 구동할 때 두 단계로 나누어 객체들을 초기화(생성)한다. 스프링 부트가 이렇게 두 단계로 나누어 빈들을 초기화하는 이유는 어플리케이션을 운영하기 위해서는 두 종류의 빈들이 필요하기 때문이다.
예를들어 웹 어플리케이션에 파일 업로드 기능을 추가한다고 가정하자. 파일 업로드를 추가하기 위해서는 먼저 BoardController 같은 컨트롤러를 MultipartFile 객체를 이용해서 업로드 가능한 컨트롤러로 구현해야 한다. 그런데 실제로 파일 업로드 기능이 동작하기 위해서는 반드시 사용자가 업로드한 파일 정보가 MultipartFile 객체에 설정되어야 하며, 이를 위해서 멀티파트 리졸버 객체가 반드시 필요하다. 즉 파일 업로드가 정상적으로 동작하기 위해서는 내가 만든 컨트롤러뿐만 아니라 이를 위해 멀티파트 리졸버 객체를 메모리에 올리는 두 개의 객체 생성 과정이 필요한 것이다.
결국 @ComponentScan은 내가 만든 컨트롤러 객체를 메모리에 올리는 작업을 처리하고 @EnableAutoConfiguration은 CommonsMultipartResolver와 같은 객체들을 메모리에 올리는 작업을 처리한다.
@EnableAutoConfiguration 어노테이션은 spring-boot-autoconfigure-*.jar 파일에 포함되어있다. 그리고 이 파일을 펼쳐보면 META-INF폴더에 spring.factories 파일이 있는데 spring.factories 파일은 스프링 부트의 메타데이터가 저장되어 있는 파일이다. 스프링 부트는 이 파일의 설정을 참조하여 여러 가지 빈을 생성한다.
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
#......
이 수많은 클래스들은 모두 스프링 빈 설정 파일로서 @Configuration을 가지고 있다. 그리고 각 클래스에는 스프링 부트가 지원하는 기능들이 모듈별로 설정되어 있다. 이 중에서 WebMvcAutoConfiguration 클래스를 열어서 확인해보자.
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
}
첫 번째 @Configuration은 이 클래스가 스프링 빈 설정 클래스임을 의미한다. 따라서 @ComponentScan이 처리될 때 자신뿐만 아니라 이 클래스에 @Bean으로 설정된 모든 빈들도 초기화된다.
두 번째 @ConditionalOnWebApplication은 웹 어플리케이션 타입이 어떻게 설정되어 있느냐를 확인하는 어노테이션이다. type속성 값이 type.SERVLET으로 설정되어 있기 때문에 만약 웹 어플리케이션 타입이 SERVLET으로 설정되어 있다면 이 자동 설정 클래스(WebMvcAutoConfiguration) 설정을 적용하라는 의미다. 메인 클래스에서 WebApplicationType을 NONE, REACTIVE, SERVLET 중 하나로 지정할 수 있었다. 이 설정을 SERVLET으로 했다는 것은 웹 어플리케이션으로 실행하겠다는 의미이므로 이 설정을 적용하여 웹과 관련된 여러 빈들을 초기화하라는 것이다.
세 번째 @ConditionalOnClass는 특정 클래스가 클래스 패스에 존재할 때, 현재 설정 클래스를 적용하라는 의미다. 따라서 위 설정은 클래스 패스에 Servlet, DispatcherServlet, WebMvcConfigurer 클래스가 존재하면 이 설정 클래스가 동작하도록 설정한 것이다. 클래스 패스에 Servlet, DispatcherServlet, WebMvcConfigurer 클래스가 있다는 이야기는 현재 어플리케이션이 웹을 기반으로 하고 있따는 의미이기 때문이다.
네 번째 @ConditionalOnMissingBean은 특정 클래스 객체가 메모리에 없을 때, 현재 설정 클래스를 적용하라는 의미다. 따라서 WebMvcConfigurationSupport 객체가 메모리에 없을 때만 현재 설정 클래스가 동작한다.
다섯 번째 @AutoConfigureOrder는 자동 설정 클래스들의 우선 순위를 지정할 때 사용한다. Ordered,HIGHEST_PRECEDENCE + 10 설정은 현재 자동 설정 클래스의 우선 순위를 가장 높은 우선 순위보다 10단계 더 높게 설정한 것이다.
여섯 번째 @AutoConfigureAfter는 현재의 자동 설정 클래스가 다른 자동 설정 클래스 다음에 적용되도록 지정할 때 사용한다. 위 설정대로라면 현재 설정 빈은 DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class 이 모두 처리된 이후에 적용되는 것이다.
Reference
- 스프링 부트 (채규태)
book
programming
spring
framework
springboot
restcontroller
componentscan
springbootapplication
springbootconfiguration
enableautoconfiguration
spring.factories
]