2. 웹개발/Javascript Function 모음

[Javascript] (BFCache이슈) IOS/Chrome 뒤로가기 자바스크립트 오류(History Back Error)

갓대희 2023. 11. 27. 01:29
728x90

안녕하세요. 갓대희 입니다. 이번 포스팅은 [  Javascript 뒤로가기 BF Cache 에러  입니다. : )

0. 들어가기 앞서

 - 예전 Safari, Firefox 브라우저에서, 나와 같은 경우 아이폰 웹뷰 Safari의 경우에 BFCache 때문에 페이지 개발 방식에 따라 뒤로가기시 스크립트 로드가 되지 않아 정상 동작하지 않는 경우가 있었다.

2020.08.15 - [2. 웹개발/Javascript Function 모음] - [Javascript] (BFCache이슈) IOS 웹뷰 뒤로가기 자바스크립트 오류(IOS History Back Error)

 


 - 다만, 이젠 크롬에도 BFCache가 도입되었고 또다시 크롬에서도 BFCache때문에 고통을 겪게 되었다. 그리고 예전글에서 가이드 했던 내용 중 Deprecated 된 API도 있기 떄문에 다시 정리하고자 한다.

https://developer.chrome.com/docs/web-platform/bfcache-notrestoredreasons/?hl=ko

 

 

 - 대부분은 내용은 web 데브의 내용을 재해석 하였다.

https://web.dev/articles/bfcache?hl=ko

 

1. BFCache

BF Cache( Back-Forward Cache )란?  

 

 - 사용자가 브라우저에서 뒤로가기/앞으로가기 했을 경우 이전 페이지를 전체 캐싱해서 in memory로( 자바스크립트 heap 영역까지 ) 가지고 있는 것, 즉 페이지 전체의 스냅샷을 저장하는 캐싱 기능이다.

 

 - BFCache를 사용하는 예시가 BFC ache를 사용하지 않은 예시보다 훨씬 빠를 수 밖에 없다.

( 이번엔 BFCache의 장점을 살펴보려는 내용은 아니기 때문에 간단히 넘어간다. )

 - 하지만 네트워크에 전혀 연결하지 않고, 메모리로부터 해당 웹페이지를 복원하기 때문에 개발자들에게는 매우 난처한 상황을 만들기도 한다. 

 

BF Cache 동작 여부 확인 방법 (BFCache 테스트 방법)

 

 - 내가 확인하려는 페이지에서 BFCache가 작동했는지 직접 테스트 해볼 수 있다. 

※ 크롬에서 98버전 이후 부터 BFCache 적용 가능여부를 테스트 할 수 있으니 참고 하자. 

https://developer.chrome.com/ko/blog/new-in-devtools-104/#bfcache

 

 

※ 테스트 방법 참고 -  https://developer.chrome.com/ko/blog/new-in-devtools-98/#bfcache

 - Application > Background Services > Back/forward cache 를 클릭 하고 뒤로가기 또는 앞으로 가기를 클릭 하면 다음과 같이 BF Cache 동작 여부를 직접 확인할 수 있다.

 

 - 미동작 했을때에는 관련 사유를 알려 준다.

( 내가 테스트한 사이트에는 캐시를 저장하지 말라고 하는 cache-control : no-store가 적용되어 있어 미동작 하였다. )

 

2. Javascript 코드로 BFCache 감지 방법 

BF Cache로 개발자들이 겪는 상황  

 

 - BF Cache를 잘 사용하면 좋겠지만, BFCache가 적용되면

    window.onload, $(document).ready()와 같은 onLoad 이벤트가 동작하지 않기 때문에 개발자의 의도와 다른 페이지를 보여줄 수 있다.

 

BF Cache 감지 방법

 

 - 혹시 긴글에 지쳐 정답만 알고 싶은 경우 다음을 활용해보면 될 것 같다. 

window.onpageshow = (e) => {
	const navigation = window.performance.getEntriesByType('navigation');
	if (e.persisted || (navigation.length && (navigation[0]).type === 'back_forward')){
		// 캐싱되면 안되는 동작 추가
	}
};

 


 

1) BFCache를 감지하는데 사용되는 기본 이벤트는 페이지 전환 이벤트(pageshowpagehide)이다.

이 이벤트는 BFCache 기간만큼 오랫동안 사용되었고, 모든 브라우저에서 지원다. 

 

 - 혹시나 호환성 체크 해보았지만, IE11에서 조차 동작 한다.

https://caniuse.com/page-transition-events

 

▶ pageshow

 - pageshow 이벤트는 다음 2가지 상황에서 발생한다.

1) 페이지가 처음 로드될 때

2) 페이지가 bfcache에서 복원될 때마다 load 이벤트 직후에 실행된다.

    └ persisted : BFache에서 복원되면 true, 그렇지 않은 경우 false를 반환한다.

 - 이를 통해 다음과 같이 BFCache로 부터 복원되었음을 감지할 수 있다.

window.addEventListener('pagehide', (event) => {
  if (event.persisted) {
    console.log('This page *might* be entering the bfcache.');
  } else {
    console.log('This page will unload normally and be discarded.');
  }
});

 

 

▶ pagehide

 - pagehide 이벤트는 다음 2가지 상황에서 발생한다.

1) 페이지가 정상적으로 언로드 될 때

2) 브라우저가 bfcache 하려고 시도할 때

    └ persisted :  이 속성이 false라면 페이지가 bfcache에 들어가지 않을 것이 확실하다.  true라면 브라우저가 캐시 하려고 시도한 것 이다.

 

※ 하지만 위에서 테스트 해봤듯이,  크롬과 같이 다른 캐싱 방지 요소에 의해 결과적으로 캐시되지 않을 수도 있기 때문에 100% 보장할 수 없다.  이때문에 pageshow 이벤트를 활용 하려고 한다. 

 

뒤로가기 감지 방법

 

 - 대부분 앞으로 가기보다는 뒤로가기 행동에서 문제를 겪게 되는 고민을 하였을 것 이다. 

 - 위에서 BFCache는 감지 할 수 있었고 이제 뒤로 가기이벤트만 감지하면 된다.

 

※ 예전 나도 글을 썼었고, 뒤로가기의 경우 다음 방법을 사용했었다. 

 - window.performance.navigation.type

window.performance && window.performance.navigation.type == 2

// 또는 다음과 같은 예시

window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD

 

 - 하지만 이제 해당 API는 deprecated되었다. 검색해 볼 수도 있지만 IntelliJ를 사용하면 친절히 알려주기도 한다.

 

 - 해당 api는 deprecated 되었며 Performance.navigation을 활용하라고 한다.  (자세한 내용은 하기 링크 참고)

https://developer.mozilla.org/en-US/docs/web/api/performancenavigation

 

 - PerformanceNavigationTiming 으로 대체 되었고 자세한 내용은 하기 참고.

https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming

 

최종 BFCache 동작 및 뒤로가기 동작 감지

 

 - 나의 경우 위와 같은 과정과 내용을 조합하여 다음과 같이 BFCache 동작을 감지 하였고, 정상동작할 수 있도록 처리 완료 하였다.

window.onpageshow = (e) => {
	const navigation = window.performance.getEntriesByType('navigation');
	if (e.persisted || (navigation.length && (navigation[0]).type === 'back_forward')){
		// 캐싱되면 안되는 동작 추가
	}
};

 

 

나와 같이 BFCache로 고통을 겪는 분들에게 조금이나마 도움이 되면 좋겠다.

혹시라도 잘못 작성한 내용이 있다면 꼭 댓글로 알려주시면 감사합니다!! :-) 

 

300x250