본문 바로가기
스프링/스프링

[Spring] Model 1, Model 2를 예제로 구현하며 알아보자

by 책 읽는 개발자_테드 2021. 2. 24.
반응형

Model 1  구현하기

 JSP 파일에서 Controller 기능과 View 기능을 모두 처리하는 Model1 구조를 구현해보자. 구현할 내용은 사용자의 이름, 전화번호, 나이를 출력하는 페이지다.

 

자바 웹프로젝트를 생성하고, hello.jsp 파일을 src/main/webapp 폴더에 등록한다.

 

그리고 HTML 태그를 이용하여 화면을 구성한다.

 

hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>

 

hello.jsp 파일을 선택하고, 마우스 오른쪽으로 클릭하여 Run As - Run on Server를 통해 실행한다.

 

그러면 다음과 같은 페이지가 실행된다.

 

지금은 경로가 http://localhost:8080/scshim/hello.jsp로 되어있다. 경로를 http://localhost:8080/hello.jsp 로 변경해보자.

 

[Servers] 뷰에서 사용 중인 서버를 더블 클릭한다. 

 

 

그러면 이동하는 [Modules] 탭에서 <Edit> 버튼을 클릭하면 path 정보를 수정할 수 있다.

 

path 정보 수정 후 서버를 재시동하면, 다음과 같이 경로가 변경된다.



이번에는 사용자 정보를 담는 Users 클래스를 생성하자. Java Resources - src/main/java 디렉토리에 users 패키지를 생성하고, 그 안에 Users.java 파일을 생성한다.

 

 

그리고 다음과 같이 작성한다.

package users;

public class Users {

private String name;
private String phone;
private int age;

public Users(String name, String phone, int age){

this.name = name;
this.phone = phone;
this.age = age;
}

public String getName() {
return name;
}

public String getPhone() {
return phone;
}

public int getAge() {
return age;
}
}

 

이번에는 hello.jsp에 Users 클래스 정보를 가져와서 사용자 정보를 생성하고, 화면에 출력하는 코드를 추가하자.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@page import = "users.Users" %> <!--Users 클래스 가져오기 -->

<% 
//사용자 정보 생성
Users user = new Users("홍길동","010-0000-0000",28);
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
<p><%= user.getName() %></p>
<p><%= user.getPhone() %></p>
<p><%= user.getAge() %></p>
</body>
</html>
 

그리고 다시 localhost:8080/hello.jsp에 접속하면, 화면이 수정된 걸 확인할 수 있다.

 

 

Model 2 구현하기

 

 

JSP에서 Controller 로직을 서블릿을 통해 분리한 Model 2를 구현해보자. 여기서는 Model2 아키텍처 구조를 이해하기 위해 아키텍처 구조가 추상화되어있는 스프링을 사용하지 않는다.

 

Servlet을 생성한다. src/main/java 소스 폴더에 마우스 오른쪽 버튼을 클릭하고 [New] -> [Other] -> [Servlet]을 선택합니다. 

 

서블릿의 생성 위치(패키지) 이름을 Java package에 입력하고, Class name에 ‘DispatcherServlet’을 입력한 후 Next를 클릭한다.

 

Name에 ‘action’은 입력하고, URL mappings에 /action을 클릭하여 패턴을 ‘*.do’로 변경한 후 ‘OK’ 버튼을 클릭한다. 마지막으로 ‘Finish’ 버튼을 클릭하여 DispatcherServlet 클래스를 생성하자.

 



DispatcherServlet 클래스가 만들어지면 WEB-INF/web.xml 파일에 서블릿 관련 설정이 자동으로 추가된다.

 

 

여기서 <description>,<display-name>은 의미 없는 설정이므로, 지운다.

 

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 
 https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
 version="2.5">

  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>com.tistory.scshim.DispatcherServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>web.xml

 

위 설정은 클라이언트의 모든 *.do 요청을 DispatcherServlet 클래스의 객체가 처리한다는 설정이다. ‘.do’는 다른 이름으로 변경할 수 있다.

 

다음으로 DispatcherServlet 클래스가 Controller 기능을 수행하도록 구현한다.

 

DispatcherServlet.java

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class DispatcherServlet
 */
public class DispatcherServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */

    public DispatcherServlet() {
        super();
        // TODO Auto-generated constructor stub
    }
    
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	process(request, response);
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	request.setCharacterEncoding("EUC-KR");
	process(request, response);
}

