Technology/Web

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

ikjo 2021. 12. 24. 07:33

리다이렉트(Redirect)란?

리다이렉트는 HTTP 프로토콜로 정해진 규칙으로서 리다이렉트를 이용하면 서버가 클라이언트의 요청에 대해 특정 URL로 이동하도록(재요청하도록) 응답할 수 있다.

 

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

 

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

 

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

 

 

리다이렉트의 용도

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

 

만일 서버에서 데이터 처리를 못하고 브라우저에 오류를 반환했더라면 다행이지만 정상적으로 서버에서 데이터 처리가 이루어진 이후에 사용자가 새로고침을 누른다면 서버에 방금 전 POST 요청이 한 번 더 전달된다. 만일 영화 예매 시 사용자가 결제를 했다면 새로고침 시 결제가 한 번 더 일어날 수도 있는 것이다. 이는 새로고침 시 웹 브라우저가 가장 마지막에 했던 요청(서버에 POST 요청했던 행위)을 기억하여 다시 한 번 서버에 POST 요청하기 때문이다.

 

POST 요청을 받은 서버가 다른 핸들러로 포워드시켜도 이는 마찬가지이다. 왜냐하면 포워드는 하나의 요청과 응답 객체를 유지한 채 작업이 이루어지기 때문이다. 즉, 브라우저 입장에서는 처음 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)

 

 

포워드(Forward)란?

forward는 "전달하다"라는 의미를 가지고 있는데, 이 의미는 실제 웹에서도 적용된다. 포워드는 서버가 클라이언트의 요청을 받으면 이를 다른 서버에게 전달하는 것이다.

 

예를 들어, 아래와 같이 Servlet1과 Servlet2가 있다고 생각해보자. 만약 웹 브라우저에서 Servlet1에게 요청을 보내면 Servlet1은 이 요청을 처리한 후, 그 결과를 HttpServletRequest에 저장하고 결과가 저장된 HttpServletRequest와 응답을 위한 HttpServletResponse를 같은 웹 어플리케이션 안에 있는 Servlet2에게 전달한다.

 

이때 Servlet2는 Servlet1으로 부터 받은 HttpServletRequest와 HttpServletResponse를 이용하여 요청을 처리한 후 웹 브라우저에게 결과를 전송한다. 웹 브라우저 입장에서는 Servlet1에게 요청을 보냈지만 응답은 Servlet2로부터 받는 것이다.

 

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

 

 

포워드의 용도

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

 

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

 

 

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

사용자 브라우저가 서버(예시 : URL A)에 요청을 보내고 또 다른 서버(예시 : URL B)가 있다고 가정해보자.

 

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

 

반면에 포워드는 사용자 브라우저 주소창에 처음 보냈던 URL A가 그대로 입력되어있다. 포워드는 단지 다른 서버(URL B)가 브라우저에게 응답하는 것일뿐 브라우저는 서버(URL A)에 한번만 요청한 것이다.

 

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

 

 

참고자료

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