[아이티센 부트캠프] Servlet & JSP 실습 1

이언덕·2026년 4월 24일

아이티센 부트캠프

목록 보기
52/115
post-thumbnail

문제

먼저 문제 원본은 아래와 같다.

문제에서 실제로 구현해야 하는 조건만 다시 정리하면 이렇다.

  • 숫자를 입력하는 lottoForm.html에서 GET 방식으로 Servlet을 요청해야 한다.
  • 이번 실습에서는 LottoServletPractice2 클래스와 /lottoPractice2 매핑으로 진행한다.
  • 전달된 숫자는 Query String으로 받아야 한다.
  • 서버에서는 1~6 사이 랜덤값을 하나 뽑아야 한다.
  • 전달된 숫자와 랜덤값을 비교해서 결과를 정해야 한다.
  • 결과에 따라 msg, imginfo, display 값을 request에 저장해야 한다.
  • 모든 경우를 /practiceJsp/lottoResultPractice.jsp 하나로만 forward해야 한다.
  • JSP에서는 request.getAttribute()로 전달받은 값을 꺼내 화면에 출력해야 한다.


문제 해석

이 문제는 앞 실습처럼 결과에 따라 success.html, fail.html 두 페이지 중 하나를 고르는 문제가 아니다.
이번에는 결과 페이지가 lottoResultPractice.jsp 하나로 고정되어 있고, 대신 Servlet이 결과에 맞는 데이터를 request에 담아 넘겨 주는 구조다.


즉 이번 실습의 핵심은 페이지를 고르는 것보다 Servlet이 데이터를 저장하고 JSP가 그 데이터를 꺼내 출력하는 흐름을 이해하는 데 있다.
브라우저에서 숫자를 보내면 Servlet이 그 값을 받고 랜덤값과 비교한다.
그다음 결과에 따라 "당첨~~~~ 추카추카" 또는 "실패~~~ 아쉽아쉽" 같은 메시지와 이미지 주소를 request에 저장하고, 마지막에는 같은 JSP로 넘긴다.


또 이번에는 실패했을 때만 “다시 돌아가기” 링크가 보이도록 display 값까지 함께 넘겼다.
즉 화면 자체를 여러 개로 나누는 대신, 하나의 JSP가 전달받은 값에 따라 출력 내용을 바꾸는 방식이다.


즉 이 실습의 흐름은 아래처럼 정리할 수 있다.
lottoForm.html 연결 → 숫자 전달 → 랜덤값 생성 → 값 비교 → request.setAttribute()로 데이터 저장 → JSP로 forward → request.getAttribute()로 화면 출력


풀이 순서

  1. 이전 실습에서 사용한 로또 입력 폼을 그대로 사용하고, action 경로만 /edu/lottoPractice2로 수정한다.
  2. LottoServletPractice2에서 전달값과 랜덤값을 비교한 뒤, 결과에 맞는 msg, imginfo, display를 request에 저장한다.
  3. /practiceJsp/lottoResultPractice.jsp로 forward하고, JSP에서 msg, imginfo, display를 꺼내 출력한다.



자세한 풀이

1. lottoForm.html 연결하기

이번 문제의 입력 화면은 앞선 로또 실습과 거의 같았다.
숫자를 입력하고 클로버 이미지를 누르면 GET 방식으로 요청이 가는 구조는 그대로 두고, 이번에는 요청 대상만 /edu/lottoPractice2로 바꿨다.
즉 새로운 화면을 다시 만든 것이 아니라, 같은 입력 폼을 다음 Servlet 흐름에 맞게 다시 연결한 단계라고 보면 된다.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>로또 번호를 맞춰 보세요!!!</h1>
    <hr />
    <form method="get" action="/edu/lottoPractice2">
      <label for="lottoNum" style="font-size: 25px">1부터 6까지의 숫자를 입력하세요: </label>
      <input
        type="number"
        id="lottoNum"
        name="lottoNum"
        min="1"
        max="6"
        step="1"
        required
        style="width: 60px; height: 30px; font-size: 18px"
      />
      <input
        type="image"
        src="../images/clover.png"
        alt="로또 추첨"
        style="width: 50px; height: 50px"
      />
    </form>
  </body>
</html>

