|
Space Map
|
1장. 사용자 관리 프로젝트로 알아본 스트럿츠 탄생 배경Summary : 스트럿츠 프레임워크 워크북의 1장 원고를 통하여 스트럿츠 탄생 배경에 대하여 총 5번의 강좌를 통하여 알아본다. 이번 강좌에서는 앞의 강좌에서 만든 모델을 바탕으로 사용자 관리 프로젝트를 완성하겠다. 단, 개발 방법은 이 시리즈를 통하여 다루게 될 모델 2 개발 방법을 사용하겠다. 4. 모델 2 개발방식으로 개발..웹 애플리케이션의 규모가 점점 커지며서 모델 1개발 방식의 한계점이 많은 기업들에게 유지보수 비용의 증가라는 결과를 가져오게 되었다. 따라서 많은 기업들은 이 같은 문제점을 극복하기 위한 대안으로 웹 애플리케이션 개발에 모델 2 개발 방법을 채택하려는 시도가 증가하고 있다. 이 절에서는 모델 2 개발 방식을 적용하여 사용자 관리프로젝트를 완성하도록 하겠다. 모델 1 개발 방식과 모델 2 개발 방식의 차이점에 대하여 살펴보면서 모델 2 개발 방식이 무엇인지 살펴보도록 하겠다. 마지막으로 모델 2 개발 방식의 장점과 한계점에 대해서 알아보도록 하겠다. 4.1 모델2 개발방식이란? 모델 2 개발 방식(이하 모델2)과 모델 1 개발 방식의 가장 중요한 차이점은 클라이언트의 요청이 진입하는 지점이 다르다는 것이다. 모델 1의 초기 진입 지점은 JSP가 담당하였지만 모델2의 진입 지점은 컨트롤러(Controller)라는 부분을 따로 두어 처리한다. 대부분 웹 애플리케이션의 컨트롤러는 서블릿이 담당하게 된다. 다음 그림을 보면 더 쉽게 이해할 수 있을 것이다. ![]() [그림 1-12]는 모델 2 방식으로 클라이언트의 요청을 처리하는 과정을 도식화한 것이다. [그림 1-12]의 초기 진입점을 보면 JSP가 아닌 서블릿이라는 것을 알 수 있다. 클라이언트의 요청이 모델2로 처리되는 세부과정은 다음과 같다.
이상의 과정을 통하여 클라이언트의 요청이 처리된다. 모델1에 비하여 한번의 요청이 처리되는 과정이 많고 복잡하기 때문에 모델2를 처음 접하는 개발자들은 이해하기 힘들다. 모델 2가 개발하기 복잡한 것으로 보이지만 실질적으로 개발을 진행해보면 요청에 대한 처리가 명확하기 때문에 익숙해지면 모델 1보다 더 쉽게 개발할 수 있다. [그림 1-12]와 같이 컨트롤러, 모델, 뷰로 구분하여 개발하는 방법을 모델-뷰-컨트롤러(MVC, Model-View-Controller, 이하 MVC패턴)패턴이라 부른다. 모델 2는 MVC패턴를 바탕으로 개발하는 것이다. 앞으로 살펴볼 스트러츠의 근간 또한 MVC패턴이다. 모델, 뷰, 컨트롤러가 담당해야 역할을 살펴보고 예제 소스로 넘어가도록 하겠다. 모델은 2절에서 살펴본 바와 같이 데이터베이스, 레거시 시스템들과의 통신을 담당하고 있으며, 애플리케이션의 비즈니스 로직의 구현을 전담하는 파트이다. 뷰는 참고사항 모델 2 개발 방식을 둔 이유. 스트럿츠 자체가 모델2라고 볼 수 있다. 따라서 모델 1을 설명한 다음 스트럿츠의 설명으로 바로 넘어갈수도 있었다. 이 책의 의도 또한 스트럿츠에 초점을 맞추고 있기 때문에 어쩌면 당연히 그렇게 해야할지도 모르겠다. 하지만 모델 1을 살펴본 다음 바로 스트럿츠으로 넘어간다면 스트럿츠 프레임워크의 복잡한 구조 때문에 모델 2 개념에 대하여 이해하는 것은 힘들다고 생각한다. 따라서 스트럿츠를 살펴보기 전에 모델 2의 필수적인 항목들을 포함하여 최대한 간단하게 예제를 만들어 보았다. 이 책이 스트럿츠에 중심을 두고 있지만 그에 앞서 모델 2를 이해하는 것이 무엇보다도 중요하다. 모델 2를 모르는 상태에서 스트럿츠의 모든 기능을 100%활용하기란 힘들다. 모델2에 대한 정확한 이해가 선행된 다음 스트럿츠를 이해하는 것도 훨씬 더 빠르다. 지금도 모델 2에 기반한 수많은 프레임워크가 등장하고 있다. 스트럿츠가 아닌 다른 프레임워크를 이용하여 개발한다고해도 모델 2에 대한 기반 지식이 있는 개발자들은 더 빠르게 새로운 프레임워크를 사용할 수 있다. 그 만큼 모델 2 개념은 중요하다. 따라서 이 절에서 살펴볼 모델 2에 대하여 정확히 이해하기 전에는 다음 절로 넘어가지 말기 바란다. 4.2 모델2 개발방식으로 사용자 관리 프로젝트 완성. 모델 1에서는 JSP가 대부분의 처리를 담당했기 때문에 모델이 만들어져 있다면 JSP의 내용만 살펴보면 되었다. 그러나 모델2는 서블릿, 모델2를 위한 기본 클래스 준비가 되어 있어야 ![]() [그림 1-13]은 사용자 관리 프로젝트를 모델 2로 구현하기 위한 기본적인 구조를 보여주고 있다. [그림 1-12]와 비교해 보면 기본적인 골격은 같다는 것을 알 수 있다. [그림 1-13]의 클래스 다이어그램에서 뷰와 모델을 제외한 클래스들이 컨트롤러 역할을 담당하는 클래스들이다. 사용자 관리 프로젝트를 위하여 Action 인터페이스를 구현하는 클래스들이 더 많지만 지면 관계상 3개의 클래스만을 보여주고 있다. 사용자 관리 프로젝트에서 초기 진입점은 UserServlet이 담당한다. UserServlet 뒤에는 JSP에서 전달되는 명령어에 따라 해당 Action 클래스를 반환해주는 UserCommandFactory 클래스가 존재하는 구조이다. 컨트롤러에서 가장 중요한 클래스군은 Action인터페이스와 이를 구현하는 여러 개의 클래스이다. JSP가 요청한 실질적인 작업은 Action 인터페이스를 구현하는 하위 클래스들이 한다. 예를들어 새로운 사용자를 추가하기 위하여 모델의 UserManager와 통신하는 일은 InsertAction 클래스에서 이루어진다. 또한 로그인 작업은 LoginAction클래스가 담당한다. 따라서 JSP는 뷰를 위한 작업만을 전담하게 되며, 나머지 작업들은 UserServlet과 각각의 Action클래스가 실행하게 된다. 마지막으로 각각의 Action클래스가 모델과 통신작업을 완료한 다음 이동하게될 다음 페이지를 결정하기 위한 정보를 ActionForward에 담겨 UserServlet에 반환된다. ActionForward클래스는 이동할 페이지 정보와 포워드(forward), 리다이렉트(redirect)중 어느 방식으로 다음 페이지로 이동할 것인지에 대한 정보를 담고 있다. 웹 애플리케이션 작업시 포워드(forward), 리다이렉트(redirect)의 차이점을 이해하고 정확히 사용하는 것이 중요하다. 참고 문서 HttpServletResponse의 sendRedirect와 RequestDispatcher의 차이점 : 포워드와 리다이렉트 :
모델 2 개념을 이해하기 위해서는 [그림 1-13]의 클래스 다이어그램에서 컨트롤러 파트에 해당하는 클래스들의 역할을 반드시 알아야한다. 또한 클라이언트로부터 시작된 요청이 컨트롤러, 모델, 뷰 순으로 처리되는 과정을 이해할 필요가 있다. 이 두가지만 이해한다면 모델 2에 대한 개념을 확실히 잡을 수 있을 것이다. 지금까지 사용자 관리 프로젝트를 위한 모델 2의 근간이 되는 클래스들의 기본적인 구조를 살펴보았다. 지금부터 각 클래스들의 예제 소스를 살펴보면서 모델 2를 더 깊이 이해할 수 있도록 하자. 모델 2에서 제일 먼저 작성해야 하는 클래스는 클라이언트로부터의 모든 요청의 초기 진입점에 해당하는 서블릿이다. [그림 1-13]에서는 UserServlet클래스가 그 역할을 담당하고 있다. package net.javajigi.model2; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.javajigi.model2.action.Action; /** * @web.servlet name="user" * display-name="User Manager Servlet" * * @web.servlet-mapping url-pattern="*.m2" */ public class UserServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ActionForward forward = null; Action action = null; try { /* * CommandFactory에 요청에 의하여 전달된 action을 전달하여 * 해당하는 Action객체를 생성한다. */ UserCommandFactory cf = UserCommandFactory.getInstance(); String command = request.getParameter("command"); if (command == null) { command = "list"; } action = cf.getAction(command); forward = action.execute(request, response); } catch (Exception e) { throw new ServletException(e.getMessage()); } /* * Action에 의해서 전달된 User, List객체들이 response객체를 통하여 전달된다. */ if ( forward.isRedirect()) { response.sendRedirect(forward.getPath()); } else { RequestDispatcher rd = request.getRequestDispatcher(forward.getPath()); rd.forward(request, response); } } } [예제 1-6]은 UserSerlvet클래스의 doPost() 메소드 내부이다. UserSerlvet클래스는 UserCommandFactory 클래스를 통하여 JSP에서 전달된 command 인자에 따라 해당 작업을 수행할 Action클래스를 얻어온다. 반환된 Action클래스의 execute() 메소드를 실행하여 사용자 생성, 수정, 삭제등의 작업을 실행한다. 마지막으로 Action클래스의 작업 결과 반환된 ActionForward클래스의 정보를 이용하여 다음으로 이동할 뷰페이지를 결정하게 된다. ActionForward의 정보에 따라 페이지 이동을 포워드, 리다이렉트방식으로 할지 결정하게 된다. "그렇다면 도대체 클라이언트의 어떻게 UserSerlvet클래스를 사용자 관리 프로젝트의 초기 진입점으로 이용할 것인가?" 하는 궁금증이 발생할 것이다. 이에 대한 해결책은 web.xml에 있다. 많은 개발자들이 이미 사용하고 있는 web.xml의 서블릿 매핑을 이용하여 UserSerlvet을 사용자 관리 프로젝트의 초기 진입점으로 사용할 수 있다. web.xml의 내용은 다음과 같다. <web-app > <servlet> <servlet-name>user</servlet-name> <display-name>User Manager Servlet</display-name> <servlet-class>net.javajigi.model2.UserServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>user</servlet-name> <url-pattern>*.m2</url-pattern> </servlet-mapping> </web-app> 많은 개발자들이 서블릿을 사용해본 경험이 있기 때문에 web.xml에 위와 같이 설정해 보았을 것으로 생각한다. [예제 1-7]의 web.xml이 가리키는 내용은 확장자가 m2인 모든 요청은 UserServlet이 먼저 요청을 처리하도록 설정하는 것이다. 따라서 초기 진입점을 UserServlet이 담당하도록 하기 위해서는 모든 요청은 m2의 확장자를 가져야 한다. 예를 들어 모델 1에서 userlist.jsp로 요청했다면 모델 2에서는 userlist.m2로 요청해야한다. userlist.m2 요청은 먼저 UserServlet으로 진입한 다음 사용자 리스트 정보를 모델에서 찾은 다음 userlist.jsp에 전달하게 된다. 따라서 userlist.jsp는 반환된 사용자 리스트를 보여주는 역할만 담당하면 되는 것이다. 지금은 이 말이 무슨 말인지 이해되지 않지만 계속되는 예제들을 통하여 이해할 수 있을 것이다. 다음은 UserSerlvet으로 전달된 요청이 처리되는 뒷부분의 작업에 대하여 살펴보도록 하자. package net.javajigi.model2; import net.javajigi.model2.action.Action; import net.javajigi.model2.action.DeleteAction; import net.javajigi.model2.action.IllegalCommandException; import net.javajigi.model2.action.InsertAction; import net.javajigi.model2.action.InsertFormAction; import net.javajigi.model2.action.ListAction; import net.javajigi.model2.action.LoginAction; import net.javajigi.model2.action.LoginFormAction; import net.javajigi.model2.action.UpdateAction; import net.javajigi.model2.action.UpdateFormAction; import net.javajigi.model2.action.ViewAction; public class UserCommandFactory { private UserCommandFactory() { } public static UserCommandFactory getInstance() { return new UserCommandFactory(); } /* * 수행해야할 명령어에 해당하는 Action객체를 생성. */ public Action getAction(String command) throws IllegalCommandException { Action action = null; if (command.equals("list")) { action = new ListAction(); } else if (command.equals("view")) { action = new ViewAction(); } else if (command.equals("insert")) { action = new InsertAction(); } else if (command.equals("update")) { action = new UpdateAction(); } else if (command.equals("delete")) { action = new DeleteAction(); } else if (command.equals("login")) { action = new LoginAction(); } else if (command.equals("updateForm")) { action = new UpdateFormAction(); } else if (command.equals("insertForm")) { action = new InsertFormAction(); } else if (command.equals("loginForm")) { action = new LoginFormAction(); } else { throw new IllegalCommandException("잘못된 실행명령입니다. 다른 명령을 실행해 주십시요"); } return action; } } [예제 1-8]은 UserSerlvet에서 전달된 명령어에 따라 해당하는 Action클래스를 반환해주는 역할을 한다. 사용자 관리 프로젝트와 같이 간단한 프로젝트를 위해서도 상당히 많은 명령어와 Action클래스가 필요하다는 것을 눈여겨 보기 바란다. 만약 새로운 요구사항이 발생한다면 위 클래스에 또 하나의 else if 절이 추가될 것이며, Action클래스를 구현하는 새로운 클래스가 추가되어야 할 것이다. package net.javajigi.model2.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.javajigi.model2.*; public interface Action { public ActionForward execute( HttpServletRequest request, HttpServletResponse response) throws Exception; } [예제 1-9]는 모든 Action클래스들이 상속하여 구현해야할 execute() 메소드만을 포함하고 있는 Action 인터페이스이다. package net.javajigi.model2; /** * 모델과의 작업 완료후 이동하게 될 페이지 정보와 * 포워드, 리다이렉트 중 어떤 이동방식을 사용할지에 * 대한 정보를 담고 있다. */ public class ActionForward { private boolean isRedirect = false; private String path = null; public boolean isRedirect() { return isRedirect; } public String getPath() { return path; } public void setRedirect(boolean b) { isRedirect = b; } public void setPath(String string) { path = string; } } [예제 1-10]의 ActionForward클래스는 모델 2의 컨트롤러에서 마지막으로 살펴볼 클래스이다. ActionForward는 각각의 Action클래스들이 모델과의 작업을 완료한 다음 이동할 페이지 정보와 페이지 이동시 사용할 이동 방법(포워드, 리다이렉트)에 대한 정보를 담고 있다. 이상으로 모델 2를 가능케 하기 위하여 기본이 되는 클래스와 설정(web.xml)에 대하여 살펴보았다. 다음은 모델 1에서 살펴보았던 사용자 리스트와 로그인 요청이 모델2에서 어떻게 처리되는지 살펴보도록 하겠다. package net.javajigi.model2.action; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.javajigi.model2.*; import net.javajigi.user.UserManager; public class ListAction implements Action { /** * UserManager의 list메써드를 호출하여 * List를 response에 저장하는 소스코드가 들어간다. * list.jsp에서 response에 저장된 List객체를 이용한다. */ public ActionForward execute( HttpServletRequest request, HttpServletResponse response) throws Exception { String currentPageStr = request.getParameter("currentPage"); int currentPage = 1; if ( (currentPageStr != null) && (!currentPageStr.equals("")) ) { currentPage = Integer.parseInt(currentPageStr); } int countPerPage = 10; UserManager manager = UserManager.instance(); List userList = manager.findUserList(currentPage, countPerPage); //userList객체를 response에 저장하여 전달. request.setAttribute("userList", userList); //이동할 페이지를 결정. ActionForward forward = new ActionForward(); forward.setPath("user_list.jsp"); return forward; } } [예제 1-11]은 사용자 리스트 요청이 있을 때 실행되는 ListAction클래스이다. execute() 메소드 내부를 보면 [예제 1-4]의 user_list.jsp의 앞 부분이 ListAction클래스으로 이동해 온 것을 볼 수 있다. 모델 2의 의도가 JSP가 처리하던 여러가지 작업을 분담하는 것이 목적이였기 때문에 같은 내용이 ListAction클래스를 이용하여 분담하고 있다는 것을 느낄 수 있다. 그렇다면 user_list.jsp는 어떻게 바뀌였을까? [예제 1-12]을 보면 모델2에서 user_list.jsp가 바뀐 모습을 볼 수 있다. <%@page contentType="text/html; charset=euc-kr" %> <%@page import="java.util.*" %> <%@page import="net.javajigi.user.*" %> <%@ include file="loginCheck.jsp" %> <% List userList = (List)request.getAttribute("userList"); %> 이하 [예제 1-4]의 user_list.jsp와 동일 [예제 1-12]는 모델 2로 개발했을 때의 user_list.jsp를 보여주고 있다. [예제 1-4]에서 인자처리와 모델과의 통신 작업이 없어졌음을 확인할 수 있다. 모델2에서는 ListAction에서 전달된 사용자 리스트 객체를 받아서 클라이언트에게 보여주기만 하면 된다. 정말 위 예제가 구현되는지 확인하기 위하여 테스트를 해보기 바란다. 테스트가 가능하도록 하기 위하여 모델 2를 위한 빌드작업을 한다. 모델 2를 위한 타겟은 model2이다. 빌드 후 http://localhost:8080/chapter1/model2/user_list.m2?command=list 를 실행하여 모델 1과 같은 사용자 리스트 화면을 볼 수 있는지 확인하기 바란다. 여기서 눈여겨 볼 것은 요청하는 URL의 확장자가 m2라는 것을 명심하기 바란다. 모델 2에서는 user_list.jsp를 직접 요청하지 않는다. 초기 진입점을 UserSerlvet으로 가져가기 위하여 확장자는 m2가 된다. 지금까지 모델 2로 개발한 사용자 리스트화면을 서비스하기 위한 과정을 시퀀스 다이어그램으로 살펴보면 다음과 같다. ![]() [그림 1-14]의 시퀀스 다이어그램을 보면 user_list.m2로 들어온 요청의 진입점은 UserServlet인 것을 확인할 수 있다. UserCommandFactory에서 사용자 리스트처리를 담당하는 ListAction을 생성한 다음 ListAction클래스가 모델 파트의 UserManager에서 사용자 리스트 정보를 얻은 다음 최종적으로 user_list.jsp에 전달하는 과정을 따르고 있다. 이 처럼 모델 2 방식은 JSP가 직접 모델 파트와 통신하는 것이 아니라 Action클래스가 모델 파트와 통신하여 원하는 결과를 얻은 다음 뷰파트인 JSP에 결과를 전달하는 과정을 거친다. UserManager가 UserDAO를 이용하여 사용자 리스트 정보를 얻는 과정은 [그림 1-11]과 같기 때문에 지면 관계상 생략하였다. 참고 사항 모델 2에서 확장자를 m2로 사용하고 있다. 그러나 꼭 m2 라는 확장자를 사용하는 이유는 web.xml에서 *.m2를 UserSerlvet으로 매핑했기 때문이다. 만약 확장자 m2가 아닌 다른 확장자를 사용하고 싶다면 web.xml의 매핑 정보를 바꿔주면 된다. 다음 절에서 스트럿츠에 대하여 살펴보겠지만 스트럿츠는 보통 *.do를 확장자로 사용한다. 다음으로 살펴볼 예제는 [예제 1-5]의 login_action.jsp가 어떻게 바뀌였는지 살펴보도록 하겠다. 로그인과정에서는 사용자 아이디와 비밀번호를 입력받은 페이지는 login.jsp이다. login_action.jsp는 login.jsp에서 전달된 사용자 아이디와 비밀번호를 전달받아 로그인 과정을 처리하는 작업을 담당했었다. 이 login_action.jsp의 모든 작업을 모델 2에서는 LoginAction클래스가 담당하게 된다. 예제 소스를 보면 알겠지만 내부에서 수행하는 작업 또한 같다는 것을 알 수 있다. package net.javajigi.model2.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import net.javajigi.model2.*; import net.javajigi.user.UserManager; public class LoginAction implements Action { public ActionForward execute( HttpServletRequest request, HttpServletResponse response) throws Exception { String userId = request.getParameter("userId"); String password = request.getParameter("password"); //모델에 로그인 처리를 위임. UserManager manager = UserManager.instance(); manager.login(userId, password); //세션에 사용자 이이디 저장. HttpSession session = request.getSession(); session.setAttribute("userId", userId); //이동할 페이지를 결정. ActionForward forward = new ActionForward(); forward.setPath("user_list.m2"); forward.setRedirect(true); return forward; } } login.jsp페이지는 LoginAction클래스를 이용하여 로그인 과정을 처리하게 된다. [예제 1-13]의 내용을 보면 login_action.jsp에서 처리했던 모든 부분이 LoginAction클래스에서 담당하고 있음을 확인할 수 있다. <%@page contentType="text/html; charset=euc-kr" %> <html> <head> <title>Chapter1 사용자 관리</title> <meta http-equiv="Content-Type" content="text/html; charset=euc-kr"> <link rel=stylesheet href="../css/user.css" type="text/css"> <script language="JavaScript"> function userCreate() { f.action = "user_write.jsp"; f.submit(); } function login() { f.command.value = "login"; f.action = "login.m2"; f.submit(); } </script> </head> <body bgcolor=#FFFFFF text=#000000 leftmargin=0 topmargin=0 marginwidth=0 marginheight=0> <br> <table width=780 border=0 cellpadding=0 cellspacing=0> <tr> <td width="20"></td> <td> <!--contents--> <table width=590 border=0 cellpadding=0 cellspacing=0> <tr> <td bgcolor="f4f4f4" height="22"> <b>사용자 관리 - 로그인</b></td> </tr> </table> <br> <!-- write Form --> <form name="f" method="post"> <input type="hidden" name="command"/> <table border="0" cellpadding="0" cellspacing="1" width="590" bgcolor="BBBBBB"> <tr> <td width=100 align=center bgcolor="E6ECDE" height="22">사용자 아이디</td> <td width=490 bgcolor="ffffff" style="padding-left:10"> <input type="text" style="width:150" name="userId"> </td> </tr> <tr> <td width=100 align=center bgcolor="E6ECDE" height="22">비밀번호</td> <td width=490 bgcolor="ffffff" style="padding-left:10"> <input type="password" style="width:150" name="password"> </td> </tr> </table> </form> <br> <table width=590 border=0 cellpadding=0 cellspacing=0> <tr> <td align=center> <input type="button" value="로그인" onClick="login()"> <input type="button" value="회원가입" onClick="userCreate()"> </td> </tr> </table> </td> </tr> </table> </body> </html> [예제 1-14]는 LoginAction클래스를 이용하여 login.jsp파일이다. LoginAction클래스를 이용하기 위하여 command 인자에 login을 사용하고 있으며, 요청 URL은 login.m2를 사용하고 있음을 확인할 수 있다. 지금까지 모델 2로 사용자 관리 프로젝트를 구현하는 방법에 대하여 살펴보았다. 모델 1에서 모델 2로 바뀌면서 상당히 많은 부분이 생소하게 느끼는 개발자들이 많을 것이다. 모델 2를 처음 접하는 개발자들은 이해하기 더 어려울 것으로 생각된다. 하지만 이 절의 모든 내용을 꼭 이해하고 다음 절을 계속해서 읽기 바란다. 이 절의 이해없이 다음 절의 스트럿츠를 이해하는 것은 더 어렵다. 이 절의 예제를 보면 모델 2로 개발하기 위해서는 추가적으로 개발해야 하는 클래스들이 너무 많다는 것을 느꼈을 것이다. 예제를 보아서 알겠지만 모델 2를 실제 개발에 직접 적용하기에는 어딘가 부족한 부분이 많다는 것을 느꼈을 것이다. 따라서 다음은 모델 2의 한계점을 살펴보고 모델 2를 근간으로 하는 다양한 프레임워크가 등장하게 된 배경에 대하여 살펴보도록 하겠다. 4.3 모델 2 개발 방식의 장,단점. 모델 1의 한계를 느낌 많은 개발자들이 웹 애플리케이션에서도 모델, 뷰, 컨트롤러에 기반한 모델 2로 개발하자는 의견이 많이 대두되고 있다. 지금까지 모델 2의 예제를 보면 모델 1에서 JSP가 처리해야 했던 많은 부분들을 분리하여 개발하는 가능하도록 하였다. 그렇게 됨으로서 JSP는 단지 뷰를 위한 로직에만 집중하면 되기 때문에 유지보수에 투입되는 시간을 단축할 수 있는 효과를 가져올 수 있다. 또한 모델에 변경이 있을 경우 모델 1에서는 JSP의 직접적인 수정이 필요하지만, 모델 2의 경우에는 모델과 뷰 사이에서 중개자 역할을 하는 컨트롤러의 수정만으로도 가능하게 되었다. 따라서 뷰에 대한 수정 사항이 발생할 경우에는 코더나 디자이너가 그러나 앞의 예제를 보면 알겠지만 모델 2로 개발할 경우 무수히 많은 Action클래스를 개발해야 하며, 그외 컨트롤러를 담당하는 여러 개의 클래스를 추가 개발해야한다. 또한 새로운 Action클래스가 추가되면 소스수정, 컴파일등의 작업을 계속해서 진행해야 한다. 이러한 작업은 개발 기간의 연장을 가져오고, 결과적으로 초기 개발 비용이 모델 1보다 상당히 많이 발생하게 된다. 따라서 모델 2의 개발 기간을 단축시키기 위하여 모델 2의 근간이 되는 컨트롤러 부분이 재사용성이 가능하도록 구현할 필요성을 느끼게 되었다. 위 예에서 UserServlet의 경우 UserCommandFactory에 종속적이기 때문에 사용자 관리 프로젝트 이외에 다른 프로젝트에 재사용하기 힘들다. 만약 재사용한다고 해도 프로젝트가 커지면 커질수록 UserCommandFactory에는 무수히 많은 if/else절을 포함하게 될 것이다. 모델 2의 이 같은 한계점을 느끼고 재사용 가능한 부분들을 찾아 모델 2 로 진행하고자 하는 프로젝트에서 사용가능하도록 프레임워크화하고자 하는 시도가 진행되게 되었다. 현재 이 같은 시도로 많들어진 무수히 많은 프레임워크가 존재하고 있다. 그 중의 하나가 스트럿츠 프레임워크인 것이다. 따라서 스트럿츠 프레임워크의 기본적인 구조는 모델 2를 기반으로 하고 있는 것이다. 다음 절에서 살펴볼 스트럿츠 프레임워크의 전체적인 구조를 보면 많은 부분이 모델 2에서 필요로 했던 부분들을 재사용 가능하도록 구현하고 있다는 것을 느낄 수 있을 것이다. 강좌에 대하여작성자 : 박재성 문서이력 :
참고 자료
|
|




Add Comment