스프링 부트 @SpringBootApplication, SpringApplication 클래스

스프링 부트 @SpringBootApplication 애노테이션

스프링 부트 @SpringBootApplication 애노테이션은 하나 이상의 @Bean 메서드를 선언하고 자동 구성(auto-configuration) 및 컴포넌트 스캔을 트리거하는 구성 클래스를 표시하는 데 사용됩니다. 이는 @Configuration, @EnableAutoConfiguration@ComponentScan 애노테이션을 사용하여 클래스를 선언하는 것과 동일합니다.

스프링 부트 SpringApplication 클래스

Spring Boot SpringApplication 클래스는 Java main 메소드에서 Spring 애플리케이션을 부트스트랩하고 실행하는 데 사용됩니다. 이 클래스는 클래스패스에서 ApplicationContext를 자동으로 생성하고 구성 클래스를 스캔하며 애플리케이션을 실행합니다. 이 클래스는 Spring Boot를 사용하여 Spring MVC 또는 Spring REST 애플리케이션을 실행하는 데 매우 유용합니다.

SpringBootApplication 및 SpringApplication 예제

지난 번 Spring RestController 튜토리얼에서는 Spring RESTful 웹 서비스를 생성하고 Tomcat에 배포했습니다. web.xml과 스프링 컨텍스트 파일을 생성해야 했으며, 수동으로 Spring MVC 종속성을 추가하고 버전을 관리해야 했습니다. 여기에서는 프로젝트를 Spring Boot 애플리케이션으로 실행하고 구성 파일을 제거합니다. 이렇게 하면 외부 Tomcat 서버에 수동으로 프로젝트를 빌드하고 배포할 필요 없이 애플리케이션 로직을 빠르게 테스트할 수 있습니다.

프로젝트 파일에 필요한 변경 사항을 수행하기 전에 GitHub 저장소에서 기존 프로젝트를 확인해야 합니다. 이후 섹션에서 필요한 변경 사항을 가할 것입니다.

아래 이미지는 최종 프로젝트 구조를 보여줍니다.

Spring Boot Maven 종속성 추가

첫 번째 단계는 pom.xml 파일을 정리하고 Spring Boot을 위해 구성하는 것입니다. REST 웹 서비스이므로 spring-boot-starter-web 종속성만 필요합니다. 그러나 Java 10에서 실행되고 XML 요청 및 응답을 지원하려면 JAXB 종속성을 유지해야 합니다. 또한 spring-boot-maven-plugin 플러그인을 추가해야 합니다. 이 플러그인을 사용하면 간단한 Java 애플리케이션을 Spring Boot 애플리케이션으로 실행할 수 있습니다. 여기에 업데이트된 pom.xml 파일이 있습니다.

<project xmlns="https://maven.apache.org/POM/4.0.0"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>Spring-RestController</groupId>
	<artifactId>Spring-RestController</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.2.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>10</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- JAXB for XML Response needed to explicitly define from Java 9 onwards -->

		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
		</dependency>
		<dependency>
			<groupId>org.glassfish.jaxb</groupId>
			<artifactId>jaxb-runtime</artifactId>
			<version>2.3.0</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>javax.activation</groupId>
			<artifactId>javax.activation-api</artifactId>
			<version>1.2.0</version>
		</dependency>
	</dependencies>

	<build>
		<!-- added to remove Version from WAR file -->
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

WebContent 디렉토리를 삭제하거나 그대로 두어도 Spring Boot 애플리케이션에서 사용되지 않습니다.

Spring Boot 애플리케이션 클래스

이제 main 메서드가 있는 Java 클래스를 만들고 @SpringBootApplication 어노테이션으로 표시하고 SpringApplication.run() 메서드를 호출해야 합니다.

package com.journaldev.spring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootRestApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootRestApplication.class, args);
	}
}

Java 어플리케이션으로 클래스를 실행하면 다음과 같은 출력물이 생성됩니다. 여기에서는 신경 쓸 필요가 없는 몇 가지 로거를 제거했습니다. 어플리케이션은 종료되지 않고 클라이언트 요청을 기다립니다.

