본문 바로가기
☕ Java 웹 프로그래밍/Servlet & JSP

[Servlet&JSP] 계산기 서블릿 완성하기

by 일단연 2023. 6. 3.

* 본 글은 [뉴렉처]의 Servlet&JSP 프로그래밍 강의를 듣고 정리한 글입니다.

 

2020 Servlet&JSP 프로그래밍

 

www.youtube.com

 

 계산기 서블릿 완성하기 

CalcPage.java의 태그에 연산식 입력 - 결과: 연산식을 계산한 값을 출력

  • 사용자가 누른 버튼의 값들(value, operator, dot)이 누적되어 입력창에 그 누적된 값들이 연산된 결과가 출력되어야 함

 

계산기 서블릿의 구동 과정

  • 1) CalcPage.java의 화면에서 사용자가 값 버튼을 클릭해 POST 요청
  • 2) Calc3.java에서 그 값들(value, operator, dot)을 누적한 값인 exp를 쿠키로 저장한 후 > CalcPage.java로 redirect
  • 3) CalcPage.java는 Calc3.java에서 exp를 쿠키로 읽어서 printf( )메소드로 화면에 출력 (계산기에 최종 출력됨)

 

계산기 서블릿 완성하기 - CalcPage.java와 Calc3.java

  • 1) [CalcPage.java] calc3.java에서 쿠키 객체와 쿠키를 읽어내는 코드를, CalcPage.java로 복사+붙여넣기
    • Calc3.java의 exp를 배열 형태의 쿠키로 받는 작업을 제일 먼저 수행하도록 CalcPage.java 코드 맨위에 위치시킴
    • 연산식 자체를 읽어내도록 operator를 exp(expression, 표현식)으로 변경
      • 원래 아래의 코드였음
        String operator = "";
        for(Cookie c : cookies) {
           if(c.getName().equals("op")) {
              operator = c.getValue( );
              break;
           }
        }
    • 쿠키가 null일 경우를 대비
      • 쿠키가 null이 아니면 쿠키를 읽어오는 조건식 사용
      • 쿠키가 null이면 exp의 기본값은 0
  •  
  •  
  • // 1) Cookie[] cookies = request.getCookies(); String exp = "0"; if(cookies != null) { for(Cookie c : cookies) { if(c.getName().equals("exp")) { exp = c.getValue(); break; } } }

 

  • 2) [CalcPage.java] 계산기에 연산식이 출력되도록, CalcPage.java의 html 코드 안 출력 서식은 %s로, 출력 내용은 exp로 변경
    • out.printf("<td class = \"output\" colspan=\"4\">%s</td>", exp);
    • printf( )메소드의 형식: out.printf ("출력 서식", 출력할 내용);

 

  • 3) [calc3.java] 불필요한 코드 제거
    • Application, Session 코드는 제거
      • ServletContext application = request.getServletContext( );
        HttpSession session = request.getSession( );
    • calc3.java에서 출력할 일은 없으니까 출력 형식 코드 제거
      • response.setContentType("text/html; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");

 

  • 4) [calc3.java] 클라이언트가 보낸 값들을 받는 문자열을 value, operator, dot 3개로 만듦
// 4) 사용자가 입력한 값들을 받는 문자열
String value = request.getParameter("value");
String operator = request.getParameter("operator");
String dot = request.getParameter("dot");

 

  • 5) [calc3.java] 불필요한 코드 제거
    • 서버가 쿠키를 배열로 받아들이는 코드, 사용자가 입력한 값들을 받아들이는 문자열 코드, 클라이언트로 redirect하는 코드를 제외한 모든 코드는 제거
