프로그래밍

mvc패턴 모델2의 개념과 간단한 mvc패턴 만들어보기

Jay Tech 2017. 1. 28. 19:18
반응형

모델1구조는 웹 브라우저의 요청이 곧바로 jsp에 전달된다. 웹 브라우저의 요청을 받은 jsp는 자바빈이나 서비스 클래스를 사용해서 웹 브라우저가 요청한 작업을 처리하고 그 결과를 클라이언트에 전달한다. 이것의 의미는 jsp페이지에 비즈니스 로직을 처리하기 위한 코드와 웹 브라우저에 결과를 보여줄 출력 관련 코드가 섞인 다는 것이다. 


모델2구조는 모델 1 구조와 달리 웹 브라우저의 요청을 하나의 서블릿이 받게 된다. 서블릿은 웹 브라우저의 요청을 알맞게 처리한 후 그 결과를 보여줄 jsp페이지로 포워딩 하게 된다. 포워딩을 통해서 요청 흐름 받은 jsp페이지는 결과화면을 클라이언트에 전송한다. 즉, 서블릿이 비즈니스 로직 부분을 처리하게 되는 것이다. 


모델2 구조의 특징은 웹 브라우저의 모든 요청이 단일 진입점, 즉 하나의 서블릿에서 처리된다는 점이다. 하나의 서블릿이 웹 브라우저의 모든 요청을 받기 때문에, 서블릿은 웹 브라우저의 요청을 구분할 수 있는 방법을 필요로 하며, 서블릿은 웹 브라우저의 요청을 처리한 후 웹 브라우저에 보여질 응답화면을 생성할 jsp를 선택하게 된다. 


MVC패턴


mvc패턴은 smalltalk이라는 언어에서 나온 패턴인데 모델2로 확장이 되면서 jsp에서도 사용이 되게 되었다.


핵심은 비지니스 로직을 처리하는 모델과 결과화면을 보여주는 뷰가 분리되어있고 어플의 흐름 제어나 사용자의 처리 요청은 컨트롤러에 집중되게 된다. 즉, 모델은 오직 비즈니스와 관련된 부분을 처리하면 될뿐 사용자에게 보여지는 화면이나 흐름 제어에 대해서는 처리할 필요가 없다. 뷰는 사용자의 알맞은 화면을 보여주면 된다. 컨트롤러는 사용자의 요청에 대해서 알맞은 모델을 사용하고 사용자에게 보여줄 뷰를 선택하기만 하면 된다. 


유지보수

웹 어플의 흐름 제어나 보안 설정 변경 등과 같은 유지 보수 작업이 필요할 경우 컨트롤러만 변경하면 되고, 새로운 기기의 추가가 이루어 진다면 뷰만 추가해 주면 된다. 즉 mvc패턴을 사용하게 되면 유지 보수 작업이 간단해지고 어플을 쉽게 확장할 수 있다.


- mvc패턴과 모델2 구조의 매핑


컨트롤러 - 서블릿

모델 - EJB, 자바빈

뷰 - JSP


-컨트롤러


서블릿에서

1) HTTP요청을 받는다. 서블릿의  doGet() 이나 doPost()가 호출된다.

2) 클라이언트가 요구하는 기능을 분석한다. 글쓰기를 요청했는지 읽기를 요청했는지 등의 동작을 분석한다.

3) 요청한 비즈니스로직을 처리하는 모델을 사용한다 <-> 모델

4) 결과를 request또는 session에 저장한다.

5) 알맞은 뷰를 선택하고 포워딩한다.


- 뷰


뷰 역할을 하는 jsp에서는 컨트롤러에서 request나 session 기본 객체에 저장한 데이터를 사용하여 웹 브라우저에 알맞은 결과를 출력해 준다. 즉, 뷰는 웹 브라우저가 지속적으로 컨트롤러에 요청을 보낼 수 있는 링크를 제공(글쓰기버튼과 같은)함으로써 엡 브라우저가 업무 흐름에 따라 컨트롤러에 알맞은 요청을 보낼 수 있도록 해준다.


- 모델


사실 비즈니스 로직을 처리해주면 모델이 될 수 있다.  컨트롤러로부터 요청을 받고 비즈니스로직을 수행하고 수행결과를 다시 컨트롤러에 반환 시킨다. 주로 자바빈을 사용한다. 모델은 서비스 클래스나 DAO 클래스를 이용해서 비즈니스 로직을 수행하게 된다.





