1. MVC 구조와 Servlet / JSP

  - Servlet: 자바의 코드 그대로 이용 가능, 상속이나 인터페이스 처리도 가능, HTTP로 전달된 HTML 처리 시 많은 코드 필요

  - JSP: HTML 코드를 바로 사용할 수 있어 HTTP 메세지 작성에 적합, 그 안의 자바 코드를 재사용하고 자바 코드와 HTML이 혼재 하는 등의 문제 존재

  - 절충안: 브라우저 요청은 해당 주소를 처리하는 Servlet에 전달 → Servlet 내부에서 응답에 필요한 재료 데이터 준비 → 준비한 데이터를 JSP에 전달 → JSP는 EL을 이용해 최종 결과 데이터 생성

 

  - MVC 구조: Model - View - Controller의 역할을 분리하여 처리, 데이터는 Controller(Servlet), 결과는 View(JSP)에서 처리

  - Servlet(Controller)가 JSP(View)에 필요한 데이터를 가공, 이때 필요한 데이터를 제공하는 객체가 Model

 

 1) MVC 구조로 계산기 설계

  • MVC 구조의 원칙
    • 브라우저의 호출은 반드시 Controller의 역할을 하는 Servlet을 호출하도록 구성
    • JSP는 브라우저에서 직접 호출 x, Controller 통해서만 JSP에 접근하도록 구성

 

  • GET 입력 화면 설계
    1. 브라우저는 /input과 같이 특정한 주소 호출
    2. /input에 맞는 Servlet을 InputController로 작성(GET 방식일 때만 동작하도록 함)
    3. InputController의 화면처리는 input.jsp를 이용하도록 지정
    4. input.jsp에는 HTML 코드를 이용해 브라우저에서 볼 수 있는 결과 생성
    • 컨트롤러에서 View 호출
package org.zerock.w1.calc;

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

// @WebServlet으로 urlPatterns 속성을 지정해서 처리해야 하는 경로 지정("/calc/input" 경로에서 데이터를 받아 처리하려고 함)
@WebServlet(name = "inputController", urlPatterns = "/calc/input")
public class InputController extends HttpServlet{

  // 부모 클래스에 있던 doGet을 Override하여 다시 정의
  // GET 방식으로 들어오는 요청에 대해서만 처리하도록 구성
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
    System.out.println("InputController...doGet...");

    // RequestDispatcher는 Servlet에서 전달된 요청을 다른 쪽으로 전달 또는 배포하는 역할의 객체
    // InputController는 RequestDispatcher를 거쳐서 '/WEB-INF/calc/input.jsp'라는 목적지에 도착 가능
    // WEB-INF는 브라우저에서 직접 접근이 불가능한 경로, jsp 파일을 브라우저에서 직접 호출할 수 없도록 하기 위함
    RequestDispatcher dispatcher = req.getRequestDispatcher("/WEB-INF/calc/input.jsp");

    dispatcher.forward(req, resp);
  }
}

 

    • RequestDispatcher를 이용하여 InputController가 '/WEB-INF/calc/input.jsp'로 접근하는 과정

 

    • 결과
    • 주소창에 'localhost:8080/calc/input.jsp'가 아닌 'localhost:8080/calc/input'으로 접속함
      • 이는 InputController 내부의 RequestDispatcher에 의해 'calc/input' 경로로 접속하면 자동으로 '/WEB-INF/calc/input.jsp'로 접근하도록 설정되었기 때문
      • 이로 인해, 브라우저에서 직접 jsp 파일에 접근할 필요가 없어짐
    • 또한, doGet이 실행됐을 때 "InputController...doGet..."이 print되도록 하여 로그에 "InputController...doGet..." 출력됨

 

  • POST 처리 설계
    1. input.jsp의 <form>태그의 action을 '/calcResult'와 같이 변경, 해당하는 CalcResultServlet 을 Controller로 작성
    2. calcResultServlet은 <form>으로 전달되는 num1, num2 데이터를 읽고 결과 데이터를 만듦
    3. 만들어진 결과를 calcResult.jsp와 같이 JSP로 전달해야 하고, JSP에서는 결과 데이터 출력
    • CalcController 생성(InputController에 doPost를 doGet과 같이 Override하여 작성해도됨)
package org.zerock.w1.calc;

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

