티스토리 뷰

웹 개발/STS

스프링 MVC

빵파레2 2019. 6. 4. 21:03

스프링 MVC 란?


스프링 MVC는 스프링의 서브 프로젝트 중 하나이다.

(스프링은 웹을 위해서 만들어진 프레임워크가 아니며 'core' 라는 프레임워크에 여러 서브 프로젝트를 결합하는 구조를 가진다.)

스프링은 Java기반의 프레임워크로서 여러 모듈로 구성되어 있는데, 이중 웹 어플리케이션을 만들고자 등장한 것이 SpringMVC 모듈이다.

 

M (Model)

  • 핵심기능, 데이터 처리 등 주로 DB쪽을 담당함
  • Controller에서 View로 객체를 전달하는데 사용된다.

V (View) 

  • 주로 디자인에 관련된 부분으로 사용자에게 정보를 출력
  • Model data의 렌더링을 담당하며, HTML output을 생성한다.
  • 모델로부터 제공된 데이터를 다양한 뷰를 통해 표시하며, 각 뷰마다 컨트롤러가 연결되어 있음
  • JSP 이외에도 Thymeleaf, Groovy, Freemarker 등의 Template Engine이 있다.

C (Controller)

  • 요청을 처리하는 부분으로 뷰와 모델사이의 통신 역할을 담당함
  • Model/View에 대한 사용자 입력 및 요청을 수신하여 그에 따라 적절한 결과를 Model에 담아 View로 전달한다.
  • Model Object와 Model을 화면에 출력할 View Name을 반환한다.
  • Servlet

MVC의 장점

비즈니스 로직과 프리젠테이션 로직이 분리되어 있어서 디자이너와 개발자의 영역이 분리됨으로써

각자의 영역에 더 집중할 수 있음. 또한 유지보수가 용이함.

(JSP 파일에 모든 로직을 다 때려박는 방식과는 확실하게 차별화 됨)

 

 

스프링 실행순서


1. 웹 어플리케이션 실행 시 Tomcat(WAS, Servlet Container) 에 의해 web.xml이 Loading

Servlet Container는 Servlet들의 저장소로 봐도 무방하다.

Java로 웹을 개발하기 위해 여러 Servlet들이 필요하게 되는데, 이러한 Servlet들의 Life Cycle (생명주기) 관리, 멀티쓰레드 지원 (Servlet Container는 요청이 들어올 때마다 새로운 자바 스레드를 만든다) 등을 하고 있는 것이

Servlet Container이다. 

Tomcat 과 같은 WAS가 Java파일을 컴파일해서 Class로 만들고 메모리에 올려 servlet객체를 만든다.

(대표적인 Servlet 컨테이너가 바로 Tomcat)

Spring MVC 역시 Servlet Container가 관리하고 있는 Servlet이다. 

 

Servlet이란?
웹프로그래밍에서 클라이언트의 요청을 처리하고 그 결과를 다시 클라이언트에게 
전송하는 Servlet 클래스의 구현 규칙을 지킨 자바 프로그래밍 기술

 

2. web.xml에 등록되어 있는 ContextLoaderListener (Java Class) 생성

서블릿 컨테이너가 web.xml 파일을 읽을 때 ContextLoaderListener 가 자동으로 메모리에 생성된다.

ContextLoaderListener 클래스는 ServletContextListener 인터페이스를 구현하고 있으며,

ApplicationContext를 생성하는 역할을 수행한다.

 

3. 생성된 ContextLoaderListener는 root-context.xml을 Loading

ContextLoderListener 객체는 src/main/resources 소스 폴더에 있는 /WEB-INF/spring/root-context.xml

파일을 로딩하여 스프링 컨테이너를 구동하는데 이를 Root 컨테이너라고 한다.

 

4. root-context.xml에 등록되어 있는 Spring Container가 구동

root-context.xml 에는 주로 view 자원을 제외한 공통 bean을 설정한다.

(web과 관련된 bean들은 등록해주지 않음, 주로 database, repository 설정을 주로함)

 

5. 클라이언트로부터 웹 어플리케이션 요청이 옴

 

6. DispatcherServlet 생성

최초의 클라이언트 요청에 의해 DispatcherServlet이 생성됨

DispatcherServlet 객체는 servlet-context.xml 파일을 로딩하여 두번째 스프링 컨테이너를 구동한다.

 

DispatcherServlet 이란?
- Spring Framework가 제공하는 Servlet 클래스
- Spring MVC로의 모든 요청과 응답을 관리함 (Front controller의 역할을 수행)
DispatcherServlet 에서 받은 요청은 HandlerMapping으로 넘어간다.
장점
-
뷰에서 들어오는 모든 요청을 담당하여 웹  애플리케이션을 실행하는 모든 요청을 일괄적으로 처리할 수있습니다.
- 기존에는 모든 서블릿에 대해 URL 매핑을 활용하기 위해서 web.xml에 모두 직접 등록해주어야 했지만
  DispatcherServlet을 통해 URL패턴을 적는 식으로 일괄적으로 처리가 가능

 

7. DispatcherServlet은 servlet-context.xml을 Loading

 

8. 구동순서

 

 