private void process(HttpServletRequest request, HttpServletResponse response) throws IOException{

	// 1. 클라이언트의 요청 path 정보를 추출
	String uri = request.getRequestURI();
	System.out.println(uri);
	String path = uri.substring(uri.lastIndexOf("/"));
	System.out.println(path);

	// 2. 클라이언트의 요청 path에 따라 분기처리 
	if(path.equals("/hello.do")) {
		System.out.println("Hello Worldl!");
	}else if(path.equals("/hello2.do")) {
		System.out.println("Hello Hello Worldl!");
	}
}

}

 

✏️DispatcherServlet에는 GET 방식 요청을 처리하는 doGet() 메소드, Post 방식 요청을 처리하는 doPost() 메소드가 재정의되어 있다. 해당 메소드들을 수정하여 모든 요청에 process() 메소드를 통해 클라이언트의 요청을 처리하도록 한다.

 

doPost() 메소드에는 한글이 깨지지 않도록 인코딩 처리를 추가한다. 이렇게 인코딩 작업을 DispatcherServlet 클래스에서 일괄처리하면, 인코딩을 변경할 때 DispatcherServlet 클래스만 수정하면 된다.

 

process() 메소드는 클라이언트의 요청 URI로부터 path정보(URI 문자열에서 마지막 xxx.do 문자열)를 추출한다. 그리고 추출된 path 문자열에 따라서 복잡한 분기 처리 로직이 실행된다.

 

이제 서버를 재구동한 후, 브라우저에 다음 URL을 차례로 요청하자.

 

http://localhost:8080/hello.do

http://localhost:8080/hello2.do

 

콘솔에 다음과 같은 분기 처리 결과가 출력된다.

 

 

이제 기존에 작성한 JSP 파일에 분기 처리 로직을 추출하여 DispatcherServlet에 추가하고, 기능을 하나씩 구현하자.

 

hello.jsp 파일에서 Contoller 로직에 해당하는 자바 코드(사용자 정보 생성)를 DispatcherServlet로 복사한다.

~생략~

// 2. 클라이언트의 요청 path에 따라 분기처리 
if(path.equals("/hello.do")) {
	//사용자 정보 생성
	Users user = new Users("홍길동","010-0000-0000",28);

	//사용자 정보를 세션에 저장하고, hello.jsp 화면으로 이동한다. 
	HttpSession session = request.getSession();
	session.setAttribute("user",user);
	response.sendRedirect("hello.jsp");
}else if(path.equals("/hello2.do")) {
	System.out.println("Hello Hello Worldl!");
}

~생략~

 

✏️ 위 코드는 리다이렉트되는 getBoardList.jsp 화면에서 검색 결과를 출력하기 위해 세션(HttpSession) 객체를 사용한다. 

 

이렇게 검색 결과를 JSP에 공유하기 위해 세션에 저장하는 것은 문제가 있다. 세션은 브라우저당 서버 메모리에 하나씩 유지되는 객체이므로 사용자가 많을 수록 많은 세션이 생성되어, 서버에 부담이 된다.

 

따라서 검색 결과를 세션이 아닌 HttpServletRequest 객체에 저장하여 공유해야 한다. HttpServletRequest 객체는 클라이언트가 서버에 요청을 전송할 때마다 새롭게 생성되며, 응답 메시지가 브라우저에 전송되면 바로 삭제되는 1회성 객체다.

 

현재는 코드 간결함을 위해 세션을 이용하며, 이후 실제로 Spring MVC 등의 프레임워크를 사용할 때는 HttpSession 대신 HttpServletRequest를 사용한다.

 

기존에 생성한 hello.jsp를 다음과 같이 수정하고, http:localhost:8080/hello.do에 접속해보자

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@page import = "users.Users" %> <!--Users 클래스 가져오기 -->

<% 
//세션에서 사용자 정보 꺼내기 
Users user = (Users) session.getAttribute("user");
%>

<!DOCTYPE html>

<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>

<body>
<h1>Hello World!</h1>
<p><%= user.getName() %></p>
<p><%= user.getPhone() %></p>
<p><%= user.getAge() %></p>
</body>
</html>

 

hello.jsp로 리다이렉트되며, 기존과 같은 결과가 출력되는 걸 확인할 수 있다.

그리고 hello.do가 아니라 hello.jsp에 직접 요청하면 다음과 같이 세션에 저장된 사용자 정보가 없어 오류가 발생한다.

 

 

다음 글에서는 조금 더 Spring 프레임워크에 가까운 아키텍로 같은 내용을 구현해보자

scshim.tistory.com/278

 

출처

스프링 퀵 스타트

반응형

댓글