몇일 전 유지보수를 하고 있는 사이트에서 뒤로가기에 대한 이슈를 접수 받았다.


하지만 이 이슈는 알고봤더니 꽤 오래전부터 묵혀져 있던 발효된 그러한 이슈 였다.


개발하던 개발자에게 부탁도 욕도 할 수 없는 상황이었다. 왜냐하면 그다음에 인수인계를 받은건 


나였기 때문이다. 


그래서 현재 발생한 이슈를 접수 받고 해결을 하기 위해 해당 증상을 파악하기 시작했다.



현재 유지보수를 하고 있는 프로젝트는 Spring + JSP + JSTL 로 이루어진 프로젝트 이다.




발생한 이슈의 내용은


화면에 들어가면 컨텐츠들이 나열되어 나오는데 이 컨텐츠들은 Spring의 ModelAndView로 리턴받아 JSTL 로 그려진 컨텐츠이다.


여기서 컨텐츠의 특정 아이콘을 누르면 해당 컨텐츠의 아이콘의 색깔이 변하면서 데이터베이스에 데이터가 쌓인다.


이 데이터를 쌓는 작업은 AJAX 비동기로 호출을 하고 있는 상태이다. 


여기서 이제 다른페이지로 이동 후 브라우저의 뒤로가기를 누르면 


이전에 클릭해서 색깔을 변경했던 아이콘들의 색상이 변경되어 있지 않은 것이다?!


하지만 새로고침을 하면 아이콘의 색깔이 정상적으로 돌아오는 것이다. 


그말은 즉슨 데이터베이스에는 데이터가 정상적으로 쌓여있다는 소리이다.


그래서 여기서 확인 할 수 있는건 브라우저의 뒤로가기시


브라우저에서 쌓는 Back Forward Cache 일 확률이 제일 크기 때문이다.


그럼 Back Forward Cache가 무엇인가 알아봤다.




Back Forward Cache 란 브라우저의 뒤로가기시 브라우저가 단일 세션내에서


자바스크립트 상태 및 웹 페이지를 전체를 캐싱함으로써 전체적은 응답속도를 빠르게 동작하기위해


사용되는 캐시입니다.


이 캐시는 페이지에 대한 추가적인 로딩을 하지않고 자바스크립트 상태 까지 유지하고 있기 때문에


페이지 로딩시 반드시 한번 호출되어야 하는 자바스크립트가 있다면 호출되지 않기 때문에 문제가 발생할 수 있습니다.

(인터넷 발췌)




라고 구글에게 검색해보니 나오고 있었다.


보아하니 현재 겪고 있는 상황이랑 매우 일치해 보였다.(뒤로가기시 해당 호출된 페이지는 서버에서 불러오지 않는다.)


그래서 Back Forward Cache를 해결하기 위해 몇가지 테스트를 진행해 보았다.




첫번째로 진행 한것은 JSP 문서상에 meta 태그로 Cache-Control을 추가하여 no-cache를 추가하였다.


결과는?! 간혈적으로 발생하지 않는 문제가 발생하였다.


인터넷상에 있는 글들을 검색해본 결과 반드시 no-cache가 되지않는다...라고 나오고 있었다.


그래서 이건 적용하지 않기로 하고 바로 두번째 테스트로 진행을 해보았다.



두번째로 진행 한것은 브라우저에서 로딩시 반드시 호출하는 window.onpageshow = function (event) {} 을 이용하는 방법이었다.


결과는?! 뒤로가기를 하던 페이지를 새로 접근을 하던 항상 onpageshow 함수는 호출을 해주었다.


여기서 이제 뒤로가기 이벤트를 잡는것이 관건이었는데 또다시 구글에게 물어본 결과


window.onpageshow 함수 인에 event 파라미터에서 event.persisted 를 통해서 Back Forward Cache를 이용해서 호출되었을 경우 true


그렇지 않을 경우 false로 호출한다는 결과를 알게되었다.


지금 당장 크롬, 익스, 파이어폭스, 사파리를 열어서 테스트해보았다.


결과는..파이어폭스와 사파리에서는 persisted를 통해서 뒤로가기 감지가 가능했지만 익스와 크롬에서는 불가능했다.


실패다. 벌써 이걸로 반나절을 까먹은듯 하다.



하지만 여기에 window.performance로 뒤로가기를 체크 할 수 있다는것을 알게되었다.


바로 코드를 작성하고 테스트를 진행하였다.


해당 자바스크립트 코드는 


window.onpageshow = function(event) {


    if ( event.persisted || (window.performance && window.performance.navigation.type == 2)) {


// Back Forward Cache로 브라우저가 로딩될 경우 혹은 브라우저 뒤로가기 했을 경우

    }

}


이거다. 이거라면 익스, 크롬, 사파리, 파이어폭스에서 브라우저 뒤로가기를 했을때 이벤트를 잡아 낼 수 있는 것이었다.

좋다. 결과는 만족스럽게 작동을 하였다.

나름 훌륭했다. 


그렇지만 문제가 하나 더 발생하였다. 

AJAX를 통해서 UI를 변경했을 경우 이 상태를 브라우저가 알고있어야되는데 서버에 갔다오지 않는 이상 모르지 않는가.

현재 유지보수를 진행하고 있는 프로젝트는 위의 부분을 해결하려면 결국 AJAX를 통해 UI의 상태를 가져오는

API가 하나더 필요한 것이다. 혹은 브라우저 뒤로가기 했을때 브라우저를 새로고침 하는 말도안되는 방식으로 처리해야 하지만

그렇게해서는 안되보였다.


그래서 더 검색을 해보았다. Spring에서 페이지에 대한 캐시를 만료시키는 방법을.. 찾았다.

Spring Intercepter부분에서 postHandle(컨트롤러 호출 후 View로 이동하기전에 실행하는 메소드) 부분에

페이지에 대한 캐시를 만료시키는 것이었다.

response.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT"); 
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0"); 
response.setHeader("Pragma", "no-cache");

이걸 추가한 후 브라우저 뒤로가기를 테스트해본 결과 만족하였다.

브라우저 뒤로가기를 해도 페이지는 다시 서버로 접근하여 데이터를 가져오니 정상작동을 하였다.


이로서 묵힘을 당했던 이슈는 처리가 되었지만.. 상세한 통합 테스트를 해보지않았기 때문에

좀 더 살펴봐야 될거같다.













+ Recent posts