1. 클라이언트가 해당 어플리케이션에 접근하면 접근한 URL 요청을 DispatcherServlet이 가로챈다.

   이렇게 요청을 가로챌 수 있는 이유는 web.xml에 등록된 DispatcherServlet의 <url-pattern>이 '/'와 같이 해당

   어플리케이션의 모든 URL로 등록되있기 때문이다.

   만약 특정 URL만 적용하고 싶다면 <url-pattern>의 내용을 바꿔주어 범위를 변경시키주면 된다.

   (Spring MVC로의 모든 요청과 응답은 DispatcherServlet이 관리하고 있다.)

 

2. DispatcherServlet은 HandlerMapping (@RequestMapping으로 봐도 무방) 에게 해당 요청을 처리할 수 있는

   Controller를 찾아내어 요청을 Controller에게 보내고 결과값을 리턴해준다.

 

HandlerMapping 의 역할?
- 사용자의 요청을 처리할 Controller를 찾는다. (Controller URL Mapping) 
- 요청 url에 해당하는 Controller 정보를 저장하는 table을 가진다. 
-  해당 URL에 대한 요청이 들어왔을 때 table에 저장된 정보에 따라 해당 클래스 또는 메서드에 Mapping한다.

 

3. Controller는 URL 요청을 통해 받은 데이터를 DTO를 통해 매핑하여 Service로 전달한다.

 

4. Service를 통해 비즈니스 로직을 처리한 후 DAO를 통해 DB에 접근한다.

 

5. Controller는 DB로 부터 응답받은 DTO와 응답받을 View의 이름을 리턴하게 됩니다.

   그 때 이 View의 이름을 ViwResolver가 먼저 받아 해당하는 View가 존재하는지 검색한다.

ViewResolver의 역할?
- Controller가 반환한 View Name(the logical names)에 prefix, suffix를 적용하여 View Object(the physical view files)를 반환한다. 

 

6. 해당 View가 있다면 처리결과를 View에 보낸다. 그리고 이 결과를 다시 DispatcherServlet에 보낸 후   

   DispatcherServlet은 최종 결과를 클라이언트에 전송한다.

 

 

 

 

레거시 프로젝트 생성


 

 

 

 

  • 레거시 프로젝트 생성 시 위와 같은 폴더구조가 생겨난다.
  • 프로젝트 구동 시 관여하는 XML은 web.xml, root-context.xml, servlet-context.xml 파일이다.
  • web.xml은 Tomcat 구동과 관련된 설정이고, root-context.xml, servlet-context.xml 파일은 스프링과 관련된 설정이다.

 

web.xml


ContextLoaderListener에 의해 root-context.xml이 구동되고 DispatcherServlet에 의해 servlet-context.xml이 구동됨

 

 

root-context.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.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
		
</beans>

이번 예제에서는 데이터베이스 설정이나 service를 구현하지 않을 것이라서 root-context.xml에서 별도의 설정을 추가하지 않음.

 

 

servlet-context.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<context:component-scan base-package="com.practice.springmvc" />
	
</beans:beans>

레거시 프로젝트를 생성하면 기본적으로 servlet-context.xml에 위와 같은 설정이 추가되어 있음

(resources (css, js, img 등) 의 요청 경로 설정, ViewResolver 설정, component-scan 설정)

 

 

MainController, Main.jsp 생성


 

MainController.java

package com.practice.springmvc;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MainController {

	@RequestMapping(value = "/main")
	public String initMain(ModelMap model) {
		
		model.addAttribute("main", "hello MVC!");
		
		return "main";
	}
}

main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
	<title>Main</title>
</head>
<body>
<h1>
	메인화면 입니다!
</h1>

<P>  컨트롤러에서 전달받은 모델은 ${main} 입니다. </P>
</body>
</html>

컨트롤러에서 return 값으로 적힌 논리적 주소 main은 ViewResolver에서 설정된 prefix (/WEB-INF/views) + main + suffix (.jsp) 로 적용되어 view Object로 반환된다.

또한 model을 통해 전달해준 데이터를 이용하여 view를 그리고 DispatcherServlet으로 전달한다.

 

 

실행결과


 

 

마무리


STS에서 처음 레거시 프로젝트를 생성할 때 Spring MVC 프로젝트로 선택해서 생성할 경우 위에서 공부했던 Spring MVC의 내부 구동 과정에 대해서 일일이 다 생각해서 구현할 필요가 없었다.

내가 스프링 MVC를 실습하면서 직접 구현한 것이라고는 Controller, Model, View (jsp) 가 전부였다.

즉, Spring MVC의 내부 아키텍쳐는 굉장히 어렵고 복잡하다고 느꼈지만 Spring 에서는 그것을 굉장히 쉽고 간단하게 

사용할 수 있도록 지원을 해주어서 굉장히 편리하게 Spring MVC를 구현할 수 있었다.

 

 

참고자료


https://javannspring.tistory.com/231

https://private.tistory.com/7?category=704776

http://egloos.zum.com/springmvc/v/504151

https://server-engineer.tistory.com/253

https://gmlwjd9405.github.io/2018/12/20/spring-mvc-framework.html

구멍가게 코딩단 지음, 코드로 배우는 스프링 웹 프로젝트 개정판, 남가람북스

'웹 개발 > STS' 카테고리의 다른 글

스프링의 특징  (0) 2019.06.03