문제
먼저 문제 원본은 아래와 같다.
문제에서 실제로 구현해야 하는 조건만 다시 정리하면 이렇다.
- 숫자를 입력하는
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()로 화면 출력
풀이 순서
- 이전 실습에서 사용한 로또 입력 폼을 그대로 사용하고,
action경로만/edu/lottoPractice2로 수정한다.LottoServletPractice2에서 전달값과 랜덤값을 비교한 뒤, 결과에 맞는msg,imginfo,display를request에 저장한다./practiceJsp/lottoResultPractice.jsp로forward하고,JSP에서msg,imginfo,display를 꺼내 출력한다.
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")로 꺼내게 된다.
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가 그 값을 꺼내 화면을 만드는 구조라는 점을 새로 알게 됐다.
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.javapackage 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는 화면 출력이라는 역할 분리를 직접 확인할 수 있었다.