간단한 MVC패턴 예제 구현하기



자 먼저 서블릿을 만들어야 한다. 서블릿은 화면에 출력할 메세지를 생성해서 jsp에 전달한다.

전형적 패턴은 이렇게 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Controller extends HttpServelt {
 
    // http요청을 받는다. doGet이든 doPost든 작성한다.
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        // ....
        process(request, response);
    }
 
    private void process(HttpServlet request, HttpServletResponse response) {
        // 요청을 분석한다.
 
        // 모델을 사용해서 기능을 수행한다.
 
          // request나 session에 처리 결과를 저장한다.
        request.setAttribute("result", result);
 
        // 뷰 포워딩(전환)
    }
 
}
cs




web.xml에 먼저 만들 클래스를 등록을 한다. SimpleController라는 서블릿을 만들건데 url맵핑을 일단한다.


1
2
3
4
5
6
7
8
9
<servlet>
    <servlet-name>SimpleController</servlet-name>
    <servlet-class>test.mvptest.SimpleController</servlet-class>
</servlet>
 
<servlet-mapping>
    <servlet-name>SimpleController</servlet-name>
    <url-pattern>/simple</url-pattern>
</servlet-mapping>

c



<servlet-name>은 서블릿 이름을 등록하는 것이니 마음대로 하시고

<servlet-class>는 실제 서블릿이 위치한 경로와 클래스명을 적어줘야 한다.

맵핑을 구현하기 위해서 <servlet-mapping> 을 써준다. 아까 등록한 서블릿 이름을 써주고

<url-pattern>은 실제 주소창에 치고 들어오는 경로를 설정해준다.



실제 컨트롤러 구현을 보면


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import java.io.IOException;
 
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class SimpleController extends HttpServlet {
 
    public void doGet(HttpServletRequest request, 
            HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
 
    public void doPost(HttpServletRequest request, 
            HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
    
    private void processRequest(HttpServletRequest request,
            HttpServletResponse response)
    throws IOException, ServletException {
        // 2단계, 요청 파악
        // request 객체로부터 사용자의 요청을 파악하는 코드
        String type = request.getParameter("type");
        
        // 3단계, 요청한 기능을 수행한다.
        // 사용자에 요청에 따라 알맞은 코드
        Object resultObject = null;
        if (type == null || type.equals("greeting")) {
            resultObject = "안녕하세요.";
        } else if (type.equals("date")) {
            resultObject = new java.util.Date();
        } else {
            resultObject = "Invalid Type";
        }
        
        // 4단계, request나 session에 처리 결과를 저장
        request.setAttribute("result", resultObject);
        
        // 5단계, RequestDispatcher를 사용하여 알맞은 뷰로 포워딩
        RequestDispatcher dispatcher =
                   request.getRequestDispatcher("/simpleView.jsp");
        dispatcher.forward(request, response);
    }
}
 
cs




doGet으로 요청을 먼저 받는다.


String type으로 들어오는 파라미터를 저장한다.

들어온 파라미터의 문자열에 따라 결과값을 가지는 resultObject에 문자열을 저장한다.

요청객체에 setAttribute에 처리 결과를 저장한다.

마지막으로 RequestDispatcher로 포워딩한다.


simpleView.jsp는 그냥 전달받은 데이터를 보여주기만 한다.



1
2
3
4
5
6
7
8
9
10
11
<%@ page contentType="text/html; charset=euc-kr" %>
 
<html>
<head><title>뷰</title></head>
<body>
 
결과: <%= request.getAttribute("result"%>
 
</body>
</html>
 
cs




이제 서버를 올려서 돌려보자.


localhost:8080/프로젝트명/simpe?type=date


get방식으로 전달하려면 ?뒤에 파라미터를 적고 =뒤에 값을 적는다. 컨트롤러에서 equals로 값 비교가 있었다. 여기에 따라 뷰에 전달되는것이 달라질 것이다.


사실 간단한 경우 JSP로만 처리하는 것이 좋지만 실제로는 그렇지 않기 때문에 이렇게 복잡하게 구조를 나눈것이다. ui변경이 필요한 경우 jsp페이지만 수정하면 되는 것이다. 왜냐하면 jsp는 로직이 포함되어 있지 않기 때문이다. 

반응형