[Spring] MVC model 1, 2 - 개념 및 설계구조

2019. 5. 17. 00:44Spring

MVC model 1

 

  • 사용자로부터 받은 REQUEST 화면을 처리하는 기능을 SERVICE라 칭하고, 
    해당 SERVICE를 수행할 때 필요한 데이터베이스를 찾아가는 역할은 DAO가 수행한다.

  • 하지만 하나의 문서에 HTML과 JAVA 소스가 함께 작성되어 유지보수나 협업 시 어려움이 발생하는 단점이 있다.

 

MVC model 2

 

  • 컨트롤러가 요청을 받고, 그에 맞는 SERVICE를 연결한다. 일종의 모듈화로써 여러 컨트롤러들이 같은 요청을 받는 경우 해당 서비스를 공유하며 사용한다.
  • MODEL1과 동일하게 DAO를 활용하여 DB에 접근하나 이또한 각각의 기능을 공유할 수 있도록 모듈화한다.
  • 각각의 기능들이 분리되어 있어 유지보수가 용이하고, 협업 시 작업 영역이 겹치지 않는 장점이 있어 거의 모든 웹 프로젝트는 해당 MODEL 2 방식을 사용하고 있다.

 

SPRING MVC FRAMEWORK 설계구조

  • 클라이언트로 부터 요청을 받고 그 요청이 어떤 컨트롤러와 매핑할 것인가를 HANDLER MAPPING 이 선택하며,
    선택된 컨트롤러의 어떤 메서드를 실행할지 HANDLER ADAPTER가 판별하여 DISPATCHER SERVLET 에게 회신한다.
  • 최종선택 된 메서드가 실행되고 결과값으로 MODEL을 받은 후 어떠한 VIEW에 연결할 것인지 VIEW RESOLVER가 체크하여 데이터를 VIEW에 입혀주고 최종적인 화면을 클라이언트에게 돌려준다.

DISPATCHER SERVLET 설정

  • 웹 어플리케이션의 첫 관문으로 전체적인 웹 프로그램의 설정을 책임진다.
  • WEB-INF/web.xml 의 파일에 springframework 패키지 안에있는 DispatcherServlet 클래스를 참조한다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/root-context.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
 
    <!-- log4J -->
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/config/log4j.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
 
    <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>
    <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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

 

  • 루트 경로에 들어온 모든 요청을 처리하도록 기본 설정되어 있으며, 
    이 위치에서 filter 태그를 이용하여 페이지에서 처리되는 글자의 charset을 정하거나 
    스프링 컨테이너의 위치, log4j의 경로 등의 전반적인 웹 프로그램의 환경설정을 책임진다. 
  • (스프링 컨테이너를 설정하지 않은 경우 기본적으로 appServlet-context.xml을 참조하게 된다.)
  • DISPATCHER SERVLET이 HANDLER ADAPTER를 통해 CONTROLLER를 찾기 위해서는
    아래의 그림처럼 어노테이션을 읽어내는 용도의 태그를 servlet-context.xml에 정의해야한다.
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />
  • DISPATCHER SERVLET이 HANDLER ADAPTER를 통해 CONTROLLER를 찾기 위해서는
    아래의 그림처럼 어노테이션을 읽어내는 용도의 태그를 servlet-context.xml에 정의해야한다.
  • 이후 컨트롤러를 찾기위해 HANDLER ADAPTER는 각 컨트롤러 파일들을 탐색하며 매핑시켜줄 컨트롤러를 찾는다.
@Controller
@RequestMapping("/member/")
public class LoginController {
	Logger log = Logger.getLogger(this.getClass());
	 
	@Resource
	private CustomerService memberService;
	
	@RequestMapping(value={"", "/", "/login"})
	public String login() {
		return "member/login";
	}
  • 위 처럼 member로 요청된 모든 요청을 해당 컨트롤러가 처리하겠다고 어노테이션을 설정해주면 핸들러 어댑터가 이 컨트롤러를 찾게 된다.

[ 로컬 서버에 /member/login 으로 요청하였을 때, loginCheck 페이지로 매핑된 화면 ]

  • 아래의 고객정보 리스트는 하드코딩되어진 값이 아닌 데이터베이스를 조회하여 얻어낸 데이터인데
    이때 이러한 데이터들을 컨트롤러로부터 뷰가 받기 위해선 모델이라는 역할이 필요하다.
  • model은 controller에서 직접 키, 값의 쌍으로 데이터를 셋팅해주고 view로 보내게 되는데,
    model에 값을 담아 지정된 뷰로 보내는 과정이 항상 반복되어지기 때문에 이를 ModelAndView 객체를 사용하여 처리할 수 있다.
@RequestMapping(value={"loginCheck","memberList"}, method=RequestMethod.POST)
public ModelAndView loginCheck(@ModelAttribute Customer customer, HttpSession session) throws Exception {
	ModelAndView mav = null;
	int rtn = 0;
	
	try {
		mav = new ModelAndView();
		rtn = memberService.selectLoginCheckCustomer(customer);
		
	} catch (Exception e) {
		e.printStackTrace();
	}
	if(rtn < 1){
		mav.setViewName("member/login");
		mav.addObject("resultMsg", "failure");
		return mav;
	}else{
		return memberList();
	}
}

[ loginCheck 으로 요청이 들어온 경우 mav라는 객체를 만들어 매핑할 데이터와 뷰를 한번에 리턴시켜 처리하는 화면 ]

  • 이때 list 라는 값을 member/login 뷰에 넘겨주게 되는데 login이라는 뷰의 경로는 
    아래 설정을 통해 /WEB-INF/views/member/login.jsp 라는 경로를 완성시킨 후 전달한다.
<!-- 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>

'Spring' 카테고리의 다른 글

리다이렉트, 인터셉트  (0) 2019.05.16
세션, 쿠키  (0) 2019.05.16
DI(Dependency injection)  (0) 2019.05.16