리다이렉트(Redirect) 와 포워드(Forward)의 차이

리다이렉트(Redirect) 와 포워드(Forward)의 차이

※ 해당 글은 필자 개인적인 학습을 목적으로 작성했으며 잘못된 부분이 있으면 아낌없이 지적해주시기 바랍니다. :)

웹 개발을 하다보면 리다이렉트(Redirect)와 포워드(Forward)를 많이 사용하게 된다. 처음 웹 개발을 할 때 리다이렉트와 포워드를 혼용해서 사용하여 발생한 오류 때문에 장시간 시간을 소비한 적이 있기에 이번 포스팅을 통해서 정리하고자 한다. 이번 포스팅을 위해 부스트코스 "웹프로그래밍(풀스택)" 강의 내용을 참고하였다.

리다이렉트(Redirect)란?

리다이렉트 역시 HTTP 프로토콜로 정해진 규칙인데, 리다이렉트를 이용하면 서버는 클라이언트의 요청(클라이언트 → 서버)에 대해서 특정 URL(처음 클라이언트가 요청했던 URL이 아닌 다른 URL)로 이동하도록 응답(서버 → 클라이언트)한다. 예를 들어 Java 서블릿(Servlet)이나 JSP는 리다이렉트하기 위해서 HttpServletResponse 클래스의 sendRedirect() 메소드를 사용하며 Spring Web MVC Controller에서는 return 반환값으로 "redirect:URL명"을 할당하면 된다.

jsp 에서 리다이렉트 하는 방법 예시

리다이렉트 시 서버는 처음 클라이언트의 요청에 대해 HTTP 상태코드 302로 응답하는데 이때 헤더 내 Location 값에 특정 URL을 추가하고 클라이언트는 서버의 리다이렉션 응답을 받게 되면 헤더 내 Location에 포함된 해당 URL로 재요청을 보내게 된다. 이때 당초 요청을 보냈던 사용자의 브라우저의 주소창은 처음 요청을 보냈던 URL이 아닌 새로운 URL로 바뀌게 된다.

브라우저에서 서버의 리다이렉트 응답을 확인하는 방법

※ 실제로는 리다이렉트의 유형에 따라 응답코드는 "3xx"로 다양하지만 여기서는 응답코드가 "302 Found"인 경우에 대해서 다뤘다.

포워드(Forward)란?

forward는 "전달하다"라는 의미를 가지고 있는데, 이 의미는 실제 웹에서도 적용된다. 포워드는 서버가 클라이언트의 요청을 받으면 이를 다른 서버에게 전달하는 것이다. 예를 들어, 아래와 같이 Servlet1과 Servlet2가 있다고 생각해보자. 만약 웹 브라우저에서 Servlet1에게 요청을 보내면 Servlet1은 이 요청을 처리한 후, 그 결과를 HttpServletRequest에 저장하고 결과가 저장된 HttpServletRequest와 응답을 위한 HttpServletResponse를 같은 웹 어플리케이션 안에 있는 Servlet2에게 전달하는 것이다. 이때 Servlet2는 Servlet1으로 부터 받은 HttpServletRequest와 HttpServletResponse를 이용하여 요청을 처리한 후 웹 브라우저에게 결과를 전송한다. 웹 브라우저 입장에서는 Servlet1에게 요청을 보냈지만 응답은 Servlet2로부터 받는 것이다.

클라이언트는 서블릿1에 요청을 보냈지만 서블릿2로부터 응답을 받는다.

예를 들어 Java 서블릿(Servlet)에서 포워드하기 위해서는 RequestDispatcher 클래스의 getRequestDispatcher() 메서드와 forward() 메서드를 사용하며 Spring Web MVC Controller에서는 return 반환값으로 "URL명"을 할당하면 된다.

서블릿에서 또 다른 서블릿(next)로 포워드 하는 방법 예시

리다이렉트와 포워드의 차이

이제 리다이렉트와 포워드의 차이에 대해서 알아보기 위해 사용자 브라우저가 서버(예시 : URL A)에 요청을 보내고 또 다른 서버(예시 : URL B)가 있다고 가정해보자.

우선 표면적으로 리다이렉트는 사용자 브라우저 주소창에 처음 요청을 보냈던 서버의 URL A가 아닌 다른 서버의 URL B로 바뀌게 된다. 왜냐하면 디라이렉트의 경우 사용자 브라우저가 처음 보낸 요청(A)에 대해 서버는 헤더 내 Location에 다른 서버의 URL B를 포함시켜 응답(302)하고 브라우저는 다시 이 URL B로 요청을 보내기 때문이다. 즉 사용자 브라우저 주소창에는 A가 아니라 B가 입력되어있는 것이다. 반면에 포워드는 사용자 브라우저 주소창에 처음 보냈던 URL A가 그대로 입력되어있다. 포워드는 단지 다른 서버(URL B)가 브라우저에게 응답하는 것일뿐 브라우저는 서버(URL A)에 한번만 요청한 것이다.

