728x90
300x250

[JSP] 9. MVC 디자인 패턴 - 초간단 이해, FrontController 패턴(1)


이전의 글을 보면, 순수하게 "JSP/서블릿"으로 처리하는 방법에 대해서 소개하고 있는데, 실질적으로 개발에서 자주 사용할 수 있는 패턴에 대해서 소개해보려고 한다.


기존 개발에 대해서 다시 한번 생각해보도록 하자.



그림 1. 기존 개발방법론의 문제점 - 요약


기존 개발방법론을 살펴보면, 크게 JSP, Servlet 처리에 대해서 하나의 코드 안에 "개발 코드(액션 코드 또는 동적 코드)", "사용자 인터페이스(UI)" 등이 혼잡되어 구현되는 문제가 있을 수 있다.


Servlet을 사용해보면 알겠지만, 자바 코드 내에서 홈페이지 코드라고 불리는 html, css 등을 넣어준다는 게 보통 쉬운 일이 아니다.

물론 저레벨의 C언어 등으로 개발해보면, 언어 특성 때문에 어쩔 수 없이 MVC 개발이 어려운 경우가 있을 수도 있다.


이야기하고자 하는 것은 MVC패턴으로 개발을 하게 되는 배경은 "소프트웨어공학"에서 유지보수 차원의 문제부터 역할 전문화 등의 각종 공학적인 문제 때문에 패턴이라는 게 생겼을 것으로 보인다.


[첨부(Attachments)]

200920_Diagram1.pptx




1. 디자인 패턴이란?


디자인 패턴은 프로그램을 개발할 때 사용하는 일정한 뼈대(프레임) 또는 틀이라고 생각하면 된다.


디자인 패턴만 전문적으로 다루고 있는 참고서적이나 참고 사이트가 있는데 찾아보면 도움이 될 것이라고 본다.

(다소 처음에는 이해가 안 될 수도 있음. 개발을 조금 해봐야 필요성을 인지하게 된다.)





2. Model View Controller (MVC) 디자인 패턴


php나 asp 개발을 해보면, 디자인패턴이 초기에 바로 적용되진 않는다. 

물론 최근에는 aspx(asp.net)의 경우에는 model 1, model 2 느낌의 개발이 적용되어 있다고 본다.

이유는 간단한게 C#의 직접적인 경쟁자는 Java 프로그래밍 언어라는 점이다.


Java 진영의 JSP 개발을 하게 되면, MVC 패턴의 적용을 먼저 시작하고 들어가게 된다.


그림 2. MVC Model 1, MVC Model 2 구조


도식화된 그림으로 이해하고 있어도 무방하다. 그림 1에서 언급했던 이야기는 그림 2로서 정리해볼 수가 있다.


[첨부(Attachments)]

200920_Diagram2.pptx


현재에도 Model 1이 사용되는 이유로는 장점이 있다.

초기 개발 속도에 있어서는 빠를 수가 있다.

무슨 이야기냐면, 컨트롤러와 뷰 영역을 신경쓰지 않고 개발하기 때문에 어렵게 공부하고 개발할 필요가 없는 것이다.

JSP 코드나 Servlet 코드 내에 통합적으로 코드를 집어넣으면 되는데, 굳이 컨트롤러를 복잡하게 매번 신경쓰고 개발하지 않아도 되는
프로젝트가 있을 수 있다.

Model2는 설계가 어려운 반면, 유지보수로 갔을 때는 역할 구분이 쉽다는 장점을 가지고 있다.


이전의 방법과 현재의 방법에서 적절한 방법을 찾아서 적용하는 것도 중요하다고 본다.


* 모델은 서비스와 데이터베이스 처리를 담당하는 역할을 하며, 각 로직처리, DB 질의 처리 기능을 수행한다.

* 는 JSP, CSS, HTML를 사용하여 구현함. 

* 컨트롤러는 뷰와 모델을 중개하는 역할을 수행하며, 클라이언트가 전달한 파라마터를 추출하여 모델로 전달하고, 처리결과를 보여주는 기능을 한다.



3. Eclipse의 Dynamic Web Project로 구현해보기


Apache Maven을 활용하면, 속도감이 있게 구현할 수 있겠으나 원초적인 방법으로 구현해보려고 한다.



그림 3. Dynamic Web Project - 생생하기


New 메뉴에서 Project -> Others를 누르면 위의 화면이 뜬다.

Web 폴더에서 Dynamic Web Project를 선택한 후 Next를 누른다.




그림 4. Dynamic Web Project - 생생하기


프로젝트 명을 입력하고 Next를 누른다.

Finish를 눌러도 무방하나 web.xml 파일을 자동으로 생성하려고 한다.