@WebServlet("/calc3")
public class Calc3 extends HttpServlet {
  @Override
  protected void service(HttpServletRequest request
                        , HttpServletResponse response)
                        throws ServletException, IOException
  {
    //브라우저가 POST 요청할 때 보낸 쿠키를 서버가 읽음
    Cookie[] cookies = request.getCookies();

    //사용자가 입력한 값들을 받는 문자열
    String value = request.getParameter("value");
    String operator = request.getParameter("operator");
    String dot = request.getParameter("dot");

    //html 페이지로 redirect
    response.sendRedirect("calc2.html");
  }
}

 

  • 6) [calc3.java] exp 쿠키를 저장하기 위해 쿠키 객체 생성
    • Cookie expCookie = new Cookie("exp", exp);
    • 쿠키 객체 생성하는 방법
      • Cookie 쿠키객체명 = new Cookie(key, value);
  • 7) [calc3.java] 클라이언트가 쿠키를 저장하도록 addCookie( ) 메소드 사용
    • response.addCookie(expCookie);
    • 서버에서 클라이언트로 쿠키 보내는 방법
      • response.addCookie(쿠키 객체명);
      • 브라우저는 response에 심어진 값을 읽어서 그 값을 자신이 가짐
  • 8) [calc3.java] redirect 주소 변경
    • response.sendRedirect("calcpage");
      • Calc3.java에서 CalcPage.java로 넘어갈 때의 경로가 같기 때문에 경로(/, 루트)를 쓰지 않고 주소만 써도 됨 > /calcpage 대신 calcpage로 써도 된다는 뜻
    • 이전에는 response.sendRedirect("calc2.html"); 였음
// 6), 7), 8) 쿠키에에서 값을 읽어와 사용자가 입력한 값에 덧붙인 값을 쿠키로 저장
Cookie expCookie = new Cookie("exp", exp);
response.addCookie(expCookie);	
response.sendRedirect("calcpage");

 

  • 9) [calc3.java] 문자열 exp 만들기
    • 쿠키가 null일 경우와 아닌 경우를 나눠서 코드 작성
      • 쿠키가 null이 아니면 쿠키를 읽어오는 조건식 사용
      • 쿠키가 null이면 exp의 기본값은 빈 문자열
        • String exp = "";
// 9) 쿠키에서 값을 읽어와 사용자가 입력한 값에 덧붙임
String exp = "";
if(cookies != null) {
  for(Cookie c : cookies) {
    if(c.getName().equals("exp")) {
      exp = c.getValue();
      break;
    }
  }
}

 

  • 10) [calc3.java] exp에 value, operator, dot 누적시키기
    • 사용자가 버튼을 클릭할 때 value, operator, dot 중 값 하나만 전달되므로 각각 코드를 작성
    • value/operator/dot 중 하나가 쿠키로 전달됐을 때 value/operator/dot가 null이면 빈 문자열을, null이 아니면 value/operator/dot 중 하나를 exp에 붙임
      • exp += (value == null) ? "" : value;
      • exp += (operator == null) ? "" : operator;
      • exp += (dot == null) ? "" : dot;
    • 삼항 연산자 사용법
      • 조건식 ? 반환값1 : 반환값2
      • 예: result = (num1 - num2 > 0) ? num1 : num2;

 

  • 11) [calc3.java] operator가 =일 경우엔 누적시키는 게 아니라 값을 계산해서 exp에 남겨야 하기 때문에 이를 위한 조건문 작성
    • operator가 =이 아닌 경우(+, -, x, ÷), 값을 누적
    • operator가 null이 아니고 =인 경우, 값을 계산
    • 값을 계산하는 식이 Java나 JavaScript에서 구문상 차이가 없기 때문에, Java에서 JavaScript를 실행할 수 있는 라이브러리 ScriptEngine(javax.script의 인터페이스) 사용
      • ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); engine.eval(exp);
        • getEngineByName( )으로 엔진 이름을 얻어오고, eval( )로 JavaScript 실행
      • engine.eval(exp); 은 예외처리를 해줘야 함
      • engine.eval(exp)를 exp에 저장
        • exp는 String이고 engine.eval(exp)는 Object라서 변환해줘야 함
        • exp = String.valueOf(engine.eval(exp));
// 10), 11) 사용자가 입력한 값이 =이라면 계산을 위한 로직 구현
if(operator != null && operator.equals("=")) {
  ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
  try {
    exp = String.valueOf(engine.eval(exp));
  } catch (ScriptException e) {
    e.printStackTrace();
  }
}
//사용자가 입력한 값이 value, operator, dot이라면 누적
else {
  exp += (value == null) ? "" : value;
  exp += (operator == null) ? "" : operator;
  exp += (dot == null) ? "" : dot;
}

 

  • 12) [CalcPage.java] <table>의 <input>에서 operator를 x가 아니라 *로, ÷이 아니라 /로 변경
    • 곱셈 연산자를 *가 아니라 x, 나눗셈 연산자를 /가 아니라 ÷로 써놨기 때문에 계산식을 만들어 수행할 때 문제가 되기 때문
    • x와 ÷를 계속 쓰려면 Calc3.java에서 해당 문자를 *와 /로 대치하는 작업을 해야 함

 

 