이 단계에서 중요한 것은 method="get", action="/edu/lottoPractice2", name="lottoNum" 세 가지다.
사용자가 숫자를 입력하고 이미지를 누르면 브라우저가 이 값을 Query String으로 붙여서 서버에 보내게 된다.

데이터 흐름 예상

<form method="get" action="/edu/lottoPractice2">
  <!-- 1. 브라우저가 `/edu/lottoPractice2`로 `GET` 요청을 보냄 -->
  <input type="number" id="lottoNum" name="lottoNum" min="1" max="6" step="1" required />
  <!-- 2. 사용자가 입력한 숫자가 `lottoNum`이라는 이름으로 전달됨 -->
  <input type="image" src="../images/clover.png" alt="로또 추첨" />
  <!-- 3. 클로버 이미지를 누르면 제출 버튼처럼 동작함 -->
</form>

→ 사용자가 1~6 사이 숫자를 입력한다.
→ 클로버 이미지를 누르면 브라우저가 GET 요청을 보낸다.
→ 주소에는 ?lottoNum=입력값 형태의 Query String이 붙는다.
→ 서버는 이 값을 나중에 request.getParameter("lottoNum")로 꺼내게 된다.



2. LottoServletPractice2에서 값 비교 후 request에 데이터 저장하기

이제 실제 핵심 처리 코드를 Servlet에 작성했다.
브라우저에서 전달한 숫자를 받아 정수로 바꾸고, 1~6 사이 랜덤값을 만든 뒤 두 값을 비교했다.
그리고 결과에 따라 msg, imginfo, display를 request에 저장한 다음, 마지막에는 같은 JSP로 forward했다.

package practiceLab;

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

@WebServlet("/lottoPractice2")
public class LottoServletPractice2 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");
         int lottoNum = Integer.parseInt(request.getParameter("lottoNum"));
         int randomNum = (int)(Math.random() * 6) + 1;

         System.out.printf("전달된 값: %d", lottoNum);
         System.out.println();
         System.out.printf("추출된 값: %d", randomNum);
         System.out.println();

         if(lottoNum == randomNum) {
             request.setAttribute("msg", "당첨~~~~ 추카추카");
             request.setAttribute("imginfo", "https://mblogthumb-phinf.pstatic.net/MjAyMjAxMjBfMzIg/MDAxNjQyNjcxNzgxNzk5.BjVMnEbJ3PAxwZ_HLThbhEZQMB8WDM9dsNJjryRzyUcg._J3HvhZMol90L88A1VG_mrc3RqRvy789Rv1Lil4O7t4g.JPEG.loveletro12/%EC%83%9D%EC%9D%BC_%EC%A7%A4.jpg?type=w800");
             request.setAttribute("display", "none");
         } else {
             request.setAttribute("msg", "실패~~~ 아쉽아쉽");
             request.setAttribute("imginfo", "https://mblogthumb-phinf.pstatic.net/MjAyMDEyMDdfMTQ3/MDAxNjA3MzMxMTU4MzIz.im6GMHgcLQ3kg9BatCBj9ESPP4zn1fWGdBcbioVjNsMg.PrhLfZAK_qFHfQA16q9S9d3O3W3-1WH35fT84EMIOjsg.JPEG.nari5636/20140110_232314_610008944.jpg?type=w800");
             request.setAttribute("display", "block");
         }

         RequestDispatcher rd = request.getRequestDispatcher("/practiceJsp/lottoResultPractice.jsp");
         rd.forward(request, response);
    }
}

여기서 핵심은 request.setAttribute()다.
이번 단계에서는 이 메서드를 원래 알고 쓰던 상태가 아니라, 직접 찾아보면서 역할을 이해하게 됐다.
찾아보면서 확인한 내용은 이렇다.
setAttribute()는 Servlet이 request 객체 안에 값을 저장하는 메서드이고, 이후 JSP는 그 값을 다시 꺼내서 출력할 수 있다.


즉 이번 문제는 결과에 따라 페이지를 나누는 구조가 아니라, Servlet이 결과 데이터를 request에 담고 같은 JSP 하나로 넘기는 구조라는 점이 핵심이었다.

데이터 흐름

