[Javascript] (BFCache이슈) IOS 웹뷰 뒤로가기 자바스크립트 오류(IOS History Back Error)
- -
[Javascript] IOS 웹뷰 뒤로가기 자바스크립트 오류(IOS History Back Error)
안녕하세요. 갓대희 입니다. 이번 포스팅은 [ [Javascript] 아이폰 뒤로가기 오류(IOS History Back Error) ] 입니다. : )
0.들어가기 앞서
Safari, Firefox 브라우저에서, 나와 같은 경우 아이폰 웹뷰 Safari의 경우에
BFCache 때문에 페이지 개발 방식에 따라 뒤로가기시 스크립트 로드가 되지 않아 정상 동작하지 않는 경우가 있다.
※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※
이글을 쓴지 오래 되었고, 점검하다보니 가이드 중 Deprecated API가 있습니다. 쭉 읽어보셔도 감사하지만,
최신 내용으로 다시 가이드글을 작성하였으니 다음 글을 참고 해주시면 더 좋을 것 같습니다.
※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※ ※
별 의미 없지만 문득, 이런 오류를 겪을수 있는 확률? 가능성?이 얼마나 되는지 확인해 보고 싶었다. 다음 모바일 브라우저의 사용 통계 데이터를 확인해보자.
1) 전 세계 기준
- 크롬이 약 65% 점유율로 단연 앞서며, 사파리가 약 25%로 한 축을 이루고 있다.
뒤이어 삼성 갤럭시의 힘을 받아 삼성 인터넷 브라우저가 뒤를 이어 가고 있는 모습이다.
2) 한국 기준
- 크롬이 약 40% 점유율, 삼성 26%, 사파리가 약 20%로 결국 최소 20% 이상은 Safari를 사용하고 있는 것이다.
1. 오류 현상
- 상기 브라우저(IOS 웹뷰 등)에서 뒤로가기기 자바스크립트가 실행되지 않는 경우.
ex) 뒤로가기시 BFCache로 동작하였기 때문에 네트워크 요청도 없고, Page Load시의 페이지를 만드는 스크립트 동작도 이루어지지 않는 경우.
2. BFCach(Back-Forward Cache)
- 해당 현상의 원인은 BF Cache 때문이다.
아이폰(IOS) Safari 브라우저에서 뒤로가기(history.back) 또는 동일 페이지 등으로 이동하는 경우 BF Cache를 사용한다.
- BFCache란 동일 세션내 브라우저에서 이전 페이지를 보다 빠르게 로딩하기 위해 이전에 저장한 캐싱된 페이지를 바로 로드하는 방법이라고 할 수 있을것 같다.
참고 : developer.mozilla.org/en-US/docs/Archive/Misc_top_level/Working_with_BFCache
- 장점 : 미리 저장한, 즉 캐싱된 페이지를 그대로 사용하기 때문에 페이지 응답 속도, 즉 속도적인 측면에서 유리하다. 이 캐싱 상태는 브라우저를 닫을 때까지 유지된다.
- 단점 : window.onload, $(document).ready()와 같은 onLoad 이벤트가 동작하지 않기 때문에 개발자의 의도와 다른 페이지를 보여줄 수 있다.
좀더 자세한 내용은 위 참고 url을 확인 해보자.
3. 뒤로가기 오류 해결 방안.
- 다음 가이드에 따라 2가지 가능한 방법을 확인할 수 있었다.
developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/1.5/Using_Firefox_1.5_caching
※ 해결 방안
▶ 3.1 pagehide / pageshow 사용, persisted 속성 사용
- 위 가이드에서 확인해보면 pageshow/pagehide 이벤트를 대안으로 제시하고 있다.
- 파이어 폭스와 같은 경우 2009년 부로 pagehide / pageshow 이벤트가 생겼고(현재 물론 safari에서도 정상 동작) 해당 이벤트에 대해 알아 보자.
(bugs.webkit.org/show_bug.cgi?id=28758)
1) pageshow 함수 : load 이벤트에 대응
2) pagehide 함수 : unload 이벤트에 대응
3) persisted 속성
- window.onpageshow(onpagehide)함수의 event 파라미터에서 event.persisted를 통해 BForward Cache를 이용해서 호출되었을 경우 true, 아닌경우 false를 리턴 한다.
4) window.performance.navigation 객체 사용
- 혹시나 event.persisted가 동작하지 않는 경우를 대비하여 추가 하였다.
- window.performance.navigation 객체는 리다이렉트(redirect), 앞/뒤 버튼, 혹은 보통의 URL 로딩이 어떤 페이지 로드를 일으키는지(trigger) 등의 확인에 사용할 수 있는 속성을 갖고 있다.
- window.performance.navigation.type = 2 인경우 History 이동을 의미 한다.
※ 참고
0(TYPE_NAVIGATENEXT) : 링크 클릭, 직접 입력, Form submit 등의 네비게이션
1(TYPE_RELOAD) : 리로드(reload) 또는 location.reload() 메소드를 통한 내비게이션
2(TYPE_BACK_FORWARD) : 히스토리 이동(순회) 연산을 통한 내비게이션
3(TYPE_UNDEFINED) : 위의 경우에 벗어난 네비게이션
5) 사용 예시
- 해당 함수에 ios 또는 특정 브라우저 일때만 핸들링 하는 부분을 추가하여 사용하면 될 것 같다. 나와 같은 경우는 ios webview인경우 reload 처리
물론 reload하기 때문에 화면 깜빡임 현상이 발생하였고, 페이지 캐시 효과는 없어 졌지만 당장 BFCache 로인한 에러는 해결 하였다.
ex1) 일반적인 사용 예
window.onpageshow = function(event){
if ( event.persisted || (window.performance && window.performance.navigation.type == 2) ){
alert("BFCache를 통해 페이지 접근!");
}
};
ex2) 일반적인 사용 예2
<body onpageshow="if( event.persisted || (window.performance && window.performance.navigation.type == 2) ) alert("BFCache를 통해 페이지 접근!");">
ex3) 화살표 함수 사용
- (https://goddaehee.tistory.com/228) 참고
window.onpageshow = (event) => {
if ( event.persisted || (window.performance && window.performance.navigation.type == 2) ){
alert("BFCache를 통해 페이지 접근!");
}
};
ex4) jQuery 사용시
$(window).bind("pageshow", function(event) {
if ( event.persisted || (window.performance && window.performance.navigation.type == 2) ){
alert("BFCache를 통해 페이지 접근!");
}
});
▶ 3.2 No Cache 처리
- developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/1.5/Using_Firefox_1.5_caching
- 상기 내용을 확인해보면 Cache처리가 안되는 몇가지 케이스가 있는데 해당 케이스처럼 만들어 주면 캐시 처리가 안되지만, 캐싱처리를 해야하는 내용까지 캐싱처리가 안될 수 있으니 조심 해야 할 것 같다.
**************** 내용 참고 ****************
ㆍthe page uses an unload or beforeunload handler;
ㆍthe page sets "cache-control: no-store".
ㆍthe site is HTTPS and page sets at least one of:
- "Cache-Control: no-cache"
- "Pragma: no-cache"
- with "Expires: 0" or "Expires" with a date value in the past relative to the value of the "Date" header (unless "Cache-Control: max-age=" is also specified);
ㆍthe page is not completely loaded when the user navigates away from it or has pending network requests for other reasons (e.g. XMLHttpRequest));
ㆍthe page has running IndexedDB transactions;
ㆍthe top-level page contains frames (e.g. <iframe>) that are not cacheable for any of the reasons listed here;
ㆍthe page is in a frame and the user loads a new page within that frame (in this case, when the user navigates away from the page, the content that was last loaded into the frames is what is cached).
****************************************
ex1) 사용 예시
@RequestMapping("/test.test")
public ModelAndView test(HttpServletRequest request, HttpServletResponse response,{
response.setHeader("Expires", "일자");
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.setHeader("Pragma", "no-cache");
}
나와 같은 경우는 당연히 속도 이슈도 그렇고, 리로드 하는 방법으로 해결 하였다.
이왕 이렇게 된 것 뒤로가기와 관련된 내용을 다음 포스팅으로 이어 나가도록 해야 겠다.
참고. Cache-Control에 대한 내용은 하기에 추가로 기재 하였다.
'2. 웹개발 > Javascript Function 모음' 카테고리의 다른 글
[Javascript] (BFCache이슈) IOS/Chrome 뒤로가기 자바스크립트 오류(History Back Error) (1) | 2023.11.27 |
---|---|
[JavaScript ] 개인정보 마스킹 함수(이름 마스킹, 이메일 마스킹, 휴대폰 번호 마스킹, 주민번호 마스킹) (4) | 2020.04.01 |
[JavaScript ] 카운트 다운 함수(Count Down Function) (9) | 2020.03.20 |
[Javascript] 브라우저 버전 체크 & Text 클립보드(Clipboard) 복사하기 (1) | 2018.06.14 |
소중한 공감 감사합니다