그림 5. Dynamic Web Project - 생생하기


Next를 누른다.



그림 6. Dynamic Web Project - 생생하기


Generate web.xml deployment descriptor에 체크를 한 후 Finish를 누르면 web.xml이 포함된 신규 프로젝트가 생성되는 것을 확인할 수 있다.



그림 7. Dynamic Web Project - 생생하기


성공적으로 신규 프로젝트가 생성되었다.



4. web.xml 설정하기


Front Controller 패턴을 적용하기 위해서 Web.xml 파일을 살짝 수정해주어야 한다.



그림 8. web.xml 수정하기


<?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 http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

  <display-name>edu-jsp-MVC</display-name>

  <welcome-file-list>

    <welcome-file>index.html</welcome-file>

    <welcome-file>index.htm</welcome-file>

    <welcome-file>index.jsp</welcome-file>

    <welcome-file>default.html</welcome-file>

    <welcome-file>default.htm</welcome-file>

    <welcome-file>default.jsp</welcome-file>

  </welcome-file-list>

  

<!-- Front Controller 패턴 -->

<servlet>

<servlet-name>front</servlet-name>

<servlet-class>com.eduJsp.controller.FrontController</servlet-class>

<init-param>

<param-name>charset</param-name>

<param-value>UTF-8</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>front</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

  

</web-app>


[소스 코드]


[첨부(Attachments)]

web.zip




5. FrontController 생성하기(서블릿) - Controller


FrontController 패턴의 초기 컨트롤러를 생성하겠다.


그림 9. Servlet 만들기 - FrontController 생성


Java Resources를 오른쪽 버튼으로 클릭한다.

New-> Servlet을 클릭한다.



그림 10. Servlet 만들기 - FrontController 생성


Java Package 명은 com.eduJsp.controller로 입력한다.

Class Name 명은 FrontController로 입력한다.

Next를 누른다.



그림 11. Servlet 만들기 - FrontController 생성


Next를 누른다.



그림 12. Servlet 만들기 - FrontController 생성


init, service만 체크해준다.

Finish를 누른다.




그림 13. Servlet-API 복사, 붙여넣기 하기


servlet-api 파일을 apahce-tomcat 설치 경로에서 lib 폴더에서 찾아보면 파일이 있다.

프로젝트의 WEB-INF/lib 폴더에 "복사, 붙여넣기"를 해준다.





6. Controller 인터페이스 생성하기 - Controller


Controller에 대한 인터페이스에 관한 것이다.

공통적으로 사용할 인터페이스이니 지정을 한번 해주면 된다.



그림 14. Interface 만들기


"com.eduJsp...." 폴더에서 오른쪽 버튼을 클릭한다.

New->Interface를 클릭한다.



그림 15. Interface 만들기


"Name(파일명)"을 Controller로 입력한다.

Finish를 누른다.



그림 16. Interface 만들기


