본문 바로가기
👨‍💻 2. 웹개발_Back end/2-6 Spring

[Spring] 3장 Model 2 아키텍처로 게시판 개발 (로그인과 로그아웃, 글 등록, 수정, 삭제 기능) - Controller 로직 코드를 DispatcherServlet로 복사하여 Controller 분리

by 달님🌙 2021. 10. 29.
반응형

 

실습 코드 참조

 

moonhy7/SpringFramework: Spring Framework 실습 코드 정리 (github.com)

 

GitHub - moonhy7/SpringFramework: Spring Framework 실습 코드 정리

Spring Framework 실습 코드 정리. Contribute to moonhy7/SpringFramework development by creating an account on GitHub.

github.com

 

 

3.1절 Model 2 아키텍처 구조

 

1. Model 2 아키텍처 구조

 

 

2. Model 2 아키텍처 구조 특징

 

- Model 1 아키텍처의 단점 : 자바 로직과 화면 디자인이 통합되어 엔터프라이즈 시스템에서 사용하기에는 유지보수가 어렵다.

- Model 2 아키텍처에서는 기존에 JSP가 담당했던 Controller 로직이 별도의 Controller 기능의 서블릿으로 옮겨졌다.

- 결과적으로 자바 개발자는 Controller와 Model만 관리하면 되고 Controller 로직이 사라진 JSP에는 View만 남기 때문에 디자이너는 JSP 파일만 관리하면 된다.

 

3. MVC 아키텍처 각 요소별 기능 및 개발 주체

 

- MVC 아키텍처에서 가장 중요한 Controller 기능은 MVC 프레임워크가 제공하는 Controller를 사용하는 것이 더 효율적이고 안정적임

- 하지만 프레임워크가 제공하는 Controller 구조가 복잡하고 어렵기 때문에 당분간은 Controller 기능 이해를 중점으로 학습

 

3.2절 Controller 구현하기 ( _052_BoardWeb_Model_Two_DispatcherServlet )

 

1. 서블릿 생성 및 등록

 

1) 버전 확인

- web.xml 버전과 org.eclipse.wst.common.project.facet.core.xml 버전이 모두 2.5로 되어있어야함

- web.xml

 

- org.eclipse.wst.common.project.facet.core.xml 

 

- Maven Project를 업데이트하고 STS 재부팅하기

 

2) 서블릿 생성하기

- Controller 기능을 수행하는 서블릿 클래스를 하나 추가하여 기존의 Model 1 기반으로 개발된 게시판 프로그램을 MVC 아키텍처로 변경하는 작업

 

- 클래스 이름을 DispatcherServlet으로 설정하고 Next 클릭

 

 

- Name에 action을 적고 URL mappings에 /action 을 더블 클릭하여 Pattern을 *.do로 설정

 

3) xml 파일

- xml 파일에 자동으로 서블릿 관련 설정이 추가되는 것을 볼 수 있음

- <description>과 <display-name> 설정 제거

- 클라이언트의 모든 *.do 요청을 DispatcherServlet 클래스의 객체가 처리한다는 설정임

<?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.springbook.view.controller.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>

 

 

2. Controller 서블릿 구현

 

1) DispatcherServlet 클래스

- DispatcherServlet에는 GET 방식과 POST 방식 요청을 처리하는 메소드가 재정의되어 있다.

- 한글이 깨지지 않도록 인코딩 처리를 DispatcherServlet 클래스에 일괄적으로 해주므로 인코딩 변경이 용이하다.

- DispatcherServlet의 process() 메소드에서는 가장 먼저 클라이언트의 요청 URI로부터 path 정보를 추출한다.

- 추출된 path는 URI 문자열에서 마지막 /XXX.do 문자열이며, 문자열에 따라서 복잡한 분기 처리 로직이 실행된다.

package com.springbook.view.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.board.impl.BoardDAO;
import com.springbook.biz.user.UserVO;
import com.springbook.biz.user.impl.UserDAO;

