Posts beforeunload vs pagehide
Post
Cancel

beforeunload vs pagehide

ios 모바일에서 새로고침시 현재 스크롤 위치를 고정하기 위해 다음과 같은 코드를 사용하였다.

1
2
3
4
5
6
7
8
if (sessionStorage.scrollPosition) {
  window.scrollTo(0, sessionStorage.scrollPosition);
}

window.onbeforeunload = function () {
  sessionStorage.scrollPosition = document.body.scrollTop || document.documentElement.scrollTop;
};

하지만 제대로 동작하지 않았는데, 찾아보니 ios에서는 beforeunload 이벤트를 지원해주지 않는다는 을 읽었다. (글에서는 ios safari를 지원하지 않는다고 명시되어있지만, 크롬에서도 동작하지 않았다.)

대신에 pagehide를 사용하도록 안내받았고, 실제로 동작했다. 하지만 둘의 차이점에 대해서 명확히 알고 넘어가기로 했다.


beforeunload vs pagehide

beforeunload

  • window, document, resource가 unload 되려할 때 발생하는 이벤트.
  • document는 계속 보이고 있고, 이벤트는 취소할 수 있다. 따라서 실제로 페이지를 떠날건지 사용자에게 물어볼 수 있다.
  • 모바일에서 다음과 같은 상황에서는 발생하지 않는다.
    1. 모바일 사용자가 페이지를 방문한다
    2. 사용자가 다른 앱으로 전환한다.
    3. 사용자가 앱 관리자에서 브라우저를 닫는다.
  • back/forward cache 와 호환되지 않는다. 이벤트 후에 더이상 페이지가 존재하지 않을 것이라고 가정하기 때문이다. 따라서 브라우저는 unload 리스너가 있으면 bfcache에 페이지를 넣지않는다. 하지만 이는 성능에 악영향을 끼친다. 따라서 성능 악영향을 최소화하기 위해 저장되지 않은 변경 사항이 있을 때만 unload 리스너를 붙이는게 좋다.

pagehide

  • 세션 히스토리에서 다른 페이지를 표시하는 과정에서 브라우저가 현재 페이지를 숨길때 Window에서 발생한다.
    • ex) 뒤로가기 눌렀을 때 이전 페이지가 보이기 전에 발생
  • unload 이벤트와 마찬가지로 모바일에서 안정적으로 동작하지 않는다.
  • back/forward cache와 호환된다. 따라서 이 이벤트에 리스너를 붙이는 건 bfcache를 비활성화시키지 않는다.


의문 : 왜 beforeunload 는 ios에서 동작하지 않지?

beforeunload와 pagehide의 가장 큰 차이는 bfcache와 호환되지는 안되는지라는 건 알았다.

하지만 다시 최초로 돌아가서 왜 beforeunload는 ios에서 동작하지 않는지 의문이 든다. 왜냐면 MDN 공식문서에서는 safari IOS에서 버전 1부터 지원한다고 적혀있기 때문이다.

1시간 정도 조사를 해본 결과 아래와 같은 단서를 찾았다.

단서 1

  • ios에 버그가 있다고 한다.
  • 링크를 클릭해서 다른 곳으로 이동하는 경우나 history.back()을 사용하는 경우에는 동작하는데, history.back()으로 다른 도메인으로 이동할 때는 동작하지 않았다고 한다.
  • 새로고침 동작에서도 버그일수도 있겠다는 생각이 들었다.

단서 2

  • webkit의 known issue이다
  • 애플에서 의도적으로 막았다(?)

이후 좀 더 조사를 해봤지만, ios에서는 지원을 안한다, ios의 버그이다라는 말 이외에 찾을 수 없었다. 추정만 있지 명확한 공식문서는 볼 수 없었다.

향후 beforeunload 이벤트가 필요해졌을 떄 한번 더 찾아봐야할거 같다.

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

useState 원리

bfcache

Comments powered by Disqus.