package com.eduJsp.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public interface Controller {


public void execute(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException;

}


* 파일명: Controller.java


[첨부(Attachments)]

Controller.zip




7. AddressInsertController와 AddressListController - Controller


이번에 수행할 작업은 앞서 6에서 생성한 Controller 인터페이스를 바탕으로 List, Insert 컨트롤러를 만들어보도록 하겠다.



그림 17. Controller 구현부 - 만들기


com.eduJsp 오른쪽 버튼 -> New -> Class를 누른다.




그림 18. Controller 구현부 - 만들기


두 개를 만들어야 함. (그림 17, 그림 18과정 - 반복)
- ClassName(클래스명): AddressInsertController

- ClassName(클래스명): AddressListController


클래스를 두개 만들어준다.

참고로 클래스를 생성할 때 Interfaces를 Add하여 Finish를 누르면 메서드(Method)가 자동으로 생성된다.



8. FrontController.java 코드 작성하기(서블릿) - Controller


앞서 작성한 컨트롤러(인터페이스)를 바탕으로 FrontController를 작성해보겠다.



그림 19. FrontController.java 코드 작성


package com.eduJsp.controller;


import java.io.IOException;

import java.util.HashMap;


import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class FrontController extends HttpServlet {

private static final long serialVersionUID = 1L;

    

private String charset = null;

private HashMap<String, Controller> list = null;

    public FrontController() {

        super();

    }


    @Override

public void init(ServletConfig sc) throws ServletException {

    charset = sc.getInitParameter("charset");

    list = new HashMap<String, Controller>();

   

    list.put("/board/insert.do", new AddressInsertController());

    list.put("/board/list.do", new AddressListController());

   

}


    @Override

protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {


    req.setCharacterEncoding(charset);

    String url = req.getRequestURI();

    String contextPath = req.getContextPath();

    String path = url.substring(contextPath.length());

   

    Controller subController = list.get(path);

    subController.execute(req, res);

   

}


}



* 파일명: FrontController.java


[첨부(Attachments)]

FrontController.zip




9. HttpUtil 코드 작성하기(서블릿) - Controller


RequestDispatcher가 해당 주제에서는 핵심이라고 보면 되겠다.

앞서 작성한 AddressListController나 AddressInsertController 등에서 jsp파일 경로 등을 요청했을 때, 작업을 처리해주는 역할을 수행한다.



그림 20. HttpUtil 코드 작성


com.eduJsp 폴더를 오른쪽 버튼한다.

New->Servlet을 클릭한다.




그림 21. HttpUtil 코드 작성


Class Name은 HttpUtil로 지정한다.

Next를 누른다.



그림 22. HttpUtil 코드 작성


Next를 누른다.




그림 23. HttpUtil 코드 작성


service만 체크하고 Finish를 누른다.

함수 원형을 생성하기 귀찮아서 하나만 선택하였다.

참고로 다음 작업에서는 함수 원형을 살짝 수정할 것이다.




그림 24. HttpUtil 코드 작성



package com.eduJsp.controller;


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 HttpUtil extends HttpServlet {

private static final long serialVersionUID = 1L;

       

public static void forward(HttpServletRequest req, HttpServletResponse res, 

String path) throws ServletException, IOException {

try {

RequestDispatcher dispatcher = req.getRequestDispatcher(path);

dispatcher.forward(req, res);

}catch(Exception ex) {

System.out.println("forward 오류:" + ex);

}


}


}



* 파일명: HttpUtil.java


[첨부(Attachments)]

HttpUtil.zip




10. addressList.jsp, addressInsert.jsp 파일 생성하기 - View (뷰 영역 만들기)


이번 작업에서는 뷰 영역을 만들어주겠다.



그림 25. 뷰 생성하기


WebContent 폴더에서 오른쪽 버튼을 클릭한다.

New->JSP File을 클릭한다.




그림 26. 뷰 생성하기


File name은 addressList로 입력한 후 Finish를 누른다.



그림 27. 뷰 생성하기


File name은 addressInsert로 입력한 후 Finish를 누른다.


<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>목록 - MVC 페이지</title>

</head>

<body>

<h3>목록 - MVC 페이지</h3>

</body>

</html>


* 파일명: addressList.jsp


[첨부(Attachments)]

addressList.zip


<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>삽입 - MVC 페이지</title>

</head>

<body>

<h3>삽입 - MVC 페이지</h3>

</body>

</html>


* 파일명: addressInsert.jsp


[첨부(Attachments)]

addressInsert.zip



11. AddressInsertController.java, AddressListController.java


AddressInsertController.java, AddressListController.java 파일에 관한 것이다.


package com.eduJsp.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class AddressInsertController implements Controller {


@Override

public void execute(HttpServletRequest req, HttpServletResponse res) throws

ServletException, IOException{


HttpUtil.forward(req, res, "/WEB-INF/view/addressInsert.jsp");

}


}


* 파일명: AddressInsertController.java


package com.eduJsp.controller;


import java.io.IOException;


import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class AddressListController implements Controller {


@Override

public void execute(HttpServletRequest req, HttpServletResponse res) throws

ServletException, IOException {

HttpUtil.forward(req, res, "/WEB-INF/view/addressList.jsp");

}


}


* 파일명: AddressListController.java



12. 결과


서버에 올려서 확인해보면, 아래와 같은 결과를 출력해볼 수 있다.



그림 28. 출력하기 - 결과(1)



그림 29. 출력하기 - 결과(2)



13. UML 설계(Controller 설계)


"bottom->top" 방식으로 UML 결과를 보여주도록 하겠다.



그림 30. UML 설계도 - edu-jspMVC 프로젝트


예를 들면, 이러한 설계도를 바탕으로 코드를 작성하기에 앞서 한번 더 생각해볼 수 있다.

물론 코드 학습에 있어서는 직접 짜봐야 감이 오는 건 분명하다.


* UML 작성 프로그램: Modelio Open Source 4.0



14. 질의처리 및 로직에 관한 영역 - Model 영역(선택)


모델은 서비스와 데이터베이스 처리를 담당하는 역할을 하며, 각 로직처리, DB 질의 처리 기능을 수행한다.

패키지를 기준으로 보면, com.edu-jspMVC.service에 해당된다고 보면 된다.


모델 영역은 데이터베이스를 사용하지 않거나 복잡한 로직을 구현할 일이 없다면, 선택으로 둬도 무방할 것 같다.


14-1. VO(Value Object) - Model 영역(선택)


정보를 저장할 목적으로 만든 VO(Value Object) 객체라고 정의할 수 있다.


* tableName(테이블명): addressbook


 키

 항목명

 속성 

 PK(기본키)

num

인덱스(ID)

 

name

nvarchar2(20)

 

address

nvarchar2(100)

 

birthdate

date


표 1. addressbook 테이블


package com.eduJsp.vo;


import java.sql.Date;


public class AddressVO {

private int num;

private String name;

private String address;

private Date birthdate;

public int getNum() {

return num;

}

public void setNum(int num) {

this.num = num;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

public Date getBirthdate() {

return birthdate;

}

public void setBirthdate(Date birthdate) {

this.birthdate = birthdate;

}

}


* 파일명: AddressVO.java


[첨부(Attachments)]

AddressVO.zip




14-2. Service 설계 - Model 영역(선택)


클래스명은 "AddressService" 이런 형태로 파일을 구성하여 사용하면 된다.

인터페이스를 설계해도 무방하다.


package com.eduJsp.service;


import java.util.List;


import com.eduJsp.vo.AddressVO;


public interface IAddress {


public AddressVO getAddress(Integer num) ;

public List<AddressVO> allData();

public int insertAddress(AddressVO addressVO);

public int updateAddress(AddressVO addressVO);

public int deleteAddress(AddressVO addressVO);

}


* 파일명: IAddress.java


[첨부(Attachments)]

IAddress.zip


package com.eduJsp.service;


import java.util.List;

import com.eduJsp.vo.AddressVO;


public class AddressService implements IAddress{


@Override

public AddressVO getAddress(Integer num) {

return null;

}


@Override

public List<AddressVO> allData() {

// TODO Auto-generated method stub

return null;

}


@Override

public int insertAddress(AddressVO addressVO) {

// TODO Auto-generated method stub

return 0;

}


@Override

public int updateAddress(AddressVO addressVO) {

// TODO Auto-generated method stub

return 0;

}


@Override

public int deleteAddress(AddressVO addressVO) {

// TODO Auto-generated method stub

return 0;

}

}



* 파일명: AddressService.java


[첨부(Attachments)]

AddressService.zip




14-3. DAO(Data Access Object) - Model 영역(선택)


데이터베이스 처리에 관한 실질적인 코드를 구현하는 곳이다.

현재 프로그램들의 대부분은 DB를 사용하지만, 꼭 사용해야 하는 것은 아니다.


패키지를 기준으로 보면, "com.edu-jspMVC.dao"에 해당된다고 보면 된다.

예를 들면, 클래스명 "AddressDAO" 이런 형태로 파일을 구성하여 사용하면 된다.


여기 부분에 예를 들면, Resultset, Preparedstatement, Connection 등의 기능을 활용하여 SQL문장 등을 정의하는 것이다.


package com.eduJsp.dao;


import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;


import com.eduJsp.vo.AddressVO;


public class AddressDAO {


    public AddressVO selectAddress(Integer num) {


    Connection conn = null;

    PreparedStatement pstmt = null;

    ResultSet rs = null;

   

    AddressVO node = new AddressVO();

   

    String sql = "select NUM, NAME, ADDRESS, BIRTHDATE " +

      " from addressbook" + 

      " where num=?";

    System.out.println(sql);

   

    // 달력 날짜 출력 버그 개선

   

    try {

    //conn = session.connect();

   

    pstmt = conn.prepareStatement(sql);

    pstmt.setInt(1, num);

   

    rs = pstmt.executeQuery();

   

    if ( rs.next() ) {

    node.setNum(rs.getInt(1));

    node.setName(rs.getNString(2));

    node.setAddress(rs.getNString(3));

    node.setBirthdate(rs.getDate(4));

    }

   

   

    }catch(Exception ex) {

    System.out.println("오류 발생: " + ex);

    }

    finally {

    // session.close(conn, pstmt, rs);

    }

   

        return node;


    }

}


* 파일명: AddressDAO.java


[첨부(Attachments)]

AddressDAO.zip




15. MVC 프로젝트 구성도


MVC 프로젝트를 구성한 모습이다.



그림 31. MVC Project 구성


그림 31처럼 이런 형태로 구성된다고 보면 되겠다.



16. 맺음글(Conclusion)


글을 다소 길게 쭉 작성했는데, MVC를 좀 더 정확하게 소개하고 싶어서 그런 점 이해하길 바란다.


MVC 패턴의 원리에 대해서 JSP/Servlet을 기반으로 소개하였다.

예를 들면, Spring Frameworks를 먼저 접하기보다는 순수한 부분에 대해서도 생각해봐야 한다고 본다.



* 참고자료(References)


반응형

+ Recent posts