위키피디아에 적힌 설명을 보면 아래와 같다.
The Spring Framework is an application framework and inversion of control container for the Java platform. The framework's core features can be used by any Java application, but there are extensions for building web applications on top of the Java EE (Enterprise Edition) platform. Although the framework does not impose any specific programming model, it has become popular in the Java community as an addition to the Enterprise JavaBeans (EJB) model. The Spring Framework is open source. From wikipedia
스프링 프레임워크는 자바 플랫폼을 위한 애플리케이션 프레임워크이며 IOC 컨테이너입니다. 프레임워크의 핵심 기능은 어떤 자바 애플리케이션에 의해서도 사용될 수 있지만, 자바 EE 플랫폼 위에서 웹 애플리케이션을 빌드하기 위한 확장 기능들이 특히 많습니다. 프레임워크가 어떠한 특정한 프로그래밍 모델을 강요하지는 않지만, 엔터프라이즈 자바 빈즈(EJB) 모델에 추가하는 것이 자바 커뮤니티에서는 인기입니다. 스프링 프레임워크는 오픈소스입니다.
위 설명만 듣고 스프링이 무엇인지 감이 오는 분은 자바 & 스프링에 대한 상당한 이해가 있는 분일 것이다. 사실 이미 스프링을 알아야 저 정의가 이해가 된다. 밑에서 다시 스프링에 대해 더 상세한 예제로 설명해보겠다.
일단 위의 스프링의 정의를 이해하기 위해 모르는 용어를 하나씩 배워보자.
스프링을 접하다보면 가장 흔히 듣는 축약어가 DI
와 IoC
이다.
스프링에서 가장 중요한 개념이 IOC 컨테이너이다. reflection이라는 기술을 통해 자바 오브젝트를 설정하고 관리하는 수단을 제공하는 기술이다. 컨테이너는 특정한 오브젝트의 오브젝트 라이프사이클을 관리하는데 책임이 있다. 오브젝트를 생성하고, 초기화 메소드를 호출하고, 오브젝트를 서로 연결하면서 환경 설정을 해준다.
컨테이너에 의해 생성된 오브젝트는 managed objects
혹은 managed beans
라고 불린다. 컨테이너는 XML 파일 또는 자바 애노테이션 또는 설정 클래스를 검출하여 환경 설정이 된다. 이러한 데이터 소스는 빈을 생성하기 위해 필요한 정보들을 제공하기 위한 빈 정의가 포함된다.
오브젝트들은 Dependency Lookup(DL)
혹은 Dependency Injection(DI)
와 같은 방식에 의해 얻어진다. Dependency Lookup
은 호출자가 컨테이너 오브젝트에 특정 타입의 특정 이름의 오브젝트를 요청하는 것이고, Dependency Injection
은 생성자, 프로퍼티, 팩토리 메소드와 같은 패턴을 통해 이름에 맞는 오브젝트를 넘겨주는 것이다.
많은 경우에, 스프링 프레임워크의 다른 파트를 사용할 때는 이러한 컨테이너를 사용하면 애플리케이션을 만들면서 더욱 쉽게 환경 설정을 하고 커스터마이징을 할 수 있음에도 컨테이너를 사용하지 않는다. 스프링 컨테이너는 작은 스케일의 애플리케이션부터 큰 기업용 애플리케이션까지 거의 모든 자바 환경에서 애플리케이션을 설정하고 통합하기 위한 지속적인 매커니즘을 제공한다.
컨테이너는 Pitchfork project의 방법으로 부분적으로 EJB 3.0을 따르는 컨테이너가 될 수 있다. 스프링 프레임워크가 표준을 따르지 않는다고 비난하는 사람도 있다. 하지만, SpringSource
는 EJB 3.0 을 주 목표로 보지 않고 스프링 프레임워크와 컨테이너를 더 강력한 프로그래밍 모델로 만드는 것이라 주장한다. 프로그래머는 직접적으로 오브젝트를 만들지 않지만, 스프링 설정 파일에 이를 정의함으로써 어떻게 만들어져야 하는지에 대해 설명한다. 비슷하게 서비스와 컴포넌트들도 직접 호출되지 않는다. 유지보수와 테스팅의 용이성을 증가시키기 위해 IoC가 의도한 방향이다.
DI
는 간단히 설명하면 스프링 내부 애플리케이션 컨텍스트에서 필요한 타입의 빈이 꺼내져서 자동으로 주입되는 것이고,DL
은 스프링 내부 애플리케이션 컨텍스트에서 해당 타입의 빈을 직접 찾아서 쓰는 방식을 말한다. 스프링 핵심 원리 - 기본편 #58 / 관련 링크는 저작권 때문에 비공개 김영한님의 스프링 핵심 원리 강의에 나옵니다.
Java Platform, Enterprice Edition
을 축약해서 Java EE
라고 불렀었고, Java 2 Platform, Enterprise Edition
을 축약해서 J2EE
라고 부른다. 결국에는 스펙들의 집합이다. Java Standard Edition
인 Java SE
를 상속받은 형태이며, Java SE
는 분산 컴퓨팅, 웹 서비스와 같은 엔터프라이즈 기능들에 대한 스펙을 담고 있다.
스펙으로는 웹 스펙, 웹서비스 스펙, 엔터프라이즈 스펙, 기타 스펙 등이 존재하는데 웹 스펙으로는 우리가 익히 알고 있는 자바 서블릿
이나, 자바 EL
, 자바 웹소켓
등이 있고, 웹 서비스 스펙으로는 Java Restful Web Services
등이 있다.
Spring Core Container
: 스프링의 기반이 되는 모듈이며, 스프링 컨테이너를 제공한다. - BeanFactory
와 ApplicationContext
가 있다.BeanFactory
는 ApplicationContext
의 상위 인터페이스로 프레임워크 환경 설정과 기본 기능을 제공하고, ApplicationContext
는 BeanFactory
를 상속하여 AOP 기능, 메세지 리소스 핸들러, 이벤트 발행 등 추가적인 엔터프라이즈 기능을 더 제공한다.Aspect-Oriented Programming
: AOP
라 불리며, 공통 관심사(Cross-cutting concerns)구현을 가능하게 한다.Authentication / Authorization
: Spring Security
라는 스프링 서브 프로젝트를 통해 보안 설정을 간편하게 할 수 있도록 지원함Convention over configuration
: Spring Roo
모듈 내부에서 스프링을 기반으로 한 엔터프라이즈 앱을 빠르게 개발할 수 있는 솔루션을 제공Data access
: Java Database Coinnectivity(JDBC) 관계형 디비 관리 시스템과 ORM 도구, NoSQL 모두 제공Inversion of Control
: 자바 오브젝트들의 라이프사이클 관리와 애플리케이션 컴포넌트 관리 환경 설정을 해준다. 주로 의존성 주입을 통해 이루어진다.
BeanFactory
와ApplicationContext
에 대한 설명 스프링 핵심 원리 - 기본편 #29 BeanFactory와 ApplicationContext
스프링 핵심 기술 설명 공식문서에 기술에 대해 매우 자세히 나와있다.
자바 웹 애플리케이션을 만들 때, DI, IoC와 같은 기술을 통해 설계된 아키텍처를 이용해 유지보수성, 확장성 등을 지키면서도 개발자는 최대한 비즈니스 로직을 만드는데만 집중할 수 있게 만들어주는 프레임워크이다. 또 DI, IoC 와 같은 기술은 객체간 결합도를 낮추어 코드 재사용성을 향상시키고, 단위 테스트를 용이하게 할 수 있도록 해준다.
한 마디로 정리하면 웹 개발에 주로 이용되는 다양한 모듈과 함께 좋은 객체지향 웹 어플리케이션을 개발할 수 있도록 도와준다.
스프링을 처음 배울 때, 스프링은 초기 설정만 잘해도 고수라는 소리를 들었다. 그만큼 설정을 어디서 어떻게 할 수 있는지에 대해 알기가 어려웠고, 막상 설정 파일을 봐도 무슨 소리가 적혀 있는 건지 알기가 너무 어려웠다.
스프링 프로젝트는 보통 독립적으로 돌아가는 게 아니라, 다양한 의존성과 함께 돌아가는데 스프링 버전이 계속 올라감에 따라 호환이 되는 의존성과 그렇지 않은 의존성을 반드시 구분해서 의존성을 추가해야 했다. 이러한 작업들이 개발자를 매우 피곤하게 했다.
스프링 프로젝트는 .war
파일을 추출하여 해당 파일을 톰캣 안의 특정 폴더로 넣어서 배포했다. 스프링 프로젝트에서 추출한 .war
파일은 WAS 없이 독립적으로 실행이 불가능해서 항상 WAS를 먼저 설치하고 그 안에 .war
파일을 넣어 배포했었다.
위의 3가지 문제를 해결하려 나온 것이 스프링 부트이다.
Spring Boot helps you to create stand-alone, production-grade Spring-based applications that you can run. We take an opinionated view of the Spring platform and third-party libraries, so that you can get started with minimum fuss. Most Spring Boot applications need very little Spring configuration.
You can use Spring Boot to create Java applications that can be started by using java -jar or more traditional war deployments. We also provide a command line tool that runs “spring scripts”.
Our primary goals are:
Provide a radically faster and widely accessible getting-started experience for all Spring development.
Be opinionated out of the box but get out of the way quickly as requirements start to diverge from the defaults.
Provide a range of non-functional features that are common to large classes of projects (such as embedded servers, security, metrics, health checks, and externalized configuration).
Absolutely no code generation and no requirement for XML configuration.
스프링 부트는 자체적으로 구동 가능한 프로덕션 수준의 스프링 기반 애플리케이션을 만드는 것을 도와줍니다. 스프링 플랫폼과 서브파티 라이브러리에 대한 독선적인 관점을 취함으로써, 최소한의 수고로 스프링 프로젝트를 실행할 수 있게 해줍니다. 대부분의 스프링 부트 애플리케이션은 매우 작은 스프링 설정만을 요구합니다.
스프링부트는 java -jar
명령어 혹은 war
파일을 배포하는 전통적인 방식으로 실행될 수 있는 자바 애플리케이션을 쉽게 만들 수 있게 해줍니다. 또, "spring script"
를 실행하는 커멘드 라인 도구도 제공합니다.
스프링 부트의 주요 목적은 다음과 같습니다.
짧게 요약하자면, 많은 설정을 고정된 값으로 자동으로 먹여주어서 빠른 스프링 애플리케이션을 개발할 수 있도록 해준다.
스프링 부트 공식문서가 생각보다 잘 되어 있어서 엄청나게 많은 정보를 얻을 수 있다.
스프링 부트 프로젝트를 생성하면, 가장 메인이 되는 자바 클래스 위에 @SpringBootApplication
이라는 애노테이션이 붙어있다. 이 곳에 자동 설정의 비밀이 있다.
@SpringBootApplication
애노테이션 내부 구현을 보면, 위와 같이 @SpringBootConfiguration
과 @EnableAutoConfiguration
을 볼 수 있다.
아래의 애노테이션 설명은 굳이 안 읽어봐도 된다. 간단히 설명하면 자주쓰이는 빈을 자동으로 주입해서 자동설정 한다는 얘기다.
스프링 부트 애플리케이션에 @Configuration
애노테이션을 제공하는 클래스이다. 스프링의 표준 @Configuration
애노테이션에 대한 대안으로 사용되어, Configuration을 자동으로 찾을 수 있다.
스프링 애플리케이션 컨텍스트의 Auto-configuration
을 가능하게 한다. 사용자가 필요할만한 빈들을 추측하고 설정해준다. Auto-configuration
클래스들은 주로 클래스 패스와 빈을 정의한 곳을 기반으로 적용된다. 이를테면, 사용자가 클래스 패스에 tomcat-embedded.jar
를 갖고 있다면, TomcatServletWebServerFactory
가 필요할 것이라고 가정하는 식이다.
@SpringBootApplication
애노테이션을 사용하면, 해당 컨텍스트의 Auto-configuration
은 자동으로 활성화되며 이 애노테이션을 사용한다고 추가적인 효과는 없다.
Auto-configuration
은 최대한 지능적으로 작동하려고 한다. 사용자가 직접 configuration
에 많이 관여할수록 Auto-configuration
이 관여하는 부분은 더 적어진다. 애노테이션에 exclude
엘리먼트나 excludeName
엘리먼트 등을 통해 Auto-configuration
에서 제외할 클래스 등을 설정할 수 있다.
@EnableAutoConfiguration
애노테이션이 있는 클래스의 패키지는 주로 @SpringBootApplication
을 통해 명확한 중요성을 갖는다. 이를테면, @Entity
클래스들을 찾아다니는데 사용될 수 있다. (SpringBootApplication
애노테이션을 쓰지 않는다면,) @EnableAutoConfiguration
은 루트 패키지에 위치하는 것이 일반적으로 권장된다. 그래야 모든 서브 패키지와 클래스들이 정상적으로 검출될(searched) 수 있다.
Auto-configuration
클래스들은 일반적인 스프링 @Configuration
빈들이다. SpringFactoriesLoader
메커니즘에 의해 위치된다. Auto-configuration
빈들은 일반적으로 @Conditional
애노테이션이 붙어있다. (대부분은 @ConditionalOnClass
나 @ConditionalOnMissingBean
애노테이션과 같은 것이 붙어있다.)
@SpringBootConfiguration
: 스프링 부트의 설정을 나타내는 애노테이션이며, Spring의 @Configuration
애노테이션을 대체한다.@EnableAutoConfiguration
: 자동 설정의 핵심 애노테이션으로 클래스 경로에 지정된 내용을 기반으로 설정 자동화를 수행한다.@ComponentScan
: 해당 애노테이션이 위치한 패키지를 루트 경로로 빈이 등록된 클래스가 있는지 탐색한다.@ComponentScan
: 일반 Spring
프로젝트처럼 컴포넌트 스캔을 통해 컴포넌트를 찾고 빈을 생성한다. 이 과정에서 사용자가 정의한 Bean
들이 생성된다. ex) @Controller
, @RestController
, @Service
, @Repository
, @Component
, @Configuration
속@Bean
, ...
@EnableAutoConfiguration
: spring.factories
내부에 들어있는 수많은 자동 설정이 위에 설명했듯, @Conditional
조건에 따라 생성되고, 스프링 부트 애플리케이션이 시작된다.
spring.factories
의 내용은 이 링크에서 볼 수 있다.
spring-boot-autoconfigure
의존성에서 다양한 자동 설정들을 구경할 수 있다.
정리하면 컴포넌트 스캔에 검출된 컴포넌트 정보와 spring.factories
파일에 사전 정의한 Auto-configuration
내용에 의해 bean
생성을 진행한다.
spring-boot-autoconfigure
의존성 내부에 있는 파일들은 각 Auto-configuration
에 필요한 정보들을 가지고 있다.
ENABLED_OVERRIDE_PROPERTY
: auto-configuration
이 활성화됐을 때, 오버라이드를 위해 사용되는 환경 프로퍼티
@AutoConfigurationPackages
: auto-configuration
패키지임을 나타내는 애노테이션, base packages
나 base package classes
가 명시되지 않았다면 애노테이트된 클래스를 등록함
@Import(AutoConfigurationImportSelector.class)
: 핵심적인 애노테이션으로, 자동설정을 위한 클래스를 임포트하는 것을 확인할 수 있다. @Import
애노테이션은 주로 @Configuration
을 import 하려고 사용한다. 스프링 설정 XML에서의 <import />
태그와 동일한 기능을 제공한다.
.selectImports()
: AutoConfigurationSelector.class
에서는 .selectImports()
라는 메소드를 통해 애노테이션 메타 데이터를 받아서 자동으로 설정해줄 빈들을 결정한다.
.getAutoConfigurationEntry()
: .getCandidateConfiguration()
을 타고 들어가 모든 후보 빈을 불러온다. 이후에 중복된 것을 제거하고, auto-configuration
에서 exclude
한 것들을 제거한다.
.getCandidateConfigurations()
: SpringFactoriesLoader.loadFactoryNames()
메소드를 이용해서 필요한 configuration
들을 불러온다.
SpringFactoriesLoader
: 내부의 .loadFactoryNames()
메소드를 이용해서 필요한 configuration
들을 불러오는데 불러오는 위치는 결국 FACTORIES_RESOURCE_LOCATION
이고, 내부에 정의된 문자열을 보면 "META-INF/spring.factories"
에서 가져오는 것을 알 수 있다.
위는 spring.factories
의 내용이다. 수많은 빈들이 정의되어 있다. 위에 정의된 빈들은 스프링부트의 @Condition
, @Conditional
과 같은 애노테이션을 이용해 우리가 직접 정의한 빈과 충돌하지 않도록 잘 설정되어 있다.
META-INF/spring.factories
: 자동 설정 타겟 클래스 목록을 제공하며, 이 파일에 선언된 클래스들이 @EnableAutoConfiguration
애노테이션을 사용할 때 자동 설정 타겟이 된다.META-INF/spring-configuration-metadata.json
: 자동 설정에 사용할 프로퍼티 정의 파일이다. 미리 구현된 자동 설정에 프로퍼티만 주입시키면 된다. 별도의 환경 설정이 필요 없다.org/springframework/boot/autoconfigure
: 미리 구현해놓은 자동 설정 리스트이다. {설정이름}AutoConfiguration
과 같은 네이밍의 파일들로 존재한다. 모두 자바 설정 방식을 따른다.<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>ABC System</display-name>
<context-param>
<param-name>logbackConfigLocation</param-name>
<param-value>classpath:logback/logback.xml</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/application-context/*-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>abc.login.SessionAttributeListener</listener-class>
</listener>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>EnvironmentSetupFilter</filter-name>
<filter-class>abc.filter.EnvironmentSetupFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EnvironmentSetupFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/web-application-context/dispatcher-context.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
<scripting-invalid>false</scripting-invalid>
<include-prelude>/WEB-INF/jsp/commonDefinition.jspf</include-prelude>
</jsp-property-group>
<jsp-property-group>
<url-pattern>*.jspf</url-pattern>
<page-encoding>UTF-8</page-encoding>
<scripting-invalid>false</scripting-invalid>
<include-prelude>/WEB-INF/jsp/commonDefinition.jspf</include-prelude>
</jsp-property-group>
</jsp-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.html</location>
</error-page>
</web-app>
웹 애플리케이션 설정 부분 중 상당히 많은 부분을 담당한다.
<context-param>
<param-name>logbackConfigLocation</param-name>
<param-value>classpath:logback/logback.xml</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/application-context/*-context.xml</param-value>
</context-param>
위의 설정부는 스프링부트 내부 application.properties
에서
logging.config=classpath:logback/logback.xml
위와 같은 설정을 함으로써 변환할 수 있다.
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>abc.login.SessionAttributeListener</listener-class>
</listener>
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public RequestContextListener requestContextListener(){
return new RequestContextListener();
}
}
DispatcherServlet
과 RequestContextListener
, RequestContextFilter
는 모두 같은 일을 한다고 한다.
@Component
public class SessionAttributeListener implements HttpSessionAttributeListener {
public static ConcurrentHashMap<HttpSession, String> sessionMap = new ConcurrentHashMap<>();
...
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>EnvironmentSetupFilter</filter-name>
<filter-class>abc.filter.EnvironmentSetupFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EnvironmentSetupFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
스프링에서 기본으로 제공하는 필터들 (CharacterEncodingFilter
, HiddenHttpMethodFilter
, FormContentFilter
, RequestContextFilter
)은 따로 정의하지 않더라도 자동으로 동작한다고 한다. CharcterEncodingFilter
에 대한 설정은 아래와 같다.
application.properties
spring.http.encoding.charset=UTF-8
spring.http.encoding.enable=true
spring.http.encoding.force=true
스프링 시큐리티 관련 필터도 spring-security-config
의존성을 갖고 있으면, 스프링 시큐리티 3.2 버전 이후부터 직접 설정을 할 필요강 ㅓㅄ다고 한다. 그래서 SpringSecurityFilterChain
도 굳이 수동으로 해줄 필요가 없다.
커스텀 필터에 대해서는 아래와 같이 작성해준다.
@Component
public class EnvironmentSetupFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest hReq = (HttpServletRequest)request;
}
}
위와 같이 컴포넌트 스캔만 가능하도록 만들어주면 된다. 필터간의 순서는 다음과 같이 정의 가능하다.
@Component
@Order(1)
public class AFilter implement Filter {
...
}
@Component
@Order(2)
public class BFilter implement Filter {
...
}
스프링부트에서는 그냥 resource
디렉토리 밑 error
디렉토리 밑에 404.html
, 500.html
을 넣어놓으면 자동으로 인식해서 보여준다.
WebMvcAutoConfiguration
과 같은 클래스를 보면, 스프링 부트에서 web.xml
로 직접 설정해주던 복잡한 설정을 자동으로 하는 것을 볼 수 있다.
만일 스프링 부트의 의존성 관리가 없었다면 위와 같은 .xml
파일들로 직접 빈 설정을 하나하나 해주어야 했다. 하지만 스프링부트에서는 WebMvcAutoConfiguration
과 같이 미리 작성된 클래스를 이용하여 자동 설정을 해준다. 단적으로 web.xml
파일만 예를 든 것이지 실제로 설정해야 할 .xml
파일들이 매우 많다.
스프링부트 프로젝트를 만들면 의존성에 spring-boot-starter...
과 같은 의존성이 매우 많이 추가되는 것을 볼 수 있다.
starter
모듈이란 의존성과 설정을 자동화해주는 모듈을 말한다. 이를테면 spring-boot-starter-jpa
를 의존성에 추가했을 때, 스프링 부트는 아래와 같은 일을 한다.
spring-aop
, spring-jdbc
등의 의존성을 걸어준다. (easy depedency
)classpath
를 뒤져 어떤 database
를 사용하는지 파악하고 자동으로 entityManager
를 구성해준다. (auto-configuration
)auto-configuration
)위는 메이븐 리포지토리의 Spring Boot Starter
이다. 아래쪽에 보면 Compile Dependencies
라는 연관 의존성이 걸려있다.
위에서는 Spring Boot Starter 2.5.2
버전을 사용하였을 때, 어떤 스프링 버전이 가장 알맞는지, 어떤 starter-autuconfigure
을 사용해야 하는지 어떤 starter-logging
을 사용해야 하는지 자동으로 버전 의존성을 걸어준다.
starter-web
은 웹에 관련된 의존성 json
, tomcat
등의 의존성을 어떤 버전을 사용해야 하는지 모두 같이 관리되고 있는 것을 볼 수 있다.
gradle 기준으로 아래 한줄만 추가하면 된다.
implementation group: 'org.springframework.boot', name: 'spring-boot-starter', version: '2.5.2'
이로써 매우 편리하게 의존성을 관리할 수 있다. 이전의 길디 긴 pom.xml
은 이제 필요 없다.
스프링부트 의존성을 관리해주는 플러그인이 있다.
plugins {
id "io.spring.dependency-management" version "1.0.9.RELEASE"
}
스프링부트의 dependency-management
를 활용하여 프로젝트 내부에 있는 수 많은 의존성들의 버전을 한번에 관리할 수 있다.
세부 내용은 공식문서 링크에서 확인할 수 있다.
스프링 부트는 Servlet Container
를 내장하고 있다. 내장 서버를 통해 애플리케이션 배포 시 수행해야 하던 복잡한 프로세스를 비교적 단순하게 만들었다.
기존에는 .war
파일을 export 후에 이 .war
파일을 WAS(서블릿 컨테이너)가 있는 곳에 위치시켜야 했다.
이제는 .jar
파일을 export 후에 이 .jar
파일을 직접 java -jar
명령어로 실행할 수 있게 되었다. 내부적으로 내장 톰캣을 가지고 있기 때문에 가능한 일이다.
스프링
프로젝트보다는 스프링 부트
프로젝트를 만들어서 사용하는 것이 더욱 합리적으로 보인다. 좋은 개발 프레임워크를 판단하는 기준은 여러 개가 있겠지만, 그 중 큰 것은 개발자가 비즈니스 로직에 더욱 집중할 수 있게 만들 수 있냐 없냐의 차이 같다.
원래의 스프링 프로젝트의 환경 설정은 너무 까다롭고 어려웠다. 스프링 부트를 통해 내가 필요한 설정만 차근차근 배워가며 필요 없는 설정은 일단 생각하지 않고 개발을 할 수 있다.
물론 이렇게 편리하게 개발할 수 있다는 것이 오히려 사람들이 스프링 프레임워크 자체에 대한 지식 없이 스프링 개발을 하게 만들 수도 있겠지만, 그건 따로 공부해야 맞는 것 같고, 어찌됐든 스프링 부트는 혁신이라고 생각한다.
또링 스프링 vs 스프링 부트
10분 테코톡 - 또링
pom.xml, web.xml
web.xml 설정 내용 등
web.xml 부트로 마이그레이션
web.xml 부트로 마이그레이션2