Hayden's Archive

[Servlet] 페이지 이동(Navigation) : Forward / Include / Redirect 본문

Study/Java & Kotlin

[Servlet] 페이지 이동(Navigation) : Forward / Include / Redirect

_hayden 2020. 6. 9. 21:34

페이지 이동을 네비게이션이라고 함. 

Web 페이지 이동
1. Forwarding(포워딩. 앞으로 간다. 제일 많이 씀. 거의 90%) 
2. Redirect 


Forwarding 방식

- 요청하고 응답하고, 요청하고 응답하면 첫번째 요청이랑 두번째 요청이 전혀 관련 없는 남남. 이걸 Stateless한 protocol라고 함.

- 원래는 요청 2번, 응답 2번 해야 하는 것을 요청 1번, 응답 1번으로 줄일 수 있음.

- 포워딩을 하게 되면 응답하지 않고 서버상에서 다이렉트로 이동함.

- 그렇게 되면 클라이언트로부터 받은 폼값을 그대로 가져가게 됨. ServletRequest에 저장한 객체도 없어지지 않고 JSP로 넘어가서도 쓸 수 있음. 그리고 나서 응답하면 죽으니까 메모리 효율성 뛰어남. 이 경우에는 HttpSession, ServletContext 안 써도 됨. ( 관련 포스팅 : Attribute https://hayden-archive.tistory.com/208 )

 

Forwarding 관련 메소드

javax.servlet - Interfaces - ServletRequest 

javax.servlet - Interfaces - ServletContext

- getRequestDispatcher()가 있는데 RequestDispatcher 타입을 리턴함  

- getRequestDispatcher() 메소드는 ServletRequest와 ServletContext 둘 다에 있음. 동일한 기능이 서로 다른 객체에 있을 때는 반드시 눈여겨 봐야 한다. 대부분 차이점이 있다.

ServletRequest.getRequestDispatcher(path); //path에 상대경로만 들어갈 수 있음.
ServletContext.getRequestDispatcher(path); //path에 절대경로만 들어갈 수 있음.

- 응답하고 없어지면 좋을 때 ServletRequest의 getRequestDispatcher를 사용하는 것이 적절. (이동하는 것과 정보 건네는 건 다름. 이동하는 건 페이지를 연결되겠다. 정보의 흐름은 Attribute를 이용하는 것 맞음)

 

javax.servlet - Interfaces - RequestDispatcher

메소드로 forward()와 include()가 있음. forward(ServletRequest request, ServletResponse response) 

 

Forwarding 코드 작성

1. 이동하려고 하는 페이지를 넣고, RequestDispatcher 객체를 리턴받는다.

RequestDispatcher rdp = request.getRequestDispatcher("viewMember.jsp");

2. 다이렉트로 이동하는데, 이 때 request와 response를 가지고 간다. 요청정보, 응답정보 모든 전권을 가지고 이동한다.  
- 명의가 서블릿 명의로 가기 때문에 응답은 JSP가 하더라도 주소가 서블릿 주소로 뜬다.

rdp.forward(request, response);

 

-> 1번, 2번 통합

request.getRequestDispatcher("view.jsp").forward(request, response)

 


Include 방식

javax.servlet - Interfaces - RequestDispatcher에 보면 forward() 메소드와 함께 include() 메소드가 있다.  forward()는 서블릿이 JSP로 모든 전권을 넘기고 JSP가 응답을 한다면, include()는 서블릿을 포함하여 JSP가 응답한다.

 

1. forward() 메소드를 사용했을 경우

PrintWriter out = response.getWriter();
out.println("forward님이 카페에 입장하셨습니다..<p>"); //출력 안 됨
request.getRequestDispatcher("viewMember.jsp").forward(request, response);
out.println("페이지 이동 시켰습니다... forward"); //출력 안 됨

JSP만 응답함

 

2. include() 메소드를 사용했을 경우

PrintWriter out = response.getWriter();
out.println("include님이 카페에 입장하셨습니다..<p>"); //출력됨
request.getRequestDispatcher("viewMember.jsp").include(request, response);
out.println("페이지 이동 시켰습니다... include"); //출력됨

서블릿까지 포함하여 JSP가 응답함.

 


Redirect 방식

방향을 다시 잡는다. 원래 가던 방향으로 가는 게 아니라 다시 다른 방향으로 되돌렸다.

- redirect 기능은 응답하면서 방향을 틀기 때문에 response에 있음.

- 웹 브라우저 header의 방향을 찾는 것이므로 ServletResponse에는 없음. ( header 관련 포스팅 : https://hayden-archive.tistory.com/204#request )

- sendRedirect() 메소드는 HttpServletResponse에 있음. ServletResponse로부터 상속받은 것 아니고 http에 특화된 기능.

javax.servlet.http - Interfaces - HttpServletResponse

 

- sendRedirect() 쓰면 Attribute 중에서 ServletRequest 쓰면 안 됨. 응답해서 죽어버림. HttpSession를 써야 함.

 


Forward와 Redirect의 차이점

- Forward

: 요청이 들어왔을 때 서버상에서 바로 다른 컴포넌트, 다른 자원으로(서블릿->JSP) 이동하는 것(브라우저 안 거침)

: 포워드같은 서버사이드에서만 이동할 수 있음.

- Redirect

: 요청이 들어왔을 때 일단 응답하고 다시 요청. 브라우저 거치고 가는 것. 브라우저를 거치면 어떤 서버사이드이든 다 연결될 수 있음.

: 리다이렉트는 다른 서버사이드로도 이동할 수 있음. 컨테이너가 달라도 이동 가능. 완전히 다른 서버사이드의 리소스에 접근 가능.

 

- 거의 대부분의 페이지가 포워딩을 씀. 그렇다면 신경 써야 할 부분은 언제 리다이렉트를 하는가?

정적인 문서로 가야 하는 경우 : 포워딩은 컨테이너 안에서 이루어짐. 동적인 프로그램만 해당된다! 정적인 문서로 이동할 때는 컨테이너 안에서 갈 수 없음. 컨테이너 밖에 있는 웹 서버로 가야 함!! 즉, 브라우저를 거쳐야 하는 경우 == 정적인 문서로 가야 하는 경우.

에러 페이지 404 : 에러 페이지 핸들링은 리다이렉트로 해야 함. 에러 페이지는 전부 다 정적인 문서이기 때문

- ServletRequest에 바인딩을 해야 할 경우 포워딩을 써야 한다.