카테고리 없음

MVC Model이란 ? (servlet사용해보기)

오늘의 진 2022. 10. 28. 15:12

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 단점

  1. JSP에 java코드와 html 코드가 섞여있어서 가독성에 문제가 있다. 
  2. 1번과 같은 이유로 프론트와 백앤드간의 분업이 모호하다
  3. 유지보수에 어려움이 있다. 

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>