계산기 서블릿 완성하기 주의사항 - CalcPage.java와 Calc3.java

  • 먼저 브라우저의 쿠키 제거
    • 개발자 도구>Network>calcpage에서 오른쪽 클릭>Clear browser cookies 클릭
  • CalcPage.java와 Calc3.java의 매핑 주소가 모두 정확해야 함
    • CalcPage.java에서 @WebServlet("/calcpage")
    • CalcPage.java의 HTML 코드에서 out.write("<form action=\"calc3\" method=\"post\">");
    • Calc3.java에서 @WebServlet("/calc3")

 

계산기 서블릿 완성하기 결과 - CalcPage.java와 Calc3.java

        계산식: 3*5 - 8/4 + 2

  • [ 3 ] 숫자 3를 클릭하면 서버에 value: 3이 POST 요청으로 전달 > 쿠키로 저장됨 (3 누적)

  • [ 3 * ] 연산자 *를 클릭하면 서버에 operator: *가 POST 요청으로 전달 > 쿠키로 저장 (3 다음에 *가 누적됨)

  • [ 3 * 5 ] 숫자 5를 클릭하면 서버에 value: 5이 POST 요청으로 전달 > 쿠키로 저장됨 (3 다음 * 다음 5 누적됨)

  • [ 3 * 5 - ] 연산자 -를 클릭하면 서버에 operator: -이 POST 요청으로 전달 > 쿠키로 저장됨 (3 다음 * 다음 5 다음 - 누적됨)

  • [ 3 * 5 - 8 ] 숫자 8를 클릭하면 서버에 value: 8이 POST 요청으로 전달 > 쿠키로 저장됨 (3 다음 * 다음 5 다음 - 다음 8 누적됨)

  • [ 3 * 5 - 8 / ] 연산자 /를 클릭하면 서버에 operator: /이 POST 요청으로 전달 > 쿠키로 저장됨 (3 다음 * 다음 5 다음 - 다음 8 다음 / 누적됨)

  • [ 3 * 5 - 8 / 4 ] 숫자 4를 클릭하면 서버에 value: 4이 POST 요청으로 전달 > 쿠키로 저장됨 (3 다음 * 다음 5 다음 - 다음 8 다음 / 다음 4 누적됨)

  • [ 3 * 5 - 8 / 4 + ] 연산자 +를 클릭하면 서버에 operator: +이 POST 요청으로 전달 > 쿠키로 저장됨 (3 다음 * 다음 5 다음 - 다음 8 다음 / 다음 4 다음 + 누적됨)

  • [ 3 * 5 - 8 / 4 + 2 ] 숫자 2를 클릭하면 서버에 value: 2이 POST 요청으로 전달 > 쿠키로 저장됨 (3 다음 * 다음 5 다음 - 다음 8 다음 / 다음 4 다음 + 다음 2 누적됨)

  • [ 3 * 5 - 8 / 4 + 2 = 15 ] =를 클릭하면 누적된 값들이 계산되어 exp에 저장 > exp가 쿠키에 담겨서 클라이언트(CalcPage.java)로 전달 > 클라이언트는 그 쿠키를 읽어서 화면에 출력 > 결과: 15

 

계산기 서블릿 코드 - CalcPage.java와 Calc3.java

  • CalcPage.java