int lottoNum = Integer.parseInt(request.getParameter("lottoNum"));
// 1. `Query String`으로 전달된 `lottoNum` 값을 문자열로 꺼낸 뒤 정수로 바꿈

int randomNum = (int)(Math.random() * 6) + 1;
// 2. `1~6` 사이의 랜덤값을 하나 만듦

System.out.printf("전달된 값: %d", lottoNum);
System.out.println();
System.out.printf("추출된 값: %d", randomNum);
System.out.println();
// 3. 전달된 값과 추출된 값을 콘솔에 출력해 비교 과정을 확인함

if(lottoNum == randomNum) {
    request.setAttribute("msg", "당첨~~~~ 추카추카");
    request.setAttribute("imginfo", "당첨 이미지 주소");
    request.setAttribute("display", "none");
} else {
    request.setAttribute("msg", "실패~~~ 아쉽아쉽");
    request.setAttribute("imginfo", "실패 이미지 주소");
    request.setAttribute("display", "block");
}
// 4. 비교 결과에 따라 `request` 안에 메시지, 이미지 주소, 링크 표시 여부를 저장함

RequestDispatcher rd = request.getRequestDispatcher("/practiceJsp/lottoResultPractice.jsp");
rd.forward(request, response);
// 5. 저장한 값을 들고 같은 `JSP`로 넘김

→ 브라우저에서 예를 들어 3을 입력하면 주소에는 ?lottoNum=3이 붙는다.
→ 서버는 이 값을 꺼내 int로 변환한다.
→ 서버가 랜덤값을 하나 뽑는다.
→ 두 값을 비교한 뒤 결과에 따라 msg, imginfo, display 값을 다르게 저장한다.
→ 마지막에는 같은 JSP로 forward한다.

트러블 슈팅

이번 단계에서는 setAttribute()와 getAttribute()를 처음부터 알고 있던 상태가 아니었다.
처음에는 이 메서드들이 어떤 역할을 하는지 몰랐기 때문에, 직접 찾아보면서 흐름을 이해하게 됐다.


찾아보면서 확인한 내용은 이렇다.
setAttribute("msg", 값)은 request 객체 안에 "msg"라는 이름으로 값을 저장하는 것이고,
getAttribute("msg")는 나중에 JSP에서 그 이름으로 저장된 값을 다시 꺼내는 것이다.


즉 이번 문제는 Servlet이 결과값을 직접 화면에 출력하는 구조가 아니라,
request에 필요한 데이터를 저장한 뒤 JSP가 그 값을 꺼내 화면을 만드는 구조라는 점을 새로 알게 됐다.



3. lottoResultPractice.jsp에서 저장된 값 꺼내 출력하기

마지막 단계에서는 Servlet이 저장해 둔 값을 JSP에서 꺼내 실제 화면에 출력했다.
이번 단계의 핵심은 request.getAttribute()다.
앞 단계에서 Servlet이 setAttribute()로 넣어 둔 값들을 여기서 이름으로 다시 꺼내 쓰게 된다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1><%= request.getAttribute("msg") %></h1>
<img src=<%= request.getAttribute("imginfo") %> />
<a style="display:<%= request.getAttribute("display") %>;" href="/edu/practiceexam/lottoForm2.html">다시 돌아가기</a>
</body>
</html>

이 코드에서는 msg를 h1에 출력하고, imginfo를 img 태그의 src 값으로 사용했다.
또 display 값을 a 태그의 style에 넣어서, 실패했을 때만 "다시 돌아가기" 링크가 보이도록 처리했다.
즉 같은 JSP를 사용하더라도, Servlet이 넘긴 값에 따라 화면 내용이 달라지게 된다.

데이터 흐름

<h1><%= request.getAttribute("msg") %></h1>
<!-- 1. `Servlet`이 저장한 `msg` 값을 꺼내 제목처럼 출력함 -->

<img src=<%= request.getAttribute("imginfo") %> />
<!-- 2. `Servlet`이 저장한 `imginfo` 값을 꺼내 이미지 경로로 사용함 -->

<a style="display:<%= request.getAttribute("display") %>;" href="/edu/practiceexam/lottoForm2.html">다시 돌아가기</a>
<!-- 3. `display` 값을 꺼내 링크를 보이거나 숨김 -->

