본문 바로가기

Backend/JSP & SERVLET

[JSP] 페이지 이동 (redirect, forward)

 

 


JSP 에서 redirect 와 forward 로 페이지 이동하기


 

 

1. redirect 방식


response.sendRedirect("main.jsp");

// name 변수에 HongGilDong, id 변수에 honghong 값을 담아 전달
response.sendRedirect("063_LoginOk.jsp?name=HongGilDong&id=honghong");

 

값을 받기 위해 사용했던 request 객체가 웹 브라우저에서 서버로 전송된 요청을 갖고 있었다면, response 객체는 서버에서 사용자의 웹 브라우저에 전송할 정보를 담고 있다. response 객체의 메소드 중에서도 response.sendRedirect() 는 현재 페이지에서 다른 페이지로 이동하는 명령이다. String 으로 작성된 url 로 이동하며, url 에 ? 와 & 를 사용하여 변수 이름에 해당하는 값을 전달할 수도 있다.

 

redirect 를 지시한 JSP 페이지가 있을 경우 웹 브라우저는 실질적으로 두 번 요청하게 된다.

웹 브라우저 (요청보내기) →  a.jsp 
웹 브라우저 ← (b.jsp로 redirect 하라고 지정) ← a.jsp
웹 브라우저 (b.jsp를 요청) → b.jsp

 

위의 예제와 request, response 정의에 따르면

response 객체는 서버에서 사용자의 웹 브라우저로 b.jsp 주소를 전달할 뿐, 웹 브라우저가 서버로 전송할 데이터는 따로 전달하지 않는다. 따라서 쿼리스트링으로 직접 url 에 값을 작성하지 않는 이상 위 명령만으로는 사용자가 서버에 값을 전달할 수 없다. (찾아보니 RedirectAttribute 라는 방법도 있다더라.)

 

 

 

간단한 로그인 폼을 이용해 알아보자.

<form method="post" action="062_Login_do.jsp">
    <label for="id">아이디 : </label>
    <input type="text" id="id" name="id"><br>
    <label for="pwd">암 &nbsp; 호 : </label>
    <input type="password" id="pwd" name="pwd"><br>
    <input type="submit" value="로그인">
</form>

<%
    // 추후 로그인 결과를 나타낼 메시지 변수
    String msg = request.getParameter("msg");
    if(msg != null) out.print("<h3>" + msg + "</h3>");
%>

 

form 에서 submit 버튼을 눌렀을 때 로그인 정보가 서버로 날아가 로그인 처리를 한다면, action 에는 로그인 처리 명령이 담겨있는 클래스 객체 또는 서블릿의 이름을 사용한다. 하지만 아직 서블릿과 백엔드 코딩을 다루지 않았기 때문에 로그인 처리를 JSP 파일에서 실행할 예정이다. 따라서 action 에 로그인 정보(아이디, 비번) 이 전달된 jsp 파일(062_Login_do.jsp)을 작성해줬다.

더보기

로그인 처리 순서

1. 아이디, 비번 입력 후 submit 버튼 클릭

2. action 에 지정된 곳으로 아이디와 비번이 전달돼서 유효한 아이디, 비번인지 검증

3. 검증을 마친 결과(성공 or 아이디 없음 or 패스워드 틀림)을 가지고 결과 페이지로 이동

→ 아이디, 패스워드 검정은 보통 서버 내부에서 실행되는 JAVA 프로그래밍으로 이루어짐 (별도의 java 클래스 생성)

→ 이러한 JAVA 프로그램의 시작을 Serlvet 이라고 함 (외부에는 노출되지 않음)

 

하지만 이 부분을 학습하기 전이기도 하고, 작동 원리를 쉽게 알아보기 위해 jsp 파일을 사용했다.

 


<%-- 최상단에 한글 인코딩을 위한 인코더 임포트 %-->
<%@ page import="java.net.URLEncoder" %>

