Helmi

스프링 MVC 기본 구조 본문

Spring

스프링 MVC 기본 구조

Helmi 2023. 4. 14. 19:21

스프링 MVC는 스프링의 서브 프로젝트!

서브 프로젝트 : 별도의 설정 존재할 수 있음

예제 구조


1. 스프링 MVC 프로젝트 내부 구조

내부적으로 root-context.xml로 사용하는 일반 Java영역(POJO, Plaoin Old Java Object)과 servlet-context.xml로 설정하는 Web 관련 영역을 같이 연동해 구동

 

바깥쪽 WebApplicationContext는 기존 구조에 MVC 설정 포함하는 구조로 만들어짐

스프링은 원래 목적 자체가 웹 애플리케이션 X - 달라지는 영역에 대해 완전 분리하고 연동하는 방식

 

새로운 예제 만들기

① Eclipse(STS) 내 'Spring Legacy Project' 이용해 ex01_230413 프로젝트 생성 

(프로젝트는 'Spring MVC Project'로 생성.)

② 패키지 명은 동일하게 com.helmi.controller 지정

③ pom.xml에 스프링 버전 변경, Lombok 추가, servlet 버전 확인, maven 옵션 변경, tomcat 연결

 

웹 프로젝트는 가능하면 절대 경로 이용하는 구조 사용하는 것이 바람직하므로  Tomcat의 'Modules'에 '/' 경로로 프로젝트 실행될 수 있도록 처리. (혹은 properties의 web project settings'속성을 '/'로 지정)


2. 예제 프로젝트 로딩 구조

 

프로젝트 구동 시 관여하는 XML

- web.xml

- root-context.xml

- servlet-context.xml

web.xml : Tomcat 구동 관련 설정. 나머지 두 파일은 스프링 관련 설정

 

프로젝트 구동은 web.xml에서 시작. 상단에는 가장 먼저 구동되는 Context Listener 등록 됨

 

web.xml 일부

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

<context-param>에는 root-context.xml 경로가 설정되어 있고, <listener>에는 스프링 MVC의 ContextLoaderListener가 등록되어 있음. ContextLoaderListener는 해당 웹 어플리케이션 구동 시 같이 동작. 해당 프로젝트 실행 시 가장 먼저 로그 출력하며 기록 함.

 

root-context.xml 처리되면 파일에 있는 빈(Bean) 설정들 동작. 

root-context.xml에 정의된 객체(bean)들은 스프링의 영역(context)안에 생성되고, 객체들 간의 의존성 처리 됨

이후 스프링 MVC에서 사용하는 DispatcherServlet이라는 서블릿과 관련 설정 동작

 

web.xml 일부

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

org.springframework.web.servlet.DispatcherServlet 클래스는 스프링 MVC의 구조에서 가장 핵심적인 역할 하는 클래스

내부적으로 웹 관련 처리 준비작업 진행하는데, 이때 사용하는 파일이 servlet-context.xml

 

DispatcherServlet에서 XmlWebApplicationContext 이용해 servlet-context.xml 로딩하고 해석하기 시작. 이 과정에서 등록된 객체들은 기존에 만들어진 객체와 같이 연동 됨


3. 스프링 MVC의 기본 사상

 

Servlet/JSP에서는 HttpServletRequest/HttpServletResponse 타입 객체 이용해 브라우저에서 전송한 정보 처리.

스프링 MVC 경우, 이 위에 하나의 계층 더한 형태

 

스프링 MVC 이용하게 되면 개발자들은 직접 HttpServletRequest/HttpServletResponse 등과 같이 Servlet/JSP의 API 사용할 필요성 현저히 줄어듬. 스프링은 중간에 연결 역할 - 이런 코드 작성 하지 않고도 원하는 기능 구현 가능

 

개발자의 코드는 스프링 MVC에서 동작 - 과거는 스프링 MVC의 특정한 클래스 상속하거나 인터페이스 구현 형태로 개발 가능, 최근 개발(스프링 2.5~) 에는 어노테이션이나 XML 등의 설정만으로 개발 가능


4. 모델 2와 스프링 MVC

스프링 MVC역시 내부적으로는 Servlet API 활용. 스프링 MVC는 모델2 방식 사용. 모델 2 방식은 쉽게 말해, "로직과 화면을 분리"하는 스타일

모델 2 방식에서 사용자의 Request는 특별 상황 아닌 이상 먼저 Controller 호출. 이렇게 설계하는 가장 중요한 이유는 나중에 View 교체하더라도 사용자가 호출하는 URL 자체에 변화 없게 만들어주기 때문. 컨트롤러는 데이터를 처리하는 존재 이용해 데이터(Model) 처리하고 Response 할 때 필요한 데이터를 View 쪽으로 전달. Servlet 이용하는 경우 개발자들은 Servlet API의 RequestDispatcher등 이용해 직접 처리해 왔으나 스프링 MVC는 내부에서 이런 처리 하고, 개발자들은 스프링 MVC의 API 이용해 코드 작성함

 

스프링 MVC의 기본 구조

1) 사용자의  Request는 Front-Controller인 DispatcherServlet 통해 처리함. 생성된 프로젝트의 web.xml 보면 Request를 DispatcherServlet이 받도록 처리하는 중

 

web.xml 

<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

 

2, 3) HandlerMapping은 Request의 처리 담당하는 컨트롤러 찾기 위해 존재. HandlerMapping 인터페이스를 구현한 여러 객체들 중 RequestMappingHandlerMapping같은 경우는 개발자가 @RequestMapping 어노테이션이 적요오딘 것을 기준으로 판단하게 됨. 적절한 컨트롤러가 찾아졌으면 HandlerAdapter 이용해 해당 컨트롤러 동작시킴

 

4) Controller는 개발자가 작성하는 클래스. 실제 Request를 처리하는 로직 작성하게 됨. 이때 View에 전달해야하는 데이터는 주로 Model이라는 객체에 담아 전달. Controller는 다양한 타입의 결과 반환하는데, 이에 대한 처리는 ViewResolver 이용

 

5) ViewResolver는 Controller가 반환한 결과를 어떤 View를 통해 처리하는 것이 좋을지 해석하는 역할. 가장 흔하게 사용하는 설정은 servlet-context.xml에 정의된 InternalResourceViewResolver

 

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>

 

6,7) View는 실제 응답 보내야하는 데이터를 Jsp 등 이용해 생성하는 역할 하게 됨. 만들어진 응답은 DispatcherServlet 통해 전송

 

그림 보면 모든 Request는 DispatcherServlet 통하도록 설계, 이런 방식을 Front-Controller패턴이라 함. Front-Controller 패턴 이용하면 전체 흐름 강제로 제한 가능. ex) HttpServlet 상속해서 만든 클래스를 이용하는 경우 특정 개발자는 이를 활용 가능 but 다른 개발자는 자신이 원래 하던 방식대로 HttpServlet을 그대로 상속해 개발 가능. Front-Controlelr 패턴을 이용하는 경우 모든 Request의 처리에 대한 분배가 정해진 방식대로만 동작하므로 좀 더 엄격한 구조 만들 수 있음.

'Spring' 카테고리의 다른 글

MyBatis + Spring 연동  (0) 2023.04.13
커넥션 풀 설정  (0) 2023.04.12
스프링 특징, 의존성 주입  (0) 2023.04.12
스프링 설명 조금 + 설정 시 Java Configuration 하는 경우  (0) 2023.04.11
구) 스프링 + Mybatis 실전  (0) 2023.04.07