→ Servlet이 "당첨~~~~ 추카추카"를 저장했다면 JSP는 그 문장을 그대로 출력한다.
→ Servlet이 당첨 이미지를 저장했다면 JSP는 그 이미지를 화면에 보여 준다.
→ Servlet이 display 값을 "none"으로 저장하면 링크는 숨겨지고, "block"으로 저장하면 링크가 보인다.
→ 즉 JSP는 계산을 하는 쪽이 아니라, 전달받은 값을 화면에 출력하는 역할을 맡는다.



최종 코드

lottoForm.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>로또 번호를 맞춰 보세요!!!</h1>
    <hr />
    <form method="get" action="/edu/lottoPractice2">
      <label for="lottoNum" style="font-size: 25px">1부터 6까지의 숫자를 입력하세요: </label>
      <input
        type="number"
        id="lottoNum"
        name="lottoNum"
        min="1"
        max="6"
        step="1"
        required
        style="width: 60px; height: 30px; font-size: 18px"
      />
      <input
        type="image"
        src="../images/clover.png"
        alt="로또 추첨"
        style="width: 50px; height: 50px"
      />
    </form>
  </body>
</html>

LottoServletPractice2.java

package practiceLab;

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

@WebServlet("/lottoPractice2")
public class LottoServletPractice2 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");
         int lottoNum = Integer.parseInt(request.getParameter("lottoNum"));
         int randomNum = (int)(Math.random() * 6) + 1;

         System.out.printf("전달된 값: %d", lottoNum);
         System.out.println();
         System.out.printf("추출된 값: %d", randomNum);
         System.out.println();

         if(lottoNum == randomNum) {
             request.setAttribute("msg", "당첨~~~~ 추카추카");
             request.setAttribute("imginfo", "https://mblogthumb-phinf.pstatic.net/MjAyMjAxMjBfMzIg/MDAxNjQyNjcxNzgxNzk5.BjVMnEbJ3PAxwZ_HLThbhEZQMB8WDM9dsNJjryRzyUcg._J3HvhZMol90L88A1VG_mrc3RqRvy789Rv1Lil4O7t4g.JPEG.loveletro12/%EC%83%9D%EC%9D%BC_%EC%A7%A4.jpg?type=w800");
             request.setAttribute("display", "none");
         } else {
             request.setAttribute("msg", "실패~~~ 아쉽아쉽");
             request.setAttribute("imginfo", "https://mblogthumb-phinf.pstatic.net/MjAyMDEyMDdfMTQ3/MDAxNjA3MzMxMTU4MzIz.im6GMHgcLQ3kg9BatCBj9ESPP4zn1fWGdBcbioVjNsMg.PrhLfZAK_qFHfQA16q9S9d3O3W3-1WH35fT84EMIOjsg.JPEG.nari5636/20140110_232314_610008944.jpg?type=w800");
             request.setAttribute("display", "block");
         }

         RequestDispatcher rd = request.getRequestDispatcher("/practiceJsp/lottoResultPractice.jsp");
         rd.forward(request, response);
    }
}

lottoResultPractice.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1><%= request.getAttribute("msg") %></h1>
<img src=<%= request.getAttribute("imginfo") %> />
<a style="display:<%= request.getAttribute("display") %>;" href="/edu/practiceexam/lottoForm2.html">다시 돌아가기</a>
</body>
</html>



실습하면서 확인한 점

  • GET 요청은 입력값이 주소의 Query String으로 전달된다.
  • request.setAttribute()는 Servlet이 request 객체 안에 값을 저장할 때 사용한다.
  • request.getAttribute()는 JSP가 그 값을 다시 꺼내서 화면에 출력할 때 사용한다.
  • 이번 실습처럼 하나의 JSP만 사용할 때는 Servlet이 어떤 데이터를 넘기느냐에 따라 같은 페이지의 출력 내용이 달라진다.
  • 결과 페이지를 여러 개로 나누지 않아도, msg, imginfo, display 같은 값을 다르게 저장하면 같은 JSP 안에서 여러 상황을 처리할 수 있다.
  • 이번 실습에서는 Servlet은 데이터 계산과 저장, JSP는 화면 출력이라는 역할 분리를 직접 확인할 수 있었다.

0개의 댓글