정리하자면 포워드는 하나의 요청과 응답 객체를 유지한 채 작업이 이루어지지만, 리다이렉트는 하나의 서블릿의 요청과 응답이 끝나면 새로운 요청과 응답이 시작되면서 작업이 끝난다. 포워드는 하나의 요청과 응답 객체를 사용하고 리다이렉트는 여러 개의 요청과 응답 객체를 사용하는 것이다.

리다이렉트와 포워드의 용도

그렇다면 리다이렉트는 언제 사용될까? 예를 들어 사용자가 어떤 웹 사이트에서 영화를 예매했다고 가정해보자. 이때 서버와 브라우저는 POST 통신한다. 사용자가 예매정보를 입력하고 예매 버튼을 클릭한 경우 사용자의 입력 정보가 서버로 전달될 것이다. 서버는 이 입력정보를 받기전 사용자가 로그인을 했는지(권한이 있는지), 사용자가 보낸 데이터가 유효한지 등을 검사하고나서 데이터를 처리할텐데, 서버가 데이터 처리만하고 브라우저에 리다이렉트나 포워드 응답을 하지않았다면 아직까지 사용자 브라우저는 예매 화면에 머물러있는 상태이다.

만일 서버에서 데이터 처리를 못하고 브라우저에 오류를 반환했더라면 다행인데 정상적으로 서버에서 데이터 처리가 이루어진 이후에 사용자가 새로고침을 누른다면 서버에 방금 전 POST 요청이 한 번 더 전달된다. 이는 새로고침 시 사용자 브라우저가 서버에 처음 POST 요청했던 행위를 기억하여 다시 한 번 서버에 POST 요청하기 때문이다.(이 부분이 이해 안된다면 아래 사진 참고)

POST 요청을 받은 서버가 포워드를 통해서 브라우저를 다른 페이지로 이동(GET)시켜도 이는 마찬가지이다. 왜냐하면 포워드는 앞서 언급했듯이 하나의 요청과 응답 객체를 유지한 채 작업이 이루어지기 때문이다. 즉, 사용자 브라우저 입장에서는 처음 POST 요청을 보낸 이후 다른 페이지로 이동(GET)하라는 응답만 받았을 뿐 POST 요청 이후 다른 어느 요청도 하지 않았으므로 가장 최근에 서버에 보냈던 POST 요청을 다시 한 번 하는 것이다.

만일 영화 예매 시 사용자가 결제를 했다면 새로고침 시 결제가 한 번 더 일어날 수도 있는 것이다. 그래서 보통 POST 요청 이후에 새로고침을 클릭하면 브라우저에서 경고창을 팝업시키지만 이를 근본적으로 해결하기 위해서는 서버가 브라우저로부터 POST 요청을 받아 데이터를 정상 처리했으면 브라우저가 다른 URL(요청 작업이 성공했다는 별도의 안내 페이지 등)로 GET 요청(재요청)하도록 리다이렉트를 하는 것이다. 그러면 사용자가 새로고침을 하더라도 가장 최근에 서버에 보냈던 GET 요청을 반복하므로 POST 요청은 더 이상 일어나지 않는다. GET 요청은 보통 데이터 조회 시 사용하는 통신 방법으로 문제될 것이 없다. 이를 PRG(POST-Redirect-GET) 패턴이라고 한다.

(PRG 패턴 적용 전) POST 요청 후 새로고침(출처: https://en.wikipedia.org/wiki/Post/Redirect/Get) (PRG 패턴 적용 후) POST 요청 후 새로고침(출처: https://en.wikipedia.org/wiki/Post/Redirect/Get)

포워드는 주로 언제 사용될까? 하나의 예로, Java 서블릿과 jsp을 연동하는 것이 있다. 서블릿은 프로그램 로직을 개발하기에 편리하지만, HTML 태그를 출력하기엔 불편하고. JSP는 프로그램 로직을 개발하기는 불편하지만, HTML 태그를 출력하기엔 편리하다. 여기서 포워드를 이용하여 브라우저가 서블릿으로 요청을 보내도 서블릿은 이 요청에 대한 처리결과를 JSP에 전달하여 JSP가 이 결과를 출력하도록 할 수 있다.

※ 그러나 요즘 웹 개발 추세는 점차 jsp를 사용하지 않고 프론트엔드(JS 등)와 API만으로 화면(html)을 구성하는 것이다.

서블릿 doGet 메서드에서 처리한 결과를 result.jsp에 포워드 시키는 예시(소스코드 일부 생략)

결론적으로 리다이렉트가 좋냐 포워드가 좋냐의 문제가 아니라 상황에 따라 리다이렉트를 써야할 때가 있고 포워드를 써야할 때가 있는 것이다. 또한 언제 리다이렉트를 쓰고, 언제 포워드를 쓰고가 아니라 복합적인 상황에 따라 리다이렉트와 포워드를 조화롭게 사용해야한다.

[ 참고자료 ]

- 부스트코스 "웹 프로그래밍(풀스택)"

from http://ikjo.tistory.com/42 by ccl(A) rewrite - 2021-12-22 21:01:42