2012년 11월 15일 목요일

[ASP.NET MVC] 브라우저 캐시 회피하기

 현재 개발 중인 모바일 버전 전자결재 서비스의 결재 시나리오다. 사용자가 [문서목록 페이지]에서 문서를 터치하면 [결재 페이지]가 표시된다. 결재 버튼을 터치하면 문서가 결재됐다는 알림과 함께 [문서목록 페이지]를 이동한다. 여기서 웹 브라우저의 'Back' 버튼이 문제가 된다. 'Back' 버튼을 누르면 이미 결재가 완료된 문서이기 때문에 한 단계 더 뒤로 가던가(history.back x 2), 결재가 완료된 문서에 접근했음을 알리는 알림이 필요하다. 우리는 간단히 알림을 제공하도록 [결재 페이지]의 최상단에 다음 스크립트를 입력했다.

     <% if (Model.IsApproved) { %>
        <script type="text/javascript">
                alert("이미 결재가 완료된 문서입니다.");
                document.location.href = "/Approval/List";
        </script>
    <%} %>

하지만 결재 완료 후 'Back' 버튼을 누르면 스크립트는 무시되고 다시 [결재 페이지]가 표시된다. 이미 결재가 완료된 문서이기 때문에 결재, 반려 등의 UI가 표시되는건 문제가 된다. 스크립트가 무시되는 이유는 캐시 때문이다. 캐시에 저장된 웹 페이지가 스크립팅되지 않고 바로 표시되기 때문이다.

캐시 페이지가 아닌 Brand New 페이지를 표시하기 위해 [결재 페이지]의 액션 메서드에 다음 코드를 추가한다.

    // 캐시를 사용하지 않는다.
    Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
    Response.Cache.SetNoStore();

But. 
크롬에서는 정상적으로 작동된다. 문제는 사파리였다. 실제 아이폰 애플리케이션에서는 위의 코드가 전혀 소용이 없다. 'Back' 버튼을 터치하면 캐시된 [결재 페이지]로 이동한다. 반나절을 구글과 StackOverflow를 해집고 돌아다니던 중 이유와 해결 방법을 찾았다. 최신 웹 브라우저들은(크롬은 되던데?) 일반적인 HTTP 캐시와는 차별되는Back/Foward를 위한 별도의 캐시를 제공한다. 이 때문에 위의 코드들이 사파리에서는 작동되지 않았던거다.

해결 방법은 '믿든지 말든지 (StackOverflow의 어느 개발자의 답글이었다. believe it or not.)' body 태그의 unload 이벤트에 빈 핸들러만 등록해주면 된다. 뭐 이런 경우가 있나 싶지만, 자~알 작동한다.이유는 참고 자료의 두 번째 링크를 통해 알 수 있다.

    <body onunload="">


참고

댓글 없음:

댓글 쓰기