@WebServlet(name = "calcController", urlPatterns = "/calc/makeResult")
public class calcController extends HttpServlet{

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{

    // req.getParameter라는 메서드를 사용하여 쿼리 스트링으로 전달되는 num1과 num2 파라미터를 처리
    // 이때, 숫자가 아닌 문자열로 처리
    // JSP에서는 ${param.num1}과 같이 단순하게 사용가능하지만, Servlet에서는 HttpServletRequest aPI를 이용해야함
    String num1 = req.getParameter("num1");
    String num2 = req.getParameter("num2");

    System.out.printf(" num1: %s", num1);
    System.out.printf(" num2: %s", num2);
  }
}

 

    • 'WEB-INF/calc/input.jsp' 파일에서 SEND 버튼을 통해 form 태그를 'calcResult.jsp'로 전송하고 있음
    • calcController에서는 urlPatterns 속성을 '/calc/makeResult'로 지정하였으므로, 'calcResult.jsp' 경로를 '/calc/makeResult'로 수정해야함
    • 이제 SEND 버튼을 클릭하면 'localhost:8080/calc/makeResult' 경로로 이동함
    • 또한, 화면은 비어있지만, System.out.printf 명령어를 통해 num1과 num2의 값을 로그에 정상적으로 출력함
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form action='/calc/makeResult' method='post'>

    <input type="number" name="num1">
    <input type="number" name="num2">
    <button type="submit">SEND</button>
    
</form>

</body>
</html>

 

  • sendRedirect()
    • POST 방식으로 처리하고 JSP로 결과를 보여준 이후에는 브라우저 창에서 반복적인 호출을 막기 위해 처리가 끝남과 동시에 다른 경로로 이동하게 하는 것이 일반적(로그인창에서 아이디, 비밀번호 입력 후 로그인 처리 끝나면 로그인을 반복적으로 시도하지 못하게 다른 화면으로 넘어감)
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{

String num1 = req.getParameter("num1");
String num2 = req.getParameter("num2");

System.out.printf(" num1: %s", num1);
System.out.printf(" num2: %s", num2);

resp.sendRedirect("/index");

    • sendRedirect를 통해 처리가 끝난 후 '/index' 경로를 호출하여 해당 페이지가 나오며, 아직 '/index'의 Controller를 생성하지 않아서 위의 에러가 발생

 

 

2. PRG 패턴(POST - Redirect - GET)

  - MVC 구조에서 가장 흔하게 사용되는 패턴

  - PRG 패턴의 흐름

  • 사용자는 Controller에 원하는 작업을 POST 방식으로 처리하기를 요청
  • POST 방식을 Constroller에서 처리하고 브라우저는 다른 경로로 이동(GET)하라는 응답(Redirecct)
  • 브라우저는 GET 방식으로 이동

 

 1) PRG 패턴을 이용한 와이어 프레임 작성

  • 간단한 Todo List 작성 
  • 와이어 프레임: 웹 개발 전, 여러 페이지를 만들때 이동이 많기 때문에, 우선 설계를 통해 동작의 흐름을 미리 구성
  • 와이어 프레임 요령
    • 화면에는 해당 페이지를 볼 수 있는 경로(URL) 명시
    • GET 방식으로 동작하고 눈에 보이는 것 먼저 구성
    • POST 방식으로 처리되는 Controller는 다른 그림으로 표현
    • redirect 되어 보영지는 경우 다른 선으로 표현
  • Todo List 웹 애플리케이션의 와이어 프레임 그리기
    • 목록 화면(GET): GET 방식으로 조회, 등록 / 수정 / 삭제 후 결과 확인할 수 있는 화면
    • 등록 화면(GET)
    • 등록 화면(POST): 등록 화면에서 입력한 내용들 을 POST 방식으로 전소오디기 때문에 별도의 Controller 추가, 처리 후에는 Redirect로 다시 목록 화면 보여지도록 설계
    • 조회 화면(GET): 목록 화면에서 특정 Todo 글을 클릭하면 동작하도록 설계
    • 수정 / 삭제 화면(GET): 조회 화면에서 '수정/삭제'를 선택하면 GET 방식으로 이동하도록 설계
    • 수정(POST): Controller에서 수정이 POST 방식으로 처리되고 다시 목록 화면으로 Redirect
    • 삭제(POST): 수정과 동일
  • 구현 목록 정리
기능 동작 방식 Controller(org.zerock.w1.todo) JSP
 목록 GET TodoListController WEB-INF/todo/list.jsp
등록(입력) GET TodoRegisterController WEB-INF/todo/register.jsp
등록(처리) POST TodoRegisterController Redirect
조회 GET TodoReadController WEB-INF/todo/read.jap
수정(입력) GET TodoModifyController WEB-INF/todo/modify.jsp
수정(처리) POST TodoModifyController Redirect
삭제(처리) POST TodoRemoveController Redirect

+ Recent posts