<%
    String id = request.getParameter("id");
    String pwd = request.getParameter("pwd");
    
    // jsp 문법으로 페이지 이동 : response.sendRedirect();
    if(id.equals("scott") && pwd.equals("tiger")){
        // 전달받은 아이디, 비번이 정확하다면 063_:oginOK.jsp로 이동
        //response.sendRedirect("063_LoginOk.jsp?name=HongGilDong&id=" + id);
        response.sendRedirect("063_LoginOk.jsp?name=" + URLEncoder.encode("홍길동", "UTF-8") + "&id=" + id);
    }else{
        // 아이디 비번 중 하나라도 틀리다면 원래 로그인 폼으로 되돌아 감
        String msg = "";

        if(!id.equals("scott")){
            msg = "해당 아이디가 없습니다.";
        }else if(!pwd.equals("tiger")){
            msg = "비밀번호를 확인하세요.";
        }

        response.sendRedirect("061_LoginForm.jsp?msg=" + URLEncoder.encode(msg, "UTF-8"));
    }
%>

 

action 을 통해 이동한 062_Login_do.jsp 파일이다. 코드를 해석해보자면..

 

 

<%
    String id = request.getParameter("id");
    String pwd = request.getParameter("pwd");
%>

 

jsp 내에 form 으로부터 전달받은 id 와 pwd 를 각각 String 변수에 넣어주었다.

 

 

if(id.equals("scott") && pwd.equals("tiger")){
    // 전달받은 아이디, 비번이 정확하다면 063_:oginOK.jsp로 이동
    response.sendRedirect("063_LoginOk.jsp?name=" + URLEncoder.encode("홍길동", "UTF-8") + "&id=" + id);
}

(데이터베이스에 연결하지 않았으므로 id 와 pwd 를 scott, tiger 이어야 이동하도록 로직을 작성했다.)

 

해당 코드는 아이디, 비밀번호가 정확하다면 "063_LoginOk.jsp" 로 이동하되, name 은 "홍길동"을, id는 받아온 id를 전달하도록 하였다.

 

 

else{
    String msg = "";

    if(!id.equals("scott")){
        msg = "해당 아이디가 없습니다.";
    }else if(!pwd.equals("tiger")){
        msg = "비밀번호를 확인하세요.";
    }

    response.sendRedirect("061_LoginForm.jsp?msg=" + URLEncoder.encode(msg, "UTF-8"));
}

 

만약 아이디, 비밀번호가 정확하지 않다면 msg 변수에 띄울 메시지를 담고, 해당 메시지를 다시 LoginForm 으로 돌아가 띄우도록 했다.

 

 

아이디가 일치하지 않는다면, 로그인 버튼(submit)을 눌렀을 때 062_Login_do.jsp 파일에서 msg 에 "해당 아이디가 없습니다." 라는 문구를 담고 다시 061_LoginForm.jsp 로 돌아와 메시지를 띄우는 것이다.

 

해당 실습에서 이동할 url 뒤에 ? 나 & 로 연결하여 값을 지정해 전달했다. redirect 는 클라이언트가 새로 페이지를 요청한 것과 같은 방식으로 페이지가 이동되기 때문에 request, response 가 유지되지 않는다. 값을 두고 몸만 이동하는 격이다. 따라서 url 뒤에 붙이는 쿼리스트링 방식으로 값을 전달하는 것이다.

 

하나 더 유의해야할 점은 url 전달 시 url 인코딩 방식은 한글 정보를 지원하지 않는다. 따라서 아래와 같이 URLEncoder를 임포트하고 한글 메시지에 URLEncoder.encode() 를 통해 "UTF-8" 형식으로 별도의 처리를 해주어야 한다.

// jsp의 import 문법
<%@ page import="java.net.URLEncoder" %>

// 한글이 전달된다면 URLencorder.encode() 를 통해 한글을 지원하는 UTF-8 로 인코딩하도록 함
response.sendRedirect("061_LoginForm.jsp?msg=" + URLEncoder.encode(msg, "UTF-8"));

 


<%
    String name = request.getParameter("name");
    String id = request.getParameter("id");
%>
<h1><%=name %>(<%=id %>)님이 로그인 하셨습니다.</h1>

 

063_LoginOk.jsp 파일에서 쿼리스트링 방식으로 전달한 값을 getParameter 로 전달받고, 간단한 텍스트를 띄워 확인해본다.

 

 

 

 

2. RequestDispatcher


forward 방식을 알아보기 전 사용되는 객체 RequestDispatcher 에 대해 알아보자.

 

