서론
스프링 MVC를 책으로 공부하다가 인프런에 SpringBoot 무료 강의를 들었다.
그래서 바로 활용해 보기 위해 SpringBoot로 토이프로젝트를 진행하고 있는데 SpringMVC와 SpringBoot에 대해 정확히 알고 사용해야 할 것 같아서 찾아보게 되었다!!
먼저 간단한하게 알아보자
Spring Boot는 Spring Framework를 사용하는 프로젝트를 아주 간편하게 셋업할 수 이쓴 스프링 프레임워크의 서브 프로젝트다. 독립 컨테이너에서 동작할 수 있기에 JAVA만 설치 되어 있으면 되기 때문에 개발하기 한결 수월하다.
또한 빌드 후에 jar파일이 생성되고, 별도의 서버 설치 없이 embeded tomcat이 자동으로 실행된다.
또 프로젝트 생성 시 기존 스프링에서 처럼 복잡한 설정이 아닌 통합 설정파일인 application.yml 또는 application.properties로 간단하게 사용할 수 있다.
그렇다면 이렇게 간단하고 좋은데 모든 프로젝트에서 Spring Boot를 쓰는게 좋은걸까?
WEB기반 어플리케이션은 Tomcat이든 WAS든 Web Container가 설치 되어 있어야 한다.
하지만, 비교적 규모가 작은 형태의 애플리케이션을 실행시키기 위해 그보다 큰 WAS를 따로 설치하기엔 효율이 좋지 않다.
이렇게 규모가 작은경우에는 Spring Boot를 사용하는게 적당하다.
하지만 비교적 큰 웹 사이트 같은 경우 이런 구조로 만드는 것 보단 Spring MVC형태로 만들어서 WAS에 배포하는 스타일이 더 낫다.
embeded container에서 애플리케이션을 실행시키기엔 불안정하기도 하고 WAS에서 관리되는 데이터 소스나 메시지 서비스를 이용할 수 있기 때문이다.
그렇기 때문에 나는 가벼운 토이프로젝트를 만들고자 했으니 Spring Boot를 선택한 것은 나쁘지 않은 선택이었던것 같다!!
그래도 Spring MVC를 공부하면서 이것도 이용해 프로젝트를 하나 만들어 봐야겠다!!!

