JSP에서 페이지를 이동하는 방법으로는 크게 네 가지가 있다. 우선 잘 알고 있는 자바스크립트를 이용한 방법이다. window.open, location.href, location.replace 등을 이용한다.
두 번째로 META 태그를 이용하는 것인데 나중에 따로 알아보겠다.
이번 글에서는 세 번째와 네 번째 방법을 알아볼 것이다. 바로 forward 방식과 redirect 방식이다. 두 가지 방식은 비슷한 것 같지만 큰 차이를 가진다.
우선 포워드 방식은 request에 담긴 값이 유효하다. 페이지를 이동해도 첫 페이지에서 받아온 request나 response가 이동한 페이지에서도 그 값이 유효하다.
또한 이동된 URL이 화면에 보이지 않아 사용자는 페이지가 이동했는지 알 수 없다. (페이지는 분명 이동했음에도 주소창에는 기존 페이지의 주소가 그대로 찍혀 나온다.)
그림을 통해 살펴보면, 클라이언트의 요청이 정보를 받는 url1으로 들어오고, url1에서 forward방식을 이용해 url2로 사용자의 데이터를 보내게 되면, 그 정보가 유지된 채로 url2에 도착하여, 사용자에게 응답하게 된다. 요지는 데이터가 계속해서 유지된다는 것이다.
포워드를 작성하는 방법으로는 두 가지가 있다.
- <jsp:forward page="이동할 페이지/>; // 액션태그 사용
- pageContext.forward("이동할 페이지"); // 내장객체 사용
우선 webapp 내부에 정보를 입력할 페이지와, 입력한 정보를 보내줄 페이지를 제작해준다. 정보를 입력할 페이지에서 forward 액션태그와, 파라미터를 받아주는 액션태그, <jsp:param / >을 함께 사용해주었다.
받아주는 페이지에서는 JSP태그 내에 request.getParameter(name값); 으로 값을 받아주면 된다.
form태그를 제작하여 회원 정보의 유효성을 검사하는 페이지를 제작한다.
- form태그에서 정보를 받아 검사한다.
- action 페이지로 보내어 유저의 이름과 아이디를 확인하고,
(DB가 있다면 여기서 DB와의 대조작업을 거친다)- forward 내장 객체를 사용하여 마지막 결과창에 결과를 띄워줄 것이다.
위와 같은 HTML에서, 자바스크립트를 이용하여 유효성 검사를 한다.
유효성 검사에서 통과한 사용자의 정보는 form action="이동할 페이지" 에 명시된 페이지로 향한다.
두 번째 페이지에서, 사용자의 정보는 값이 담긴 키(username, userid)를 request.getParameter(""); 에 담에 두 번째 페이지에서 따로 정의한 변수에 담아준다. 만약 DB에서 자료를 찾아야 한다면, 해당 페이지에서 변받아온 데이터를 변수로 저장한 후, 저장한 변수와 DB에 담겨있는 정보를 비교한다. 이후 forward 내장객체를 이용한 방식으로 pageContext.forward(""); 세 번째 결과창으로 넘겨준다.
마지막 결과창에서는 request.getParameter("") 구문을 이용하여 2페이지에서 담은 변수의 정보를 꺼내어 jsp태그에 담아 사용한다.
주소창에 사용자가 입력한 request 값이 전부 담겨있다. 또한 페이지도 2번 페이지에서 3번 페이지로 이동했음에도, 주소창에서 확인할 수 없다.
클라이언트가 새로 페이지를 요청한 것과 같은 방식으로 페이지가 이동된다. 페이지가 이동될 때 이전 페이지에서 저장되었던 request나 response가 유지되지 않고 새로 만들어진다. 또한 이동된 URL로 주소창에 새롭게 나타나게된다.
그림을 통해 redirect방식을 살펴보자. 클라이언트가 url1에게 데이터를 보내게되면, url1은 url2로 정보를 보내는게 아니라, 다시 클라이언트에게 redirect로 응답하게 된다. 클라이언트의 로컬pc에선 받아온 redirect response를 다시 url2로 request2 하게 되며, 여기서 첫 번째 request1에서 보냈던 데이터는 전부 날아가게된다.
url2에선 마지막으로 클라이언트에게 response하여 페이지에 정보를 표시해주는데, request로 보냈던 정보는 전부 날아간 상태이게 된다.
만약 쇼핑몰에서 사용자가 상품 결제 버튼을 누른 직후, 결제 완료 화면이 사용자에게 보여져야하는 상황이라고 가정해보자. 이 때 forward 방식을 사용하게 되면, 사용자의 아이디나 계좌번호, 비밀번호 등이 모두 url에 담겨 결제 완료 화면으로 보내질것이다. 이는 보안상 좋은 방법이 아니다. 그렇기 때문에 사용자의 개인정보를 모두 날린 이후 결제 화면을 띄워줘야 하는 경우에 redirect방식을 사용한다.
만약 redirect를 사용하면서도, 사용자의 데이터를 살리고 싶다면 request가 아니라 session을 이용하여 정보를 담아주면 된다. 이는 뒤에서 좀 더 자세히 설명하도록 하겠다.
response.sendRedirect("이동할 페이지");
redirect 사용 예시를 확인하기 전에, 우선 선택한 요소의 속성값을 정해주는 .setAttribute(); 메소드에 대해 알아봐야한다.
.setAttribute()메소드는 선택한 요소(element)의 속성(attribute)값을 정한다. setAttribute(String name, Object value); 의 형태로 사용하고, getAttribute(String name); 로 값을 받아올 수 있다. 중요한 점은, 앞의 파라미터에는 객체명을, 뒤의 파라미터에는 그 값을 적어준다는 점이다.
그렇다면 setAttribute를 이용하여 아까 살펴봤던 forward방식으로 정보를 넘겨보자.
우선 간단하게 유저의 아이디와 이름 비밀번호를 변수에 할당한다. 그 뒤, request.setAttribute(); 를 이용하여 변수에 담긴 정보를 임의로 정한 속성 이름에 담아준다. 그 뒤, forward 방식으로 정보를 넘겨줄 페이지를 작성한다.
String userid_ = "java"; String userpw_ = "1234"; String username_ = "김자바"; // 속성이름을 임의로 지정하고, 그 뒤에 값이 담긴 변수를 속성의 값으로 넣어준다. request.setAttribute("idParam", userid_); request.setAttribute("pwParam", userpw_); request.setAttribute("nameParam", username_); pageContext.forward("practice2.jsp");
받아오는 페이지에선, getAttribute로 정보를 받아온다. 해당 정보들을 다시 2번째 페이지에서 String 변수로 받아주는데, 받아온 정보들은 object타입으로 들어오기 때문에 String 타입으로 형변환을 걸어준다. 이후 태그에 해당 변수를 넣어주면 첫 페이지에서 설정한 값들을 확인할 수 있게 된다.
String userid = (String)request.getAttribute("idParam"); String userpw = (String)request.getAttribute("pwParam"); String username = (String)request.getAttribute("nameParam"); 아아디 : <%=userid><br> 비밀번호 : <%=userpw><br> 이름 : <%=username><br>
이처럼 request를 이용하여 데이터를 담게되면, 변수가 요청을 받아 웹 브라우저에게 응답할 때 까지 유지된다. 하지만 redirect 방식은 브라우저 별로 변수가 달라지기 때문에, 브라우저 별로 변수가 따로 관리 될 수 있도록 속성의 scope를 달리해줘야 한다. 여기서 session이 등장한다. session은 request와 달리 브라우저별로 변수가 관리되기 때문에 redirect를 사용할 수 있다.
forward 방식 1.
(request 객체가 유지되기 때문에 getParameter로 바로 데이터 꺼내서 사용 가능)
pageContext.forward("이동할 페이지");
<%=request.getParameter("데이터 키");%>forward 방식 2.
(물론 당연하게도 setAttribute -> getAttribute 방식도 사용 가능)
request.setAttribute("데이터키");
pageContext.forward("이동할 페이지");
<%=request.getAttribute("데이터키");%>redirect 방식
(속성의 scope를 session으로 잡아준다. 이후 setAttr -> getAttr 로 데이터를 전달한다.)
session.setAttribute("데이터 키");
response.sendRedirect("이동할 페이지);
<%=session.getAttribute("데이터 키");
객체 배열에 담긴 정보를 request를 이용하여 결과 페이지로 넘길 수 있다.
- 간단한 객체를 생성하고 생성자를 만들어준다.
- 데이터를 받아주는 페이지에서 객체배열을 생성한다.
- request.setAttribute();를 통해 데이터를 담아준다.
- forward 방식으로 데이터를 넘겨준다.
- request.getAttribute();로 출력해준다.
간단한 클래스를 만들고, 파라미터가 있는 생성자를 만들어준다.
public class User{ public String userid; public String username; public int age; public User(String userid, String username, int age){ super(); this.userid = userid; this.username = username; this.age = age; }
jsp파일을 하나 만들고, 내부에 해당 클래스의 객체배열을 만들어준다. 그 이후, 데이터를 request.setAttribute(); 내부에 통째로 object형식으로 담아준 후, forward 방식으로 페이지 이동시켜준다.
<% User[] arrUser = { new User("토트넘", "손흥민", 29), new User("나폴리", "김민재", 25), new User("마인츠", "이재성", 30) }; request.setAttribute("users", arrUser); pageContext.forward("이동할 페이지"); %>
이동할 페이지에서 객체배열을 꺼내와준다. 이 때 object 배열이기 때문에 해당 객체배열로 형변환을 시켜준다. 이후 for 문을 통해 해당 객체배열의 데이터를 꺼내와준다.
<% User[] arrUser = (User[])request.getAttribute("users") if(int i = 0; i < arrUser.length; i++){ out.println(arrUser[i].userid); out.println(arrUser[i].username); out.println(arrUser[i].age + "<br>"); } %>
ArrayList를 이용하여 데이터를 날려줄 수도 있다.
- ArrayList를 생성해준다.
- ArrayList안에 인자들을 add해준다.
- session.setAttribute(); 를 통해 데이터를 담아준다.
- redirect 방식으로 페이지 이동시켜준다.
- 이동한 페이지에서 session.getAttribute();로 출력해준다.
ArrayList를 String 타입으로 생성한 뒤, 인자를 추가해주었다.
ArrayList<String> datas = new ArrayList<>(); datas.add("Hello"); datas.add("JSP"); datas.add("너무"); datas.add("즐거워요");
이후 session.setAttribute(); 안에 생성한 ArrayList를 통째로 담아준다. 이후 redirect 방식으로 결과 페이지로 쏴준다.
session.Attribute("msg", datas); // msg라는 키값에 datas를 통째로 object 형태로 담아준다. response.sendRedirect("이동할 페이지");
이동할 페이지에서 첫 페이지에서 msg라는 키값에 담아 넘겨준 데이터를 받아온다. session에서 getAttribute()로 꺼내오는데, object 타입이기 때문에 ArrayList로 형변환 해준다.
ArrayList<String> datas = (ArrayList)session.getAttribute("msg");
이후 for문으로 데이터를 꺼내오면 된다.
for(int i = 0; i < datas.size(); i++{ out.println(datas.get(i) + "<br>"); }