Posts bfcache
Post
Cancel

bfcache

BFCache

  • 사용자가 브라우저 내에서 뒤로가기/앞으로가기를 할 때 이전 페이지를 자바스크립트 heap 영역까지 전체 캐싱하여 메모리에 저장하는 것
  • HTTP 캐시는 리소스만을 캐시하고 JS 작업까지 캐시하지 않기에 BFCache보다 빠르지 않다.


BFCache 작동을 판단할 수 있는 API

pageshow, pagehide

pageshow

  • 페이지가 처음 로드 될 때, bfcache에서 페이지가 복원될 때마다 load 이벤트 직후 트리거 된다.
  • event.persisted === true이면 BFCache에서 복구된 것이다.

pagehide

  • 페이지에서 나가거나, 브라우저가 페이지를 bfcache에 저장하려고 할 때 트리거 된다.
  • event.persisted === false이면 bfcache에 저장되지 않았다는 뜻이다.
  • true라고 항상 bfcache에 저장되지 않는다. (브라우저가 저장하려고 했다는 알수 있음.)

freeze / resume

크롬에서 지원되는 이벤트

freeze

  • pagehide 이벤트의 persisted 가 true일 경우, pagehide 이벤트 다음에 호출됨.
  • bfcache에 저장하려고 한 의도를 알 수 있음.

resume

  • BFCache로 들어가고 나올 때 호출되는 이벤트 (이외 상황에서도 호출됨 ex : CPU 사용량 최소화를 위해 백그라운드 탭이 동결된 경우)
  • bfcache에서 페이지가 복원 될 때, 정지된 배경 탭을 다시 방문할 때도 실행


BFCache를 위한 페이지 최적화 방법

  1. unload 이벤트 사용하지 않기
    • unload 이벤트는 페이지가 더이상 존재하지 않을 거라는 가정하여 운영됨.
    • 따라서 unload 이벤트 사용시 BFCache는 사용되지 않음. 대신 pagehide 이벤트 사용하기
  2. window.opener 참조를 피하라
    • rel="noopener"를 사용하지 않고 열면 새로운 페이지는 window.opener를 가지고 있고, 이 opener를 가지고 있는 페이지는 bfcache에 넣지 않는다.
    • Tabnabbing 보안 취약점 공격과도 연관된 부분이기 때문이다. (Tabnabbing 공격)
  3. navigate 전에 항상 open된 connection 닫기.
    • setTimeout, promise 함수가 진행중일때 bfcache에 삽입하면, 작업을 일시정지하고 다시 페이지에 돌아왔을 때 진행중인 작업을 재개한다.
    • 스케쥴된 작업이 단지 DOM APIdㅔ 접근하는 등 해당 페이지에만 영향을 주는 API라면 일시 정지 후 재개가 문제되지 않는다.
    • 하지만 same-origin의 다른 페이지에서도 액세스할 수 있는 API의 경우 작업이 일시 중지되었을 때, 다른 탭의 코드가 실행되지 않을 수도 있기 때문에 문제가 발생한다.
    • 따라서 많은 브라우저에서는 connection이 open되어있을 경우 bfcache에 해당 페이지를 넣지 않는다.
      • IndexedDB 트랜잭션 중일때
      • fetch(), XMLHttpRequest 중일때
      • WebSocket, WebRTC 연결이 열려있을 때.
    • 최적화를 위해선, pagehide나 freeze 이벤트에서 항상 connection을 닫고, observer를 제거하거나 연결을 끊는게 좋다. 물론 다시 돌아왔을 때 연결을 맺어줘야한다.


bfcache 비활성화하기

아래와 같이 Cache-Control 속성을 설정하면 된다.

1
Cache-Control: no-store

물론 다른 캐시들도 동작하지 않는다.


BFCache 문제점

  • 성능측정을 불분명하게 함 : bfcache에서 페이지가 로드되면 매우 빠르게 로드되기에 성능 측정 시 잘못된 결과값을 내게할 수 있다.
  • 집계를 내는 것이 힘듬 : bfcache로 다시 방문했을때 페이지 접속 집계가 안될 수도 있음.

두 경우 모두 pageshow 이벤트를 사용하여 정상적으로 수행하도록 해야한다.


출처

https://blog.naver.com/PostView.nhn?blogId=qls0147&logNo=222157982248&categoryNo=0&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=postView

This post is licensed under CC BY 4.0 by the author.

beforeunload vs pagehide

딥링크

Comments powered by Disqus.