이제 스프링이 무엇인지, 스프링의 특징과 스프링과 스프링 부트의 차이점을 한번 알아보자!
🍃스프링(Spring) 이란?
스프링 프레임워크는 자바 생태계에서 가장 대중적인 응용프로그램 개발 프레임워크이다.
의존성 주입(Dependency Injection)과 제어의 역전(IOC, Inversion Of Control)은 스프링에서 가장 중요한 특징중 하나이다.
이들로 인해 좀더 결합도를 낮추는 방식으로 어플리케이션을 개발할 수 있다. 이러한 개발방식으로 개발한 응용프로그램은 단위테스트가 용이하기 때문에 보다 퀄리티 높은 프로그램을 개발할 수 있다.
스프링(Spring)의 특징
스프링의 가장 큰 특징은 제어의 역전(IOC), 의존성 주입(DI), 관점 지향 프로그래밍(AOP) 이렇게 3가지가 아닐까 싶다.
이런 특징으로 인해 결합도를 낮춰(Loose coupling) 유연한 개발이 가능해졌다.
특징들을 하나씩 살펴보자!
제어의 역전(IOC : Inversion Of Control)
제어의 역전 패턴이 인기를 끄는 이유는 프로그램의 생명주기에 대한 제어권이 웹 어플리케이션 컨테이너에 있기 때문이다.
즉, 사용자가 직접 new 연산자를 통해 인스턴스를 생성하고 메서드를 호출하는 일련의 생명주기에 대한 작업들을 스프링에 위임할 수 있게 되는 것이다.
의존성 주입(DI : Dependency Injection)
객체 사이에 필요한 의존 관계에 대해서 스프링 컨테이너가 자동으로 연결해 주는 것을 말한다.
스프링 컨테이너는 DI를 이용하여 빈(Bean)객체를 관리하며, 스프링 컨테이너에 클래스를 등록하면 스프링이 클래스의 인스턴스를 관리해준다.
의존성이란 무엇일까??
간단히 생각하면 스마트폰을 사용하기 위해서는 배터리가 필요하다. 배터리가 없으면 스마트폰을 사용할 수 없다. 즉 스마트폰을 배터리에 의존한다고 보면 된다. 만약 그 배터리가 스마트폰과 일체형으로 되어 있으면 어떤가?
배터리 교체를 하기 위해서는 분리형과 비교해서 가볍게 바꿀수가 없지 않겠는가?!
이러한 의존성에 대해서 느슨한 결합이 필요하고 의존성을 주입받아 사용받을 필요성이 있게 된다.
스프링 컨테이너에 빈(Bean)을 등록하고 설정하는 방법은 크게 두가지가 있다.
1. XML 설정을 통한 DI
2. 어노테이션(Annotations)을 이용한 DI
🛑 XML 설정을 통한 DI
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="UserAddController" class="com.lotts.web.user.UserAddController">
<property name="userImpl" ref="userImpl"/>
</bean>
<bean id="userImpl" class="com.lotts.domain.logic.UserImpl">
<property name="userDao" ref="userDao"/>
<property name="orgDao" ref="orgDao"/>
<property name="uploadpath" value="${file.upload.path}" />
</bean>
<bean id="userDao" class="com.lotts.dao.ibatis.SqlMapUserDao">
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
<bean id="OrgDao" class="com.lotts.dao.ibatis.SqlMapOrgDao">
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="WEB-INF/config/SqlMap.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
위의 내용은 아래 출처 msyu1207님이 실무에서 사용중인 내용을 약간 변형하여 작성한 것이다.
1~5라인은 파일 자체를 위한 내용이며, bean 태그를 사용하기 위한 선언이다.UserAddController는 사용자를 등록하는 컨트롤러이며 클래스인 userImpl을 ref태그를 사용해 명시했다.userImpl은 사용자 구현체 클래스이며 해당 클래스는 인터페이스인 userDao는 ref태그를 사용하여 명시할 수 있다.각각의 userDao, orgDao 인터페이스는 sql을 위한 인터페이스인 sqlMapClient를 명시했다.
SpringTest.java
public class SpringTest {
public static void main(String ar[]) {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
UserFacade userImpl = (UserImpl) ctx.getBean("userImpl");
userImpl.사용자_정보를_조회한다();
userImpl.사용자를_등록한다();
}
}
UserFacade 인터페이스에서 구현한 기능을 사용할 수 있다.
소스를 수정하지 않아도 xml의 환경설정 만으로 프로그램을 제어할 수 있게 되었다!
🛑 어노테이션(Annotations)을 이용한 DI
@Component를 사용하여 해당 클래스를 찾아 @Autowired가 붙은 클래스를 자동적으로 객체를 만들어주고 사용할 수 있게 해준다.
또한, XML에 설정에 auto scan을 설정하면 해당 패키지 범위에 Component를 설정하여 사용할 수 있다.
<context:component-scan base-package="com.lotts.web" />
@Component의 확장된 어노테이션을 사용하면 스프링은 패키지 및 하위 패키지 내에서 해당 어노테이션을 찾아서 인젝션을 한다.
@Repository - 데이터베이스에서 정보를 검색하는 DAO(Data Access Objects)에 사용된다.
@Service - 서비스 계층 클래스에 사용되며 데이터 및 비즈니스 로직 처리에 사용된다.
@Controller - UI에서 요청 처리에 사용된다.
@Controller
public class InfoController extends MultiActionController{
@Autowired
private InfoServiceImpl InfoService;
}
@Service("InfoService")
public class InfoServiceImpl implements InfoService{
@Autowired
private InfoDaoImpl InfoDao;
}
@Repository("InfoDao")
public class InfoDaoImpl implements InfoDao {
@Autowired
private SqlSessionTemplate sst;
}
Spring과 Spring Boot의 차이점
앞에서 설명한 것처럼 스프링은 IOC나 DI를 통해
의존성을 주입할 수 있기 때문에 다양한 스프링 모듈을 사용할 수 있다.
😀Spring Module
Spring MVC 프레임워크를 사용할 때 위에 applicationContext.xml이외의 다양한 설정을 통해 의존성을 주입한다.
Spring MVC는 DispatcherServlet, View Resolver, Interceptort, Handler, View 등으로 구성되어있다.
📍 web.xml
DispatcherServlet 클래스를 등록하고, url-patter 태그에서는 요청에 대해서 응답받을 수 있도록 설정한다.
또한, 인코딩 타입이나 log4j 등을 설정한다.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/conf/applicationContext.xml
/WEB-INF/conf/DataAccessContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<filter>
<filter-name>encodingFilter</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>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/conf/action-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
📍 action-servlet.xml(dispatcherServlet.xml)
뷰 리졸버는 컨트롤러에서 데이터를 받은 후 리턴할 때 뷰 이름을 지정해서 리턴해준다.
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<property name="prefix" value="/browser/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- URL Handler Mapping -->
<bean id="defaultHandlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
📍 DataAccessContext.xml
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${DB.driver}"/>
<property name="url" value="${DB.url}"/>
<property name="username" value="${DB.id}"/>
<property name="password" value="${DB.pw}"/>
<property name="defaultAutoCommit" value="false"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:/mybatisConfig/mybatisConfiguration.xml"/>
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
아직 여기서 끝이 아니다.
Spring MVC를 사용하기 위한 설정뿐만 아니라 사용해야 할 dependency를 설정해야 하며 호환되는 버전을 선택해야 합니다.
물론 아래 내용도 일부중 하나이다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-instrument -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
이처럼 MVC모델을 기반으로 어플리케이션을 만들때 상당히 많은 시간을 환경설정에만 투자하게 된다.
설정을 제대로 하지 않으면 코딩을 시작하기도 전에 404ERROR를 맛보게 된다..
그렇다면 Spring Boot를 알아보자
🙄Spring Boot
🎈Spring Boot Starter
기존에는 스프링을 사용할 때 버전까지 명시하고 버전에 맞는 설정을 하였지만, 스프링 부트는 버전 관리를 스프링 부트에 의해서 관리가 된다. 따라서 아래처럼 spring-boot-starter-web을 사용하면 종속된 모든 라이브러리를 알맞게 찾아서 함께 가져오기 때문에 종속성이나 호환 버전에 대해 신경 쓸 필요가 없게 된다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
spring-boot-starter-web은 다음과 같은 의존성이 추가된다.
🔹 starter-web
🔹 starter-webmvc
🔹 spring-boot-starter-tomcat 🔹tomcat-embed-core
🔹tomcat-embed-logging-juli
또한, spring-boot-starter-test를 쓰고 싶으면 아래처럼 추가만 해주면 된다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
🎈Embeded Tomcat
Spring Boot는 내장형 톰캣을 가지고 있기 때문에 별도의 톰캣을 설정할 필요가 없어졌으며, 그렇기 때문에 독립적으로 실행 가능한 jar로 손쉽게 배포가 가능해졌다.
🎈AutoConfigurator
공통적으로 필요한 DispatcherServlet같은 설정을 어노테이션을 이용하여 대신할 수 있도록 해준다.
Spring Boot의 main 메서드는 @SpringBootApplication 어노테이션을 가지고 있는데 이는 ComponentScan+configuration+EnableAutoConfiguration을 합친 어노테이션이라 볼 수 있다.
🍕🍕🍕출처- https://sas-study.tistory.com/274- https://msyu1207.tistory.com/m/entry/Spring-VS-Spring-Boot-%EC%B0%A8%EC%9D%B4%EC%A0%90%EC%9D%84-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90?category=640981