2018-06-18 14:33:51.276  INFO 3830 --- [           main] c.j.spring.SpringBootRestApplication     : Starting SpringBootRestApplication on pankaj with PID 3830 (/Users/pankaj/Documents/eclipse-jee-workspace/Spring-RestController/target/classes started by pankaj in /Users/pankaj/Documents/eclipse-jee-workspace/Spring-RestController)
2018-06-18 14:33:51.280  INFO 3830 --- [           main] c.j.spring.SpringBootRestApplication     : No active profile set, falling back to default profiles: default
2018-06-18 14:33:51.332  INFO 3830 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@38467116: startup date [Mon Jun 18 14:33:51 IST 2018]; root of context hierarchy
2018-06-18 14:33:52.311  INFO 3830 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2018-06-18 14:33:52.344  INFO 3830 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2018-06-18 14:33:52.344  INFO 3830 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.31
2018-06-18 14:33:52.453  INFO 3830 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2018-06-18 14:33:52.453  INFO 3830 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1127 ms
2018-06-18 14:33:52.564  INFO 3830 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2018-06-18 14:33:52.927  INFO 3830 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/rest/employee/get/{id}],methods=[GET]}" onto public com.journaldev.spring.model.Employee com.journaldev.spring.controller.EmployeeRestController.getEmployeeByID(int)
2018-06-18 14:33:52.928  INFO 3830 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/rest/employee/getAll],methods=[GET]}" onto public java.util.List<com.journaldev.spring.model.Employee> com.journaldev.spring.controller.EmployeeRestController.getAllEmployees()
2018-06-18 14:33:52.929  INFO 3830 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/rest/employee/create],methods=[POST]}" onto public com.journaldev.spring.model.Employee com.journaldev.spring.controller.EmployeeRestController.createEmployee(com.journaldev.spring.model.Employee)
2018-06-18 14:33:52.929  INFO 3830 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/rest/employee/search/{name}],methods=[GET]}" onto public com.journaldev.spring.model.Employee com.journaldev.spring.controller.EmployeeRestController.getEmployeeByName(java.lang.String)
2018-06-18 14:33:52.929  INFO 3830 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/rest/employee/delete/{id}],methods=[DELETE]}" onto public com.journaldev.spring.model.Employee com.journaldev.spring.controller.EmployeeRestController.deleteEmployeeByID(int)
2018-06-18 14:33:53.079  INFO 3830 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-06-18 14:33:53.118  INFO 3830 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-06-18 14:33:53.124  INFO 3830 --- [           main] c.j.spring.SpringBootRestApplication     : Started SpringBootRestApplication in 2.204 seconds (JVM running for 2.633)

로그에서 얻을 수 있는 몇 가지 중요한 포인트는 다음과 같습니다:

  1. 스프링 부트 어플리케이션 프로세스 ID는 3830입니다.
  2. 스프링 부트 어플리케이션은 포트 8080에서 톰캣을 실행하고 있습니다.
  3. 우리 어플리케이션의 컨텍스트 경로는 “”입니다. 이는 우리의 API를 호출할 때 서블릿 컨텍스트를 제공할 필요가 없음을 의미합니다.
  4. 로거는 구성된 모든 API를 출력합니다. 예: Mapped "{[/rest/employee/get/{id}],methods=[GET]}" 등.

아래 이미지는 우리의 스프링 부트 어플리케이션이 노출시킨 API를 호출하는 예시를 보여줍니다.

SpringBootApplication scanBasePackages

기본적으로 SpringApplication은 구성 클래스 패키지와 그 하위 패키지를 스캔합니다. 따라서 만약 우리의 SpringBootRestApplication 클래스가 com.journaldev.spring.main 패키지에 있다면, com.journaldev.spring.controller 패키지를 스캔하지 않습니다. 이 상황을 SpringBootApplication scanBasePackages 속성을 사용하여 해결할 수 있습니다.

@SpringBootApplication(scanBasePackages="com.journaldev.spring")
public class SpringBootRestApplication {
}

Spring Boot 자동 구성된 빈들

Spring Boot은 자동 구성을 제공하기 때문에 많은 빈들이 그에 의해 구성됩니다. 아래의 코드 스니펫을 사용하여 이러한 빈들의 목록을 얻을 수 있습니다.

ApplicationContext ctx = SpringApplication.run(SpringBootRestApplication.class, args);
String[] beans = ctx.getBeanDefinitionNames();
for(String s : beans) System.out.println(s);