/**
 * 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 {
		// TODO Auto-generated method stub
		process(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//클라이언트에서 전송하는 데이터가 한글일 경우 깨짐 방지
		request.setCharacterEncoding("UTF-8");
		process(request, response);
	}
	
	private void process(HttpServletRequest request, HttpServletResponse response) throws IOException {
		//1. 클라이언트 요청  path 정보를 추출한다.
		String uri = request.getRequestURI();
		//  http://localhost:9900/biz/login.do
		String path = uri.substring(uri.lastIndexOf("/"));
		//  /login.do
		System.out.println(path);
		
		//2. 클라이언트 요청 path에 따라 적절히 분기처리한다.
		if(path.equals("/login.do")) {
			System.out.println("로그인 처리");
			}
		} else if(path.equals("/logout.do")) {
			System.out.println("로그아웃 처리");
		} else if(path.equals("/insertBoard.do")) {
			System.out.println("글 등록 처리");
		} else if(path.equals("/updateBoard.do")) {
			System.out.println("글 수정 처리");
		} else if(path.equals("/deleteBoard.do")) {
			System.out.println("글 삭제 처리");
		} else if(path.equals("/getBoard.do")) {
			System.out.println("글 상세 조회 처리");
		} else if(path.equals("/getBoardList.do")) {
			System.out.println("글 목록 검색 처리");
		} 
	}
}

 

2) 실행 결과

- 아래  URI을 차례로 요청해보면 다음과 같은 분기 처리 결과가 출력된다.

port : 9090으로 변경

 

- 이제 기존에 작성된 JSP 파일에서 각 분기 처리 로직을 추출하여 DispatcherServlet에 추가하고 기능을 구현할 것이다

 

 

3.3절 로그인 기능 구현하기

 

1) login.jsp 

- 로그인 기능을 MVC로 변환하기 위해 login.jsp 파일의 action 속성값을 login.do로 수정

- .do 형태의 요청에 대해서만 DispatcherServlet이 동작하기 때문

<form action="login.do" method="post">

 

2) DispatcherServlet 

- login_proc.jsp 파일에 있는 모든 자바 로직을 복사하여 DispatcherServlet에 추가할 것

- import 선언을 위해 Ctrl + Shift + O 단축키 누르기

//2. 클라이언트 요청 path에 따라 적절히 분기처리한다.
		if(path.equals("/login.do")) {
			System.out.println("로그인 처리");
			
			//1. 사용자 입력 정보 추출(login.jsp에서 전송한 id, password 받기)
			String id = request.getParameter("id");
			String password = request.getParameter("password");
			
			//2. DB연동 처리(UserDAO의 메소드 호출)
			UserVO vo = new UserVO();
			vo.setId(id);
			vo.setPassword(password);
			
			UserDAO userDAO = new UserDAO();
			UserVO user = userDAO.getUser(vo);
			
			//3. 화면 네비게이션(로그인 후 화면 이동 처리)
			//로그인 성공 시 게시판 목록 조회 화면으로 이동
			if(user != null) {
				response.sendRedirect("getBoardList.do");
			//로그인 실패 시 다시 로그인 화면으로 이동
			} else {
				response.sendRedirect("login.jsp");
			}
		} else if(path.equals("/logout.do")) {
			System.out.println("로그아웃 처리");

 

3) 실행 화면

 

 

3.4절 글 목록 검색 기능 구현하기

 

1) DispatcherServlet 

- 기존의 getBoardList.jsp 파일에서 Controller 로직에 해당하는 자바 코드를 DispatcherServlet으로 복사하기

	} else if(path.equals("/getBoardList.do")) {
			System.out.println("글 목록 검색 처리");
			
			//1. 사용자 입력정보 추출(검색기능 나중에 구현)
			//2. DB 연동 처리(BoardDAO의 메소드 호출)
			BoardVO vo = new BoardVO();
			BoardDAO boardDAO = new BoardDAO();
			List<BoardVO> boardList = boardDAO.getBoardList(vo);
			
			//3. 검색 결과를 세션에 저장하고 목록 화면으로 이동한다.
			HttpSession session = request.getSession();
			session.setAttribute("boardList", boardList);
			response.sendRedirect("getBoardList.jsp");
		}

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

- 세션은 브라우저당 서버 메모리에 하나씩 유지되는 객체이므로 사용자가 많을 수록, 세션에 정보가 많이 저장될수록 서버 입장에서 부담스러움

- 따라서 검색 결과는 HttpServletRequest 객체에 저장하여 공유해야 한다.

- HttpServletRequest 객체는 클라이언트가 서버에 요청을 전송할 때마다 생성되며 바로 삭제되는 1회성 객체이므로 서버에서는 부담되지 않는다.

- 하지만 코드의 간결함을 유지하기위해 HttpSession을 사용할 예정

 

2) getBoardList.jsp

- 글 목록을 검색하는 자바 코드 대신 세션에 저장된 글 목록을 꺼내서 출력하도록 수정

- getBoardList.jsp 파일에 있었던 자바 코드는 Controller인 DispatcherServlet 클래스로 이동했기 때문에 getBoardList.jsp는 단지 세션에 저장된 글 목록을 꺼내서 출력하는 기능만 제공함

<%
	// 세션에 저장되어 있는 게시글 목록을 꺼낸다.
	List<BoardVO> boardList = (List)session.getAttribute("boardList");
%>
<!DOCTYPE html>
	...

 

3) 실행 화면

- getBoardList.jsp 파일을 직접 요청하거나 login.jsp 파일을 실행하여 로그인하면 아래와 같은 오류 발생

- getBoardList.jsp 파일에서 세션에 저장된 글 목록을 꺼내려면 DispatcherServlet이 먼저 실행되어 검색 결과를 저장해야하므로 반드시 /getBoardList.do로 요청해야 한다.

 

4) 게시글 목록 검색 실행 순서

① DispatcherServlet이 클라이언트의 /getBoardList.do 요청을 받으면

② DispatcherServlet은 BoardDAO 객체를 이용하여 글 목록을 검색한다.

③ 검색된 글 목록을 세션에 등록하고

④ getBoardList.jsp 화면을 요청하면,

⑤ getBoardList.jsp는 세션에 저장된 글 목록을 꺼내어 목록 화면을 구성한다.

⑥ 마지막으로 이 응답 화면이 브라우저에 전송된다.

 

5) 로그인 성공 시 리다이렉트 .do로 변경

	//3. 화면 네비게이션(로그인 후 화면 이동 처리)
			//로그인 성공 시 게시판 목록 조회 화면으로 이동
			if(user != null) {
				response.sendRedirect("getBoardList.do");
			//로그인 실패 시 다시 로그인 화면으로 이동
			} else {
				response.sendRedirect("login.jsp");
			}

 

 

3.5절 글 상세 보기 기능 구현하기

 

1) getBoardList.jsp 

- 글 상세 화면도 MVC 아키텍처로 변환하기위해 게시글 제목에 설정된 하이퍼링크를 수정한다. 

- getBoardList.jsp를 getBoardList.do로 변경하면 된다.

<% for(BoardVO board : boardList) { %>
<tr>
  <td><%= board.getSeq() %></td>
  <td><a href="getBoard.do?seq=<%= board.getSeq() %>"><%=board.getTitle() %></a></td>
  <td><%= board.getWriter() %></td>
  <td><%= board.getRegDate() %></td>
  <td><%= board.getCnt() %></td>
</tr>
<% } %>

 

2) DispatcherServlet 

- 글 목록 검색 기능과 비슷하게 검색 결과를 getBoard.jsp 파일에 공유하기 위해 검색 결과를 세션에 저장하고 getBoard.jsp 파일을 리다이렉트한다. 

	} else if(path.equals("/getBoard.do")) {
			System.out.println("글 상세 조회 처리");
			
			//1. 상세 조회할 게시글 번호 추출
			String seq = request.getParameter("seq");

			//2. DB 연동 처리(BoardDAO의 메소드 호출)
			BoardVO vo = new BoardVO();
			vo.setSeq(Integer.parseInt(seq));
			
			BoardDAO boardDAO = new BoardDAO();
			BoardVO board = boardDAO.getBoard(vo);
			
			//3. 검색 결과를 세션에 저장하고 목록 화면으로 이동한다.
			HttpSession session = request.getSession();
			session.setAttribute("board", board);
			response.sendRedirect("getBoard.jsp");
		} else if(path.equals("/getBoardList.do")) {
			System.out.println("글 목록 검색 처리");
            	...

 

3) getBoard.jsp

- 세션에 저장된 검색 결과를 getBoard.jsp 파일에서 출력한다. 

<%
	// 세션에 저장된 게시글 내용을 꺼낸다.
	BoardVO board = (BoardVO) session.getAttribute("board");
%>

 

 

3.6절 글 등록 기능 구현하기

 

1) insertBoard.jsp

action 속성값을 insertBoard.do 로 수정한다.

<form action="insertBoard.do" method="post">

 

2) DispatcherServlet 

- insertBoard_proc.jsp 파일에 있던 자바 코드를 복사하여 DispatcherServlet 클래스에 이동한다.

- 글 등록 처리 후 getBoardList.do가 아닌 getBoardList.jsp로 설정하면 글 등록 전 세션에 저장된 글 목록을 또다시 출력

- 한글 인코딩 코드는 DispatcherServlet의 doPost() 메소드가 일괄적으로 처리해주기 때문에 각 기능에서 삭제해도 된다.

		} else if(path.equals("/insertBoard.do")) {
			System.out.println("글 등록 처리");
			
			//1. 사용자 입력정보 추출(insertBoard.jsp에서 전송된 정보 추출)
			String title = request.getParameter("title");
			String writer = request.getParameter("writer");
			String content = request.getParameter("content");
			
			//2. DB 연동 처리(BoardDAO의 메소드 호출)
			BoardVO vo = new BoardVO();
			vo.setTitle(title);
			vo.setWriter(writer);
			vo.setContent(content);
			
			BoardDAO boardDAO = new BoardDAO();
			boardDAO.insertBoard(vo);
			
			//3. 화면 네비게이션
			//글 등록 처리 후 글 목록 페이지로 이동
			response.sendRedirect("getBoardList.do");
		} else if(path.equals("/updateBoard.do")) {
			System.out.println("글 수정 처리");

 

 

3.7절 글 수정 기능 구현하기

 

1) getBoard.jsp 

 

2) DispatcherServlet

- updateBoard_proc.jsp 파일에 있던 자바 코드를 복사하여 DispatcherServlet 클래스의 /updateBoard.do 분기 처리로 이동시킴

- 한글 인코딩 코드는 DispatcherServlet의 doPost() 메소드가 일괄적으로 처리해주기 때문에 각 기능에서 삭제해도 된다.

- 글 수정 작업이 처리된 후에도 반드시 /getBoardList.do를 리다이렉트하여 세션에 저장된 글 목록을 갱신한다.

 

 

3.8절 글 삭제 기능 구현하기

 

1) 글 삭제 관련 링크 수정 

- getBoard.jsp 파일에서 글 삭제 관련 링크를 deleteBoard.do로 수정하고 글 목록 링크도 .do로 변경한다.

 

2) DispatcherServlet 

- deleteBoard_proc.jsp 파일에 있던 자바 코드를 복사하여 DispatcherServlet 클래스의 /deleteBoard.do 분기 처리로 이동시킴

- 글 삭제 작업이 처리된 후에도 반드시 /getBoardList.do를 호출하여 세션에 저장된 글 목록을 갱신한다.

	} else if(path.equals("/deleteBoard.do")) {
			System.out.println("글 삭제 처리");
			
			//1.사용자 입력정보 추출(getBoard.jsp에서 전송된 정보 추출)
			String seq = request.getParameter("seq");

			//2. DB 연동 처리(BoardDAO의 메소드 호출)
			BoardVO vo = new BoardVO();
			vo.setSeq(Integer.parseInt(seq));
			
			BoardDAO boardDAO = new BoardDAO();
			boardDAO.deleteBoard(vo);
			
			//3. 화면 네비게이션
			//글 삭제 처리 후 글 목록 화면으로 이동
			response.sendRedirect("getBoardList.do");
		} else if(path.equals("/getBoard.do")) {
			System.out.println("글 상세 조회 처리");

 

 

3.9절 로그아웃 기능 구현하기

 

1) getBoard.jsp

- 로그아웃 기능을 MVC로 변환하려면 우선 모든 페이지에서 logout_proc.jsp 라는 링크를 모두 logout.do 링크로 수정한다.

<h1>글 목록</h1>
<h3>테스트님 환영합니다...<a href="logout.do">Log-out</a></h3>

 

2) DispatcherServlet 

- logout_proc.jsp 파일에 있던 자바 코드를 복사하여 DispatcherServlet 클래스의 /logout.do 분기 처리로 이동시킴

		} else if(path.equals("/logout.do")) {
			System.out.println("로그아웃 처리");
			
			//1. 브라우저와 연결된 세션 객체를 강제 종료한다.
			HttpSession session = request.getSession();
			session.invalidate();

			//2. 세션 종료 후, 로그인 화면으로 이동
			response.sendRedirect("login.jsp");
		} else if(path.equals("/insertBoard.do")) {
			System.out.println("글 등록 처리");

 

3) MVC 구조 확인

 

- Model 기능의 VO, DAO 클래스는 재사용되었고, DispatcherServlet이라는 Controller 기능의 서블릿이 추가되었다.

- JSP 파일에서는 Controller 기능의 자바 로직이 DispatcherServlet 클래스로 이동되어서 View 기능만 남음

- 따라서 xxx_proc.jsp 파일들은 모두 삭제해도 된다.

- getBoard.jsp와 getBoardList.jsp 파일에서도 Controller 자바 로직은 사라진 상태다.

- Controller 로직 : 사용자 입력 정보 추출, Model을 이용한 DB 연동 처리, 화면 네비게이션에 해당하는 자바 코드

- 결과적으로 MVC 아키텍처를 적용한 결과 JSP 파일에서 Controller 로직에 해당되는 자바 코드는 모두 제거됨

 

반응형

댓글