RequestDispatcher는 클라이언트로부터 최초에 들어온 요청을 JSP/Servlet 내에서 원하는 자원으로 요청을 넘기는(보내는) 역할을 수행하거나, 특정 자원에 처리를 요청하고 처리 결과를 얻어오는 기능을 수행하는 클래스입니다. 즉 /a.jsp 로 들어온 요청을 /a.jsp 내에서 RequestDispatcher를 사용하여 b.jsp로 요청을 보낼 수 있습니다. 또는 a.jsp에서 b.jsp로 처리를 요청하고 b.jsp에서 처리한 결과 내용을 a.jsp의 결과에 포함시킬 수 있습니다.
요청을 보내는 방법으로는 RequestDispatcher#forward( )와 RequestDispatcher#include( ) 두 가지 방법이 있습니다.
RequestDispatcher가 있는 이유. HttpServletResponse#sendRedirect() 와의 차이점
HttpServletResponse를 사용하면 sendRedirect( ) 메서드를 이용하여 지정한 경로로 제어를 이동시킬 수 있습니다. 그러나 sendRedirect( )는 HTTP 리다이렉션을 이용하기 때문에 하나의 요청 범위 안에서 처리를 하는것이 아니라 브라우저에게 Response 후 브라우저측에서 지정받은 요청 경로로 다시 재요청을 하는 방식이기에 두 번의 HTTP 트랜잭션이 발생하며, 서버측에서는 최초에 받은 요청중에 처리한 내용을 리다이렉트 된 요청안에서 공유할 수 없는 문제가 있습니다.
물론 sendRedirect( ) 에서도 쿠키나 세션등을 이용해 특정 상태를 유지하여 공유할 수는 있겠으나, 상황에 따라 제한적일 수 있으며, 코드 레벨 에서의 알고리즘 등을 곧바로 이어가는데에도 한계가 있기 때문에 좋은 방법이라고 할 수는 없을것입니다.
그대신 HttpServletResponse를 통해 리다이렉트 하는 방식은 현재 어플리케이션 이외에 다른 자원의 경로를 요청할 수 있는 반면 RequestDispatcher는 현재 처리중인 서블릿이 속해 있는 웹 어플리케이션 범위 내에서만 요청을 제어할 수 있습니다.
RequestDispatcher 생성(얻는) 방법
RequestDispatcher는 ServletContext나 ServletRequest 클래스에서 제공하는 팩토리 메서드(Factory Method)를 통해 얻을 수 있습니다. 팩토리 메서드라는 용어에 대해서는 이 글의 범위 밖이므로 디자인 패턴을 참고해 주시기 바랍니다.
ServletContext을 통해서 얻는 법
서블릿 클래스에서 ServletContext를 사용하여 RequestDispatcher를 얻을 수 있습니다.
호출 대상을 web.xml에 지정한 서블릿 이름(<servlet-name>)으로 지정하는 방법
서블릿 클래스에서는 service() 메서드나 doGet() doPost() 등에서 ServletRequest의 하위 클래스인 HttpServletRequest를 매개변수로 받기 때문에 이것을 이용하여 RequestDispatcher를 얻을 수 있습니다. HttpServletRequest에서는 URL 경로를 통해서 대상을 지정하는 한가지 방법만을 제공합니다. 그러나 ServletContext를 통해서 대상을 지정할때와는 다르게 절대경로 및 상대경로 모두 지정이 가능합니다. JSP 페이지에서도 ServletRequest의 인스턴스인 request 기본객체가 있으므로 쉽게 얻을 수 있습니다.
forward() 메서드는 대상 자원으로 제어를 넘기는 역할을 합니다. 브라우저에서 /a.jsp로 요청했을 때 /a.jsp에서 forward()를 실행하여 /b.jsp로 제어를 넘길 수 있습니다. 제어를 넘겨받은 /b.jsp는 처리 결과를 최종적으로 브라우저에게 출력합니다. 브라우저 입장에서는 /a.jsp를 요청했지만 받은 결과는 /b.jsp의 결과입니다. 이때 HTTP 리다이렉트 방식과는 달리 하나의 HTTP 요청(Request) 범위 안에서 동작이 이루어집니다.
forward( ) 메서드 실습
forward( )는 특정 자원으로 제어를 넘긴다고 했는데 대상 자원은 Servlet 또는 JSP 페이지가 됩니다(JSP도 결국은 최종적으로 서블릿이므로). 여기서는 서블릿으로 실습을 진행하지만 JSP페이지에서도 application이나 request 내장객체를 통해서 RequestDispatcher 를 얻어 forward( )를 실행할 수 있습니다. 다음과 같이 DispatchTest(/dispatch) -> HelloServlet(/hello) 로 forward( )를 실행하는식으로 진행합니다.
DispatchTest 서블릿이고 URL은 /dispatch로 맵핑합니다. RequestDispatcher를 통해 /hello자원으로 forward( )를 실행하는데 /hello는 HelloServlet입니다. 이때 request에 사전처리로 name 속성에 "dololak"을 담았습니다. forward( )는 제어가 넘어간 이후 다지 이전의 자원으로 제어가 돌아가지 않으므로 호출하는쪽의 처리를 모두 완료한 후 제어를 넘겨야 합니다. forward( ) 실행시에는 HttpServletRequest와 HttpServletResponse 객체를 같이 넘겨주기 때문에 호출한 쪽과 호출당한 쪽에서 이 두 가지의 객체를 공유합니다.
댓글