아래는 우리의 Spring Boot 애플리케이션에서 구성된 빈들의 목록입니다.

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
springBootRestApplication
org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
employeeRestController
employeeRepository
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.condition.BeanTypeRegistry
propertySourcesPlaceholderConfigurer
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration
websocketContainerCustomizer
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat
tomcatServletWebServerFactory
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
servletWebServerFactoryCustomizer
tomcatServletWebServerFactoryCustomizer
server-org.springframework.boot.autoconfigure.web.ServerProperties
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
webServerFactoryCustomizerBeanPostProcessor
errorPageRegistrarBeanPostProcessor
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration
dispatcherServlet
mainDispatcherServletPathProvider
spring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration
dispatcherServletRegistration
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration
defaultValidator
methodValidationPostProcessor
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration
error
beanNameViewResolver
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration
conventionErrorViewResolver
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
errorAttributes
basicErrorController
errorPageCustomizer
preserveErrorControllerTargetClassPostProcessor
spring.resources-org.springframework.boot.autoconfigure.web.ResourceProperties
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration
faviconHandlerMapping
faviconRequestHandler
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration
requestMappingHandlerAdapter
requestMappingHandlerMapping
mvcConversionService
mvcValidator
mvcContentNegotiationManager
mvcPathMatcher
mvcUrlPathHelper
viewControllerHandlerMapping
beanNameHandlerMapping
resourceHandlerMapping
mvcResourceUrlProvider
defaultServletHandlerMapping
mvcUriComponentsContributor
httpRequestHandlerAdapter
simpleControllerHandlerAdapter
handlerExceptionResolver
mvcViewResolver
mvcHandlerMappingIntrospector
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter
defaultViewResolver
viewResolver
welcomePageHandlerMapping
requestContextFilter
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
hiddenHttpMethodFilter
httpPutFormContentFilter
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
mbeanExporter
objectNamingStrategy
mbeanServer
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration
standardJacksonObjectMapperBuilderCustomizer
spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration
jacksonObjectMapperBuilder
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$ParameterNamesModuleConfiguration
parameterNamesModule
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration
jacksonObjectMapper
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
jsonComponentModule
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration
stringHttpMessageConverter
spring.http.encoding-org.springframework.boot.autoconfigure.http.HttpEncodingProperties
org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration
mappingJackson2HttpMessageConverter
org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
messageConverters
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration$JacksonCodecConfiguration
jacksonCodecCustomizer
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration
spring.security-org.springframework.boot.autoconfigure.security.SecurityProperties
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
restTemplateBuilder
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration
tomcatWebServerFactoryCustomizer
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
characterEncodingFilter
localeCharsetMappingsCustomizer
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
multipartConfigElement
multipartResolver
spring.servlet.multipart-org.springframework.boot.autoconfigure.web.servlet.MultipartProperties

거대한 목록이네요. 사용하지 않는 많은 자동 구성된 빈들이 있습니다. 우리는 @SpringBootApplicationexclude 또는 excludeName 속성을 사용하여 이러한 빈들을 비활성화하여 Spring Boot 애플리케이션을 최적화할 수 있습니다. 아래의 코드 스니펫은 JMX와 Multipart 자동 구성을 비활성화합니다.

@SpringBootApplication(scanBasePackages = "com.journaldev.spring", exclude = {
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration.class, org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration.class })
public class SpringBootRestApplication {
}

비자동 구성 클래스를 제외하려고 시도하면 오류가 발생하여 애플리케이션이 시작되지 않습니다.

@SpringBootApplication(scanBasePackages = "com.journaldev.spring", exclude = {com.journaldev.spring.controller.EmployeeRestController.class })
public class SpringBootRestApplication {
}

위의 코드 스니펫은 다음과 같은 오류를 발생시킵니다:

2018-06-18 15:10:43.602 ERROR 3899 --- [main] o.s.boot.SpringApplication: Application run failed

java.lang.IllegalStateException: The following classes could not be excluded because they are not auto-configuration classes:
	- com.journaldev.spring.controller.EmployeeRestController

SpringBootApplication 주석과 SpringApplication 예제에 대해서는 여기까지입니다.

최종 프로젝트는 GitHub 저장소에서 다운로드할 수 있습니다.

Source:
https://www.digitalocean.com/community/tutorials/springbootapplication-springapplication