에러(error)

웹 브라우저마다 에러 메시지는 다르지만, 현재 문제가 발생하면 볼 수 있는 에러 화면이다. 현재 개발을 위해 테스트 중인 3개 브라우저는 아래와 같은 에러들을 출력시키고 있다.

Chrome Browser (크롬)

양식 다시 제출 확인 / Confirm Form Resubmission / ERR_CACHE_MISS

 

Edge Browser (엣지)

이 페이지가 방금 전까지 여기 있었음

 

Internet Explorer 11 (인터넷 익스플로러)

웹 페이지가 만료되었습니다.

 

플랫폼(platform)

Chrome, Edge, Internet Explorer

STS 4(Spring Tool Suite 4), java, spring boot 1.5.17, Windows10

 

상황(situation)

웹 애플리케이션 서버(Web Application Server)를 개발하던 중에 (특정 어떤 상황에 대해서만) “양식 다시 제출 확인"이라는 에러가 발생했다. 본인이 테스트시 발견했던 특정 어떤 상황의 시나리오를 재현하면 아래와 같다.

 

  1. user는 web page1접속

  2. user는 web page1의 "data"를 post로 web server로 전달

  3. web server는 web page2로 변경해서 user에게 전달

  4. user는 web page2를 사용하다가 뒤로가기를 눌러서 web page1로 이동

  5. user는 web page1을 사용하다가 뒤로가기를 눌러서 web page2로 이동하지 못하고 “양식 다시 제출 확인“에러 발생

 

[ 문제 발생한 시나리오 ]

원인(cause)

앞에서 설명한 본인의 상황에서 발생한 근본적인 원인은 부터 말하자면, 리다이렉트(redirect)를 하지 않은 것이 원인이었다. 앞의 시나리오에서 5번 단계에서 에러가 발생했지만, 사실 이 에러를 발생시킨 시발점은 3번 단계이다. web server는 2번 단계에서 user의 요청을 처리한 후 web page2.html의 결과 페이지로 응답을 하고 있지만, 이렇게 하면 web browser에서 web page2.html를 출력시킬 수는 있지만, web page2.html의 주소를 가지지 않게 된다. web server에서 web page2.html이라는 데이터만 응답했을 뿐, 실제 web page2에 대한 URL 주소는 넘겨주지 않았기 때문이다. 따라서 2번 단계를 마치면 web browser는 web page2.html을 출력시키기만 하고, 실제 web page2.html에 대한 URL주소는 알지 못하는 것이다. 위 그림을 자세히 살펴보면 web browser의 URL 주소창에 적혀있는 값은 모두 web page1.html인 것을 볼 수 있다. 현재 본인과 동일한 문제라면 아마도 위 그림처럼 URL 주소가 변하지 않고 있을 것이다.

 

이 문제의 원인은 web server에서 다음 페이지로 직접 변경시킨 후, 다음 페이지의 URL 없이 web browser에게 응답하는 포워드(forwad)방식으로 응답했기 때문이다. 이 문제를 해결하려면 web browser에게 web page2.html 주소를 넘길테니 이 주소로 다시 재요청하라는 리다이렉트(redirect)방식으로 응답해줌으로써 문제를 해결할 수 있다.

 

아래 코드는 개발 중인 코드에서 현재 문제를 발생시킨 부분만 발췌한 것이다. web page에서 page1요청을 처리한 후, (forward로) page2로 응답하는 부분이다.

 

web page1를 처리하는 Controller 코드의 일부

@RequestMapping(value="/page1", method = {RequestMethod.POST})
public ModelAndView page1(String data, HttpSession session) {
  ...
  ModelAndView modelAndView;
  modelAndView = new ModelAndView("page2"); // direct 방식
  ...
  return modelAndView;
}

 

해결(solution)

앞에서 설명한 시나리오에서 3번 단계만 변경하면 문제를 해결할 수 있다. 변경된 시나리오는 아래와 같다.

 

  1. user는 web page1접속

  2. user는 web page1의 "data"를 post로 web server로 전달

  3. web server는 web page2로 변경해서 다시 요청하라고 web browser 에게 전송한 후,  web browser는 바로 web server에게 web page2를 요청하고나서, web server는 바로 web browser로 web page2를 전송

  4. user는 web page2를 사용하다가 뒤로가기를 눌러서 web page1로 이동

  5. user는 web page1을 사용하다가 뒤로가기를 눌러서 web page2로 이동

 

[ 문제 해결한 시나리오 ]

 

아래 코드는 앞에서 설명했던 (forward 때문에 발생했던) 문제를 해결하기 위해 리다이렉트(redirect)로 변경시켜서 web browser에게 다시 요청하라고 응답하는 부분이다.

 

web page1를 처리하는 Controller 코드의 일부

@RequestMapping(value="/page1", method = {RequestMethod.POST})
public ModelAndView page1(String data, HttpSession session) {
  ...
  ModelAndView modelAndView;
  modelAndView = new ModelAndView("redirect:page2"); // redirect 방식
  ...
  return modelAndView;
}