본문 바로가기
Framework/Spring Framework

[Spring Framework] MVC 기초(원리와 구조)

by 사용자 원동호 2018. 7. 25.

스프링의 전체적인 구조

클라이언트의 요청 -> DispatcherServlet가 클라이언트의 최초 요청을 받음 -> HandlerMapping ,HandlerAdapter, Controller, View, ViewResolver로 요청을 보낸다.

 

우리가 건드릴 부분은 View단과, Controller단

 

DispatcherServlet에서 Controller에게 요청을하고 Controller에게 무언가 응답을 받으면 DispatcherServlet은 ViewResolver를 통해 View가 응답이 되는 구조이다.

 

정리하자면

DispatcherServlet은

1) 클라이언트의 요청을 최초로 받아

2) 컨트롤러에게 전달한다.

 

 

프로젝트 생성

빨간줄로 그어논 부분(Test)이 내가 생성하고자 하는 프로젝트의 Context 명이다.

com.test 는 내가 생성하고자 하는 프로젝트의 default package 명이다.

 

 

기본 디렉토리 구조

 

유심히 보아야 할 파일

web.xml 

dynamic web project에서 JSP할때 servlet-mapping해주는 부분이랑 동일한 파일

1)DispatcherServlet 서블릿  매핑

2) 스프링 설정 파일 위치 정의(servlet-context.xml 등등..)

<servlet> 		
	<servlet-name>appServlet</servlet-name> 	
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 	
	<init-param> 			
		<param-name>
			contextConfigLocation
		</param-name> 	
		
		<param-value> 
			//dispatcherservlet에서 appServlet디렉토리 밑의 servlet-context.xml을 읽어드리라고 명시되어있다. 
			//프로젝트 실행시 web.xml을 먼저 읽어드린 후 servlet-context.xml을 읽어드린다. 			
			/WEB-INF/spring/appServlet/servlet-context.xml 			
		</param-value> 		
	</init-param> 		
	<load-on-startup>1</load-on-startup> 	
	<async-supported>true</async-supported> 
</servlet> 
<servlet-mapping> 
	<servlet-name>appServlet</servlet-name> 
	// " / " 으로 들어오는 요청은 DispatcherServlet으로 매핑하라고 명시되어있음. 
	// 이 부분도 사용자가 원하는대로 custom 가능	 
	<url-pattern>/</url-pattern> 
</servlet-mapping> 

 

servlet-context.xml

bean과 스프링 컨테이너 설정 하는 부분

//ViewResolver가 property로 정한 prefix인 /WEB-INF/views/ 디렉토리 + 내가설정한 ViewName + 
//suffix인 .jsp 로 뷰 페이지 이름만 정해주면 ViewResolver가 알아서 뷰 페이지를 찾아준다. 
//custom directory를 사용하고싶다면, prefix값을 사용자가 임의로 수정해주면된다. 
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
<beans:property name="prefix" value="/WEB-INF/views/"> 
	<beans:property name="suffix" value=".jsp"> 
</beans:property></beans:property></beans:bean>

 

그렇다면 DispatcherServlet은 어떻게 Controller를 인식하고 요청할까?

 

JAVA Class위에 @Controller라고 어노테이션을 붙여줌으로써 인식한다.

단지 어노테이션만 붙여주면 컨트롤러라고 인식을할까?

servlet-context.xml을 다시한번 보자

<!-- 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.test.TEST" />
<context:component-scan base-package="com.test.Test" />

 

프로젝트를 실행하게 되면 servlet-context.xml 파일을 읽으면서 스프링이 사용자가 "지정한 패키지 " 들을 스캔하게된다.

스캔을 하면서 @Controller, @Service 등등.. 어노테이션을 찾게되면 스프링은 해당 클래스가 컨트롤러,서비스 등등 으로써 인식을 하게된다.

 

패키지가 여러개 있다면 <context ~/>를 더 추가해주면 될것이다.

 

프로젝트를 실행 시켜보았다. 콘솔 창을보면 스프링 프레임워크가 appServlet을 초기화하면서 

사진에는 짤렸지만 servlet-context.xml을 읽고 있다고 나와있다. 그런 후 package들을 scan하면서 어노테이션이 있는 클래스들을 찾는다.

 

이번에는 Controller단으로 가보겠다.

@Controller 
public class HomeController { 
		@RequestMapping(value = "/", method = RequestMethod.GET) 	
		public String home(Locale locale, Model model) { 		
		logger.info("Welcome home! The client locale is {}.", locale); 		
		return "home"; 	
	} 
}
	

@RequestMapping(value ="/"~) 이 부분은 "/"로 요청이 들어오면 이 메소드를 실행해라 라는 말이다. 

못봤을 수도 있지만 위에서 DispatcherServlet이 Controller에게 요청을 하면 Controller단에서 무언가 응답을 받는다고 했었다.

위의 소스에서는 return 값으로 "home"이라는 값을 반환하고있다. 여기서 "home" 은 뷰 페이지를 의미한다.

DispatcherServlet은 Controller에게 응답을받은 return 값을 ViewResolver로 전달 하게 되고,

ViewResolver은 prefix + return 값 + suffix 을 조합해 사용자에게 "home.jsp"의 뷰 페이지를 보여주게 되는것이다.

 

정리를 해보면

 

1. 예를들어 사용자가 http://wondongho.com/Test/ 홈페이지로 접속을 했다. 

2. 사용자는 당연히 해당 뷰페이지를 보고있겠지만 스프링 내부적으로는 사용자(http://wondongho.com/Test/)의 요청을 받음. 

3. " / "로 요청되었기 때문에 DispatcherServlet이 사용자의 요청을 받아, servlet-context.xml을 읽어 드릴것이다. 

4. servlet-context.xml에서는 <context:component-scan ~/>으로 해당 package를 스캔하게 되며 어노테이션을 찾음. 

5. @Controller가 명시되어있는 클래스로 간 후 value값이 "/"인 메소드를 찾아 실행 후 DispatcherServlet에게 값을 return. 

6. return 값을 DispatcherServlet이 받아 ViewResolver에게 요청. 

7. ViewResolver은 해당 prefix값, return값, suffix값을 조합해 사용자에게 뷰 페이지를 보여주게 된다. 

 

설명이 너무 장황하고 복잡할 수 있지만 양해 부탁드립니다!

 

 

 

댓글0