데이터 처리를 클라이언트 측에서 요청받은 후 서버 측에서 처리하고, 클라이언트에게 다시 페이지를 로드하거나 새로운 페이지로 리다이렉트하는 것입니다. 이는 서버측에서 데이터를 처리한 후 처리 결과를 클라이언트에게 다른 페이지로 보여주는 역할이나, 혹은 사용자가 새로고침을 눌렀을 때 동일한 정보가 서버로 요청되는 불필요한 작업을 방지하고자 하는 역할에 주로 사용되는데요.
이러한 리다이렉션은 크게 리다이렉션을 실행할 때 정보가 유지되느냐, 유지되지 않느냐의 차이를 두면서 두 가지 메서도르 나뉘는데요. 그것이 바로 RequestDispatcher 객체의 forward 메서드와, HttpServletRequest 객체의 sendRedirect 메서드입니다.
request의 정보는 클라이언트의 요청과 그 요청을 받은 JSP 페이지 혹은 서블릿 서버에서만 유효합니다. 그래서 해당 페이지나 서버에서 사용자의 정보를 처리한 뒤 그 결과를 사용자에게 응답으로 보내게 되죠. 물론 편법으로 URL에 GET 방식 처럼 사용자의 요청 값들을 묶어 보내는 방법도 있지만 좀 비효율적일 수 밖에 없겠죠.
(자료 출처 : https://mangkyu.tistory.com/51)
하지만 forward의 경우 reuqest 객체에 사용자의 요청 값들을 저장한 뒤 dispatcher에 forward 메서드로 보내고자 하는 페이지에 request와 response를 보내는 방식으로 처리가 가능하기 때문에 정리하자면 정보를 별도의 인코딩 과정 없이 원형으로 보내는 것이 가능합니다.
해당 메서드를 사용하기에 앞서, 다음과 같은 JSP 구조가 있다고 생각해 봅시다.
main.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 정보 전달 해보기</h1> <form action="sub1.jsp" method = "get"> <label>이름 : <input type = "text" name = "name"></label> <label>나이 : <input type = "number" name = "age"></label> <input type="submit" value="제출"> </form> </body> </html>
이 정보를 sub1.jsp가 받아서 sub2.jsp로 리다이렉트 하는 코드로 작성되었습니다. 이때 sendRedirect로 전달할 때는 페이지의 URL을 전송해야 하기 때문에 get 방식으로 조합을 해 sub2.jsp 페이지와 정보를 함께 묶은 url을 전송해야 하는데요.
거기에 한자나 한글과 같은 비아스키 코드 언어는 전달 받는 쪽에서 제대로 식별을 하지 못하기 때문에 URLEncoder 객체의 메서드로 인코딩 처리를 해주어야 하는 불편함도 존재하죠.
<%@page import="java.net.URLEncoder"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String name = request.getParameter("name"); String age = request.getParameter("age"); /* db에 저장하거나, 섹션에 저장하는 용도로 작업 수행 */ // 조합을 해보면 url은 "sub2.jsp?name=Re_Go&age=30" 이 됩니다. String redirectURL = "sub2.jsp?name=" + URLEncoder.encode(name, "UTF-8") + "&age=" + age; response.sendRedirect(redirectURL); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> </body> </html>
그렇게 어찌어찌 전달 받은 sub2.jsp는 해당 정보를 이용해 사용자의 정보를 다음 코드를 통해 출력하게 됩니다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String name = request.getParameter("name"); int age = Integer.parseInt(request.getParameter("age")); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h1>정보가 정상적으로 저장되었습니다.</h1> <p>사용자님의 아이디는 <%=name%> 입니다.</p> <p>사용자님의 나이는 <%=age%> 입니다.</p> </body> </html>
이러한 데이터 전송 방식은 정보를 클라이언트와 단순히 페이지를 보여주는 서버가 직접적으로 주고 받는 1:1 방식에는 유용하나, 서버가 페이지를 보여주는 것이 아닌, 서버 본연의 역할 (db나 다른 객체를 만드는 작업)을 수행하는 경우 매우 비효율적이기 때문에, 이럴 경우 사용할 수 있는 옵션이 바로 RequestDispatcher 객체의 메서드인 forward 것이죠.
RequestDispatcher 객체의 메서드인 forward로 정보를 전송하게 되면 POST 방식에서도 효과적으로 정보를 전송할 수 있는데요. 사용자에게 입력 받는 http 요청 양식을 post 방식으로 지정했다고 하고 다음과 같이 sub1.jsp의 코드를 다음과 같이 작성해 보겠습니다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% request.setCharacterEncoding("UTF-8"); String name = (String) pageContext.getAttribute("name"); int age = Integer.parseInt((String) pageContext.getAttribute("age")); // RequestDispatcher를 사용하여 sub2.jsp로 요청을 포워딩 RequestDispatcher dispatcher = request.getRequestDispatcher("sub2.jsp"); request.setAttribute("name", name); request.setAttribute("age", age); dispatcher.forward(request, response); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> </body> </html>
어떻습니까? request의 sendRedirect 메서드보다 간결하고 더 깔끔하게 데이터를 보낼 수 있지 않습니까? 하지만 이러한 데이터 전송도 결국 request의 정보 범위 (하나의 요청에만 유효)의 한계 때문에 사용자로부터 받은 중요한 데이터들은 결국 session에 보관을 하여 sendRedirect와 함꼐 사용하는 편이 좀 더 나은 선택지이며, 기본 검색과 같은 역할에는 request(pageContext)를 주로 사용하게 됩니다.
참고로 위의 코드처럼 전송할 때 포워딩을 이용하는 방법도 존재하는데, 이때 request 객체에 속성과 값을 설정했다면, 전달 받은 쪽에서는 굳이 getAttribute 메서드를 쓰지 않고도 EL 표기법으로 아래와 같이 접근이 가능합니다.
<%@ 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>사용자 정보</h1>
<p>name : ${name} </p>
<p>age : ${age} </p>
</body>
</html>
session은 앞서 소개한 session 섹션에서도 말씀 드렸듯이, 고객의 주요 정보를 유효 기간 내에 저장하는 용도로 사용한다고 했는데요. 그래서 주요 정보는 보통 session으로 저장을 하는 작업이 대부분인 만큼 사용자의 정보를 받은 뒤 session에 저장한 후 filter 작업을 거쳐 제공 세션과 입력 값이 같을 경우와 다를 경우를 각각 처리하는 용도로 사용이 가능합니다.
특히 session을 사용하면 get이든 post 방식이든 get 방식의 쿼리 스트림을 사용하여 정보를 전송하는대에 국한 되어있던 sendRedirection 방법을 좀 더 유연하게 사용할 수 있게 되기에, session과 sendRedirection 조합은 궁합이 잘 맞는 페이지 정보 전달 기술이라고 할 수 있겠습니다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String name = request.getParameter("name"); String age = request.getParameter("age"); session = request.getSession(); session.setAttribute("name", name); session.setAttribute("age", age); response.sendRedirect("sub2.jsp"); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> </body> </html>
특히 request의 범위는 클라이언트의 1회 요청에만 유효한 반면, session은 정해진 유효기간 내라면 어플리케이션 내에서 어느 페이지든 유효하기에 그 쓰임새가 더 넓다고 할 수 있겠죠.
참고로 EL (${})로 접근할때에 각 객체의 속성 이름이 중복되는 경우 접근 우선 순위는 페이지 컨텍스트 => request => session => application 순이라고 합니다.