RequestDispatcher rd = request.getRequestDispatcher("main.jsp");
rd.forward(request, response);

 

RequestDispatcher 는 클라이언트로부터 최초에 들어온 요청을 JSP/Servlet 내에서 원하는 자원으로 요청을 넘기거나, 특정 자원에 처리를 요청하고 처리 결과를 얻어오는 기능을 수행하는 클래스다. 

 

RequestDispatcher 는 ServletContext 나 ServletRequest 클래스에서 제공하는 팩토리 메소드(Factory Method)를 통해 얻을 수 있다. 서블릿 클래스에서는 ServletRequest의 하위 클래스인 HttpServletRequest를 매개변수로 받기 받고 있어 해당 매개변수를 이용하면 RequestDispatcher를 얻을 수 있다.

 

HttpServlet 을 상속한다

 

JSP 페이지에서는 ServletRequest 의 인스턴스인 request 기본 객체가 있어 쉽게 얻을 수 있다.

 

 

 

3. forward 방식


forward(request, response)

// RequestDispatcher 객체 생성 + 동시에 목적지 지정
RequestDispatcher rd = request.getRequestDispatcher("main.jsp");
rd.forward(request, response); // 전달할 내용이 담겨있는 request 와 현재 페이지에 같이 존재하는 response 를 갖고 이동

// forward 까지 연결
request.getRequestDispatcher("main.jsp").forward(request, response);

 

forward 방식은 RequestDipatcher 객체에 있는 이동 기능인 forward 메소드를 이용해 데이터를 전달하는 방식이다.

1. request 객체에 있는 attribute 라는 저장 장소에 데이터를 담고

2. RequestDispatcher 객체에  request와 response 를 담아

3. forward 로 보내는 것이다.

* 사용자의 웹브라우저에서 서버로 전송될 request 에는 attribute 에 담은 전송할 데이터들

* 웹 브라우저의 요청에 응답하고 응답의 정보를 가지고 있는 response(요청) 

 

한마디로, 전달할 데이터를 Attribute 에 각 자료의 이름과 값을 같이 저장하고 forward(이동)하면 목적지에 해당 데이터가 같이 이동하는 것이다.

 

request 의 수명은 response.sendRedirect 또는 form 태그의 submit 으로 이동한 페이지까지만이다. 하지만 RequestDispatcher 가 forward 를 하면서 현재 페이지에 있는 request 를 그대로 담아간다면, 현재 페이지에서 수명을 다한 request 가 다음 페이지까지로 수명이 늘어나게 된다.

 

웹 브라우저 → 요청 → a.jsp

                                      ↓ forward 실행 (제어 넘김)

웹 브라우저 ← 출력  ← b.jsp

 

forward 는 웹 브라우저의 요청 이후 바로 지정한 .jps(서블릿 등) 에 제어를 넘겨 처리결과를 볼 수 있다. redirect 는 두번의 요청을 필요로 했다면, forward는 하나의 HTTP 요청 범위 안에서 동작을 할 수 있게 된다

 

 

request.setAttribute()

request 에는 attribute 라는 저장장소가 있다. 

// request.setAttribute("객체명", 객체);
request.setAttribute("name", "홍길동");

 

request.setAttribute 는 HashMap 과 사용이 비슷하다. 전달할 데이터를 (자료의 이름, 값) 의 형태로 저장한다. 위와 같은 형태라면 "홍길동" 이라는 값이 "name" 이라는 이름으로 저장됐다. 

forward 를 사용하면 Attribute 에 넣은 한글이 UTF-8 로 자동 인코딩 되기 때문에 번거로운 처리를 할 필요가 없다.

 

 

request.getAttribute("객체명")

Attribute 에 담긴 값은 getAttribute 로 꺼낸다.

String name = (String)request.getAttribute("name");

 

 getAttribute 의 반환은 Object 형식이다. request 에는 데이터들이 Object 로 들어간다.

앞서 저장한 "홍길동" 이라는 문자열이 저장되는 과정에서 Object 형식으로 저장된 것이다.

 

getAttribute에 지정한 객체명을 넣어 값을 출력한다. String 데이터를 이름으로 지정했다면, 따옴표까지 작성한다. 이렇게 출력된 데이터는 Object 형식이기 때문에, 다른 데이터타입의 변수에 저장하기 위해서는 형변환을 해주어야 한다.

 

 

 