package com.newlecture.web;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/calcpage")
public class CalcPage extends HttpServlet {
  @Override
  protected void service(HttpServletRequest request
                        , HttpServletResponse response)
                        throws ServletException, IOException
  {
    Cookie[] cookies = request.getCookies();
		
    String exp = "0";
    if(cookies != null) {
      for(Cookie c : cookies) {
        if(c.getName().equals("exp")) {
          exp = c.getValue();
          break;
        }
      }
    }
		
    response.setContentType("text/html; charset=UTF-8");
    response.setCharacterEncoding("UTF-8");
    PrintWriter out = response.getWriter();

    out.write("<!DOCTYPE html>");
    out.write("<html>");
    out.write("  <head>");
    out.write("    <meta charset=\\"UTF-8\\">");
    out.write("    <title>계산기 웹 프로그램</title>");
    out.write("    <style>");
    out.write("      input{");
    out.write("        width: 50px;");
    out.write("        height: 50px;");
    out.write("      }");
    out.write("      .output{");
    out.write("        height: 50px;");
    out.write("        background: #e9e9e9;");
    out.write("        font-size: 24px;");
    out.write("        font-weight: bold;");
    out.write("        text-align: right;");
    out.write("        padding: 0px 5px;");
    out.write("      }");
    out.write("    </style>");
    out.write("  </head>");
    
    out.write("  <body>");
    out.write("    <form action=\\"calc3\\" method=\\"post\\">");
    out.write("      <table>");
    out.write("        <tr>");
    out.printf("          <td class = \\"output\\" colspan=\\"4\\">%s</td>", exp);
    out.write("        </tr>");
    out.write("        <tr>");
    out.write("          <td><input type=\\"submit\\" name=\\"operator\\" value=\\"CE\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"operator\\" value=\\"C\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"operator\\" value=\\"BS\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"operator\\" value=\\"÷\\"></td>");
    out.write("        </tr>");
    out.write("        <tr>");
    out.write("          <td><input type=\\"submit\\" name=\\"value\\" value=\\"7\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"value\\" value=\\"8\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"value\\" value=\\"9\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"operator\\" value=\\"x\\"></td>");
    out.write("        </tr>");
    out.write("        <tr>");
    out.write("          <td><input type=\\"submit\\" name=\\"value\\" value=\\"4\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"value\\" value=\\"5\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"value\\" value=\\"6\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"operator\\" value=\\"-\\"></td>");
    out.write("        </tr>");
    out.write("        <tr>");
    out.write("          <td><input type=\\"submit\\" name=\\"value\\" value=\\"1\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"value\\" value=\\"2\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"value\\" value=\\"3\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"operator\\" value=\\"+\\"></td>");
    out.write("        </tr>");
    out.write("        <tr>");
    out.write("          <td></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"value\\" value=\\"0\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"dot\\" value=\\".\\"></td>");
    out.write("          <td><input type=\\"submit\\" name=\\"operator\\" value=\\"=\\"></td>");
    out.write("        </tr>");
    out.write("      </table>");
    out.write("    </form>");
    out.write("  </body>");
    out.write("</html>");
  }
}
  • Calc3.java
package com.newlecture.web;

import java.io.IOException;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/calc3")
public class Calc3 extends HttpServlet {
  @Override
  protected void service(HttpServletRequest request
                        , HttpServletResponse response)
                        throws ServletException, IOException
  {
    Cookie[] cookies = request.getCookies();
		
    //사용자가 입력한 값들을 받는 문자열
    String value = request.getParameter("value");
    String operator = request.getParameter("operator");
    String dot = request.getParameter("dot");
		
    //쿠키에서 값을 읽어와 사용자가 입력한 값에 덧붙임
    String exp = "";
    if(cookies != null) {
      for(Cookie c : cookies) {
        if(c.getName().equals("exp")) {
          exp = c.getValue();
          break;
        }
      }
    }
		
    //사용자가 입력한 값이 =이라면 계산을 위한 로직 구현
    if(operator != null && operator.equals("=")) {
      ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
      try {
        exp = String.valueOf(engine.eval(exp));
      } catch (ScriptException e) {
        e.printStackTrace();
      }
    }
    //사용자가 입력한 값이 value, operator, dot이라면 누적
    else {
      exp += (value == null) ? "" : value;
      exp += (operator == null) ? "" : operator;
      exp += (dot == null) ? "" : dot;
    }
		
    //쿠키에에서 값을 읽어와 사용자가 입력한 값에 덧붙인 값을 쿠키로 저장
    Cookie expCookie = new Cookie("exp", exp);
    response.addCookie(expCookie);	
    response.sendRedirect("calcpage");
  }
}