MVC Model이란 ? (servlet사용해보기)
MVC Model
JSP 장점중 하나는 비즈니스 로직과 표현을 분리 할 수 있다는 점이다.
웹 응용 프로그램 개발에서 비즈니스 로직과 표현의 분리는 다음과 같은 이점이 있다.
- 디자이너는 표현에 집중하여 개발하고 프로그래머는 비즈니스 로직에 전념하여 개발하므로 효율성이 높아진다.
- 웹 응용 프로그램의 수정이 쉽다.
- 웹 응용 프로그램의 확장이 쉽다.
- 웹 응용 프로그램의 유지 보수가 쉽다.
>> MVC는 Model, View, Controller의 약자이다.
MVC 요소 | 구현프로그램 | 역할 |
Model | 자바빈즈 | 자료의 비즈니스 로직 처리 |
View | JSP, HTML | 표현(Presentation) 부분 처리 |
Controller | Servlet, JSP | 적절한 Model을 처리하여 뷰로 제어 이동 |
MVC 모델은 웹 응용 프로그램을 구성하는 서버 모듈을 사용자에게 보이는 부분을 View로 자료와 비즈니스 로직 처리를 Model로 그리고 이들간의 흐름을 제어하는 Controller로 분리하여 개발하는 모델이다.
SerVlet과 JSP
기본적으로 웹 서비스를 위해서 http protocol을 통해 클라이언트는 서버에게 데이터를 요청한다.
이때 동적으로 클라이언트에게 화면을 뿌려주는 역할을 하는 것이 servlet과 JSP 이다.
Java EE (Enterprise Edition) 기능의 일종으로, 다이나믹 웹 프로젝트를 이용한다.
servlet은 화면에 뿌려주는 역할인 만큼 java에 html코드를 작성 할 수 있게 고안되었다.
하지만 자바코드의 html 태그들을 삽입한다는 점에서 코딩을하는데 불편함을 격었다.
그렇게 불편함을 최소화 하기 위해서 반대로 html 안에 java 코드가 들어가게 만든것이 jsp 이다.
jsp(java Server Page) 는 디자인에 초점을 맞추어 html 태그 및 스크립트 작성에 용이하지만,
이름에 들어간 것과 같이 서버의 역할도 한다. 즉 servlet을 작성하지 않고 간편하게 웹 프로그래밍을 구현하기 위해서 등장하였다. 얼핏봐서는 servlet과 jsp과 동일해 보이지만 , 다음과 같은 차이가 있다.
Servlet | HTML을 자바코드로 구현하며 문자열 스트림(" ")을 통해 처리한다. 배포시 컴파일을 하며, 코드가 수정된다면 또 다시 컴파일을 해야한다. |
JSP | 자바 코드를 <% %>를 이용해서 태그처럼 사용할 수 있다. 즉, JSP를 이용하면 Servlet에 비해서 자바 코딩 없이 태그만으로 간략히 기술이 가능하므로 생산성을 높일 수 있다. 따라서 Servlet을 사용하지 않고 JSP만을 사용해서 동적 웹 서비스를 하는 model 1이 탄생했다. |
model 1 단점
- JSP에 java코드와 html 코드가 섞여있어서 가독성에 문제가 있다.
- 1번과 같은 이유로 프론트와 백앤드간의 분업이 모호하다
- 유지보수에 어려움이 있다.
model 2 (MVC Architecture)
: model 1 에 대한 단점을 극복하기 위해서 MVC(Model view Controller) design pattern 에 등장했다.
이 디자인 패턴은 이름과 동일하게 모델, 뷰, 컨트롤러 3가지로 나뉘어서 구성된다.
View | 클라이언트의 요청을 받으며, 응답을 해주고 화면을 구성해준다. |
Controller | View로 부터 요청을 전달 받으며, Model로 부터 넘어온 데이터를 view측에 전달한다. |
Model | DTO(Data Transfer Object) : 데이터 담는 객체를 정의한다. |
*Service : 클라이언트가 요청하는 서비스에 대해 처리한다. (ex - 트랜잭션)
*DAO(Data Access Object) : 데이터베이스와 연결되는 곳이다.
*DTO는 Bean이나 VO(Value Object)로 쓰이기도 하지만 여기서는 DTO로 표현한다.
MVC 패턴은 다음과 같은 장단점이 있다.
장점
- 화면과 비즈니스 로직을 분리해서 분업에 용이하다.
- 영역별 개발로 인해 확장성이 뛰어나다.
- 표준화된 코드를 이용하기때문에 협업에 유리하다.
- 유지보수에 용이하다.
단점
- 구조가 복잡하기 때문에 초기 개발속도가 느리다.
- 초보자가 이해하고 개발하기 다소 어렵다.
package test_1;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/HelloTest")
public class HelloServlet_1 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
// HTML을 생성할 수 있는 printWriter 객체를 저장
PrintWriter out = response.getWriter();
out.println("<h2>Hello Servlet JIn !!! </h2>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
주소창에 다음과 같이 HelloTest를 입력해주면 글이 나타남
(어노테이션으로 접근하는 방법)
package test_1;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/korea")
public class HelloServlet_2 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
// HTML을 생성할 수 있는 printWriter 객체를 저장
PrintWriter out = response.getWriter();
out.println("<h2>Hello Servlet 금요일 ~~~ !!! </h2>");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
service(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
service(request, response);
}
}
@WebServlet()
어노테이션은 자바 주석문처럼 소스안에 @ 기호와 함께 사용된다.
자바 실행문은 아니고 주석문처럼 컴파일러에 정보를 알려주는 기능,
또는 자바 프로그램 실행에 관한 내용을 설정하는 용도로 사용된다.
작성한 Hellow Servlet.java 소스는 /WEB-INF/Classes 디렉토리에 컴파일되었다.
WEB-INF 디렉토리에 있는 web.xml 파일은 웹 어플리케이션에 관한 환경설정 파일로서 웹 서버가 시작할때
web.xml 파일에 설정된 내용대로 서비스를 올려준다.
/WEB-INF/Classes나 /WEB_INF/lib 디렉토리에 있는 파일들도 애플리케이션 서버가 사용한다.
이처럼 /WEB-INF/는 웹 서버가 사용하는 파일이 들어있는 중요한 디렉토리 이다.
따라서 외부에서 클라이언트가 곧바로 접근할 수 었도록 막아 놓았다.
클라이언트가 서블릿에 접근할 수 있게 하려먼 서버쪽에서 설정을 해주어야 한다.
web.xml과 annotation을 이용하여 서블릿 접근 경로를 지정 할 수 있다.
[servlet]을 사용하여 로그인 해보기
다음과 같은 구조로 작성하였다.
이때 view 부분이 login.jsp coltroller 부분이 UserController.java(servlet) , model부분이 UserBean.java이다
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>mvc_login</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file> <!-- 1 --> <!-- 우선 서버를 실행시키면 시작되는공간 :welcom file index.html로 가야하네? 갑니다 -->
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.jsp</welcome-file>
<welcome-file>default.htm</welcome-file>
</welcome-file-list>
<servlet> <!-- 5 서블릿을 찾으러 옴 -->
<description>MVC Login</description>
<display-name>login process</display-name>
<servlet-name>login process</servlet-name> <!-- 6 서블릿 네임이 loginprocess인것을 찾음 -->
<servlet-class>kr.app.servlet.UserController</servlet-class> <!-- 7 이름이 loginprocess인 것의 class 경로를 찾음 이 경로로 이동 -->
</servlet>
<servlet-mapping>
<servlet-name>login process</servlet-name> <!-- 4 --> <!-- servlet name이 login process로 이동해야한다. -->
<url-pattern>/Login.do</url-pattern> <!-- 3 -->
</servlet-mapping>
</web-app>
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 폼</title>
</head>
<body>
<h2>로그인 예제</h2>
<hr>
<!-- 2 -->
<form action="Login.do" method="post" name="form1">
<table border="1">
<tr background="mistyrose">
<td colspan="2" height="22" align="center"><b> <font size="3">로그인</font>
</b></td>
</tr>
<tr bgcolor="lightcyan">
<td>아이디</td>
<td><input type="text" name="userid" size="10"></td>
</tr>
<tr bgcolor="lightcyan">
<td>암호</td>
<td><input type="password" name="passwd" size="10"></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" name="submit" value="로그인">
<input type="reset" name="reset" value="취소"></td>
</tr>
</table>
</form>
</body>
</html>
UserController.java
package kr.app.servlet;
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;
import kr.app.model.UserBean;
//컨트롤러 역할
public class UserController extends HttpServlet {
private static final long serialVersionUID = 1L;
//8 xml 파일에서 받아온 경로로 이동해옴
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 이때 index.html에서 입력한 값을 파라미터로 전달
String userid = request.getParameter("userid");
String passwd = request.getParameter("passwd");
//userbean : 모델 부분 담당
//모델부분을 호출
//내가 입력한 아이디를 인스턴스에 전달 하고 입력한 아이디 비번이 UserBean에 저장한 것과 같은지 getChackUser()을통해 확인
UserBean user = new UserBean(); // 빈속에 아이디랑 패스워드 담음
user.setUserid(userid);
user.setPasswd(passwd);
//아이디 비번이 맞는지를 getCheckUser()을 통해 확인하고 그결과를 request.setAttribute를 통해 속성으로 저장함
request.setAttribute("resultlogin", user.getCheckUser());
//로그인한 이름에다가 getChaeckuer()을 실행한 값을 넣어라 (아이디 비번이 같은지 확인해줌 t/f)
/*
* request로 넘어온 값들을 아래에서 RequestDispatcher를 통해 login.jsp로 모두 넘겨줄 것이다.
* 이때 로그인이 되었는지 안되었는지의 여부도 함께 넘겨주려고
* request.setAttribute()를 통해 resultlogin이라는 속성에 결과를 담아서 request에 담아서 함께 전달한다.
*
* */
// 처리결과가 저장된 request를 전송하며 동시에 뷰인 login.jsp로 제어 이동
//처리한 결과를 가지고 login.jsp로 이동
/*
* requestDispatcher란?
* 서블릿 또는 JSP에서 요청을 받은 후 다른 컴포넌트로 요청을 동일하게 위임 할 수 있다.
* 요청받은 요청 객체(request)를 위임하려는 컴포넌트에게 동일하게 전달 할 수 있다.
* 웹 브라우저에서 전달하는 사용자가 전달한 정보를 requset.getParameter()로 받을수 있었는데
* 이것을 다른 컴포넌트로 전달하면 그 컴포넌트에서 똑같이 속성을 받을 수 있다
*
* (예 : A.jsp에 담겨있는 param이라는 이름으 파라미터를 B.jsp에서도 C.jsp에서도 받아볼수있다.)
*
*
* request & response의 단계에서 forward, sendRedirect 방식이 있다.
*
* 1.forward
* A.jsp > Servlet > B.jsp 로 넘어감에 따라 A의 파라미터를 B로 넘겨준다.
*
* 2.sendRedirect
* 모든 파라미터 정보를 제외하고 단순 페이지 호출을 한다(페이지로 이동)
*
* 만약 RequestDispacher없이 forward만 하면 A.jsp > Servelet > B.jsp까지는
* 정보가 넘어가지만 그다음 단계에서는 A.jsp의 정보를 별도로 저장하지 않는다면 소실된다.
*
*
* servlet에서 servlet 또는 jsp로 rsquest를 넘길때 requestDispatcher을 이용한다.
* */
//정보를 전달할 객체 RequestDispatcher을 만들고 옮길 주소 login.jsp를 적음
RequestDispatcher view = request.getRequestDispatcher("login.jsp");
// view.forward를 통해 이동시킴
view.forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
UserBean.java
package kr.app.model;
public class UserBean {
private String userid;
private String passwd;
private String dbUserid;
private String dbPasswd;
// 생성자
public UserBean() {
// 인증에 사용할 기본값 설정
// 현재 저장하는 사용자와 암호인 경우 로그인 성공
dbUserid = "mvc";
dbPasswd = "model";
}
// 아이디와 비밀번호가 맞는지 체크하는 메소드
public boolean getCheckUser() {
if (userid.equals(dbUserid) && passwd.equals(dbPasswd))
return true;
else
return false;
}
// getter , setter
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
}
login.jsp
<%@ 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>
<!-- 9. UserController를 통해서 전달한 request가 전달되어옴 -->
<%
//전달 받은 request에서 정보를 뽑아옴
Boolean res = (Boolean) request.getAttribute("resultlogin");// 로그인 성공 여부
String userid = request.getParameter("userid"); // 유저가 입력한 id
if (res.booleanValue()) {
out.println("사용자 " + userid + "님, 로그인 하였습니다. 반갑습니다.");
} else {
out.println("사용자 " + userid + "님, 암호가 다릅니다.");
}
%>
<hr size="5" color="red">
<!-- 위와 같은 내용을 jsp를 이용하여 출력해보는 코드 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="result" value="${requestScope.resultlogin }" />
<!--requestScope : request와 동일한 역할을 한다. -->
<!-- var result = 전달받은 resultlogin 으로 주겠다는 말 -->
<c:choose>
<c:when test="${result }">
<!-- 위에서 설정한 result가 true이면 -->
사용자 ${param.userid }님, 로그인 하셨습니다. 반갑습니다.
</c:when>
<c:otherwise>
<!-- resutl가 false이면 -->
사용자 ${param.userid }님 암호가 다릅니다.
<jsp:include page="index.html" />
<!-- 거짓일때는 id 입력창을 다시 띄운다. -->
</c:otherwise>
</c:choose>
</body>
</html>