이 모든 과정을 예시를 통해 알아보자.

입장하려면 나이를 입력하세요. <br>
<form action ="072_Forward_do.jsp">
    아이디 <input type="text" name="userid"><br/>
    나이 <input type="text" name="age"><br/>
    <input type="submit" value="입장">
</form>

 

간단하게 값을 입력 받을 form 이다. userid, age 를 받고 있다.

입장 버튼을 누르면 072_Forward_do.jsp 파일로 이동한다.

 


<%
    String userid = request.getParameter("userid");
    int age = Integer.parseInt(request.getParameter("age"));

    if( age <= 19 ){
        // 20세 미만은 입장이 불가능합니다. 라고 경고 문구를 보여주고 되돌아감
%>
        <script type="text/JavaScript">
            alert("20세 미만은 입장이 불가능합니다.");
            location.href='071_ForwardForm.jsp';
            //history.go(-1);
        </script>
<%	
    }else{
        // 성인 인증이 되어 이동할 페이지 : 073_ForwardResult.jsp
        request.setAttribute("userid", userid);
        request.setAttribute("age", age);
        request.setAttribute("name", "홍길동"); // 자동 url 인코딩

        RequestDispatcher rd = request.getRequestDispatcher("073_ForwardResult.jsp");
        rd.forward(request, response);
    }
%>

 

072_Forward.jsp 파일이다.

 

 

<%
    String userid = request.getParameter("userid");
    int age = Integer.parseInt(request.getParameter("age"));
%>

 

getParameter 를 통해 form 에서 입력받은 userid 와 age를 입력 받는다.

 

 

    if( age <= 19 ){
        // 20세 미만은 입장이 불가능합니다. 라고 경고 문구를 보여주고 되돌아감
%>
    <script type="text/JavaScript">
        alert("20세 미만은 입장이 불가능합니다.");
        location.href='071_ForwardForm.jsp';
        //history.go(-1);
    </script>
<%

 

만약 입력받은 age 가 19 이하라면 JavaScript 를 통해 입장이 불가능하다는 알림과 함께 이전 페이지인 071_ForwardForm.jsp 로 돌아간다. 해당 코드는 history.go(-1); 로도 구현 가능하다.

 

 

<%	
    }else{
        // 성인 인증이 되어 이동할 페이지 : 073_ForwardResult.jsp
        request.setAttribute("userid", userid);
        request.setAttribute("age", age);
        request.setAttribute("name", "홍길동"); // 자동 url 인코딩

        RequestDispatcher rd = request.getRequestDispatcher("073_ForwardResult.jsp");
        rd.forward(request, response);
    }
%>

 

age 가 20 이상이라면, 입력받은 userid, age, 임의로 "홍길동" 이라는 이름을 setAttribute 에 저장한다.

이후 경로를 "073_ForwardResult.jsp" 로 지정하고 저장한 객체와 요청 정보를 지정한 경로로 forward 해준다.

 


<%
    int age = (int)request.getAttribute("age");
    String name = (String)request.getAttribute("name");
    String userid = (String)request.getAttribute("userid");
%>
    <h1>forward 방식으로 이동된 페이지</h1>
    <h2>나이 : <%=age %></h2>
    <h2>이름 : <%=name %></h2>
    <h2>userid : <%=userid %></h2>

 

073_ForwardResult.jsp 파일이다.

 

 

<%
    // getAttribute 의 반환은 Object
    // request 에 Object 로 들어감 -> 강제 형변환 필요
    int age = (int)request.getAttribute("age");
    String name = (String)request.getAttribute("name");
    String userid = (String)request.getAttribute("userid");
%>

 

Attribute 에 들어간 값은 Object 이기 때문에 값을 추출하는 과정에서 형변환을 해주었다.

 

<h1>forward 방식으로 이동된 페이지</h1>
<h2>나이 : <%=age %></h2>
<h2>이름 : <%=name %></h2>
<h2>userid : <%=userid %></h2>

 (JSP 로 선언한 변수는 JSP 형식으로 데이터를 불러온다. )

 

 

 


참고자료

https://dololak.tistory.com/502