크롬 unload 중단, 종료 직전 저장은 어디로 옮길까

탭을 닫을 때 입력 내용을 저장하던 unload 코드가 Chrome 155에서 더는 돌지 않는다. 이름이 비슷한 beforeunload로 옮기기만 하면 될까?

크롬 unload 중단, 종료 직전 저장은 어디로 옮길까
세 줄 요약
  • Chrome 155에서는 별도 예외 설정이 없으면 unload 처리기가 실행되지 않는다.
  • 자동 저장, 페이지 이탈 정리, 미저장 경고는 서로 다른 이벤트로 나눠야 한다.
  • visibilitychange의 hidden은 탭 전환 때도 발생하므로 로그아웃 신호로 쓰면 안 된다.

종료를 기다리지 말고 숨겨질 때 저장한다

크롬에서 탭을 닫아도 unload에 넣은 저장 코드가 실행되지 않는다면, 이벤트를 다시 켜기보다 저장 시점을 앞당겨야 한다. Chrome의 이벤트 전환 안내는 visibilitychange에서 문서가 hidden이 되는 시점을 앱·사용자 데이터를 저장할 마지막 안정적인 기회로 설명한다.

Chrome 팀은 10월 16일 발표에서 Chrome 155를 기준으로 unload의 기본 실행을 중단하는 전환이 끝났다고 밝혔다. 과거에는 동작하던 종료 처리기가 업데이트 뒤 멈출 수 있는 이유다. Permissions Policy나 기업 정책으로 예외를 둔 사이트는 다르며, WebKit을 쓰는 iOS의 Chrome에서도 실행될 수 있다.

저장·정리·경고를 같은 이벤트에 몰아넣지 않는다

대체 이벤트는 기존 코드가 하던 일에 따라 고른다. 이름이 비슷한 beforeunload로 전부 옮기면 자동 저장의 불안정성까지 함께 옮기게 된다.

기존 작업옮길 곳함께 지킬 조건
사용자 입력·앱 상태 저장visibilitychange의 hidden 전환다른 탭으로 갔다가 돌아오는 경우도 처리한다.
페이지 이탈 시 자원 정리pagehide뒤로 가기로 복원될 때 필요한 자원을 다시 준비한다.
저장하지 않은 변경 경고beforeunload미저장 변경이 있을 때만 리스너를 둔다.

beforeunload 경고창은 사용자 상호작용이 있어야 표시되며, 문구는 브라우저가 정한다. 저장이 끝났다면 리스너도 해제하는 방식이 적절하다. 이 이벤트는 모바일에서 앱을 바꾼 뒤 브라우저를 종료하는 상황 등에 실행되지 않을 수 있다.

pagehide도 모바일의 모든 종료를 잡지는 못한다. 다만 뒤로·앞으로 가기 캐시인 bfcache와 함께 사용할 수 있어, 페이지 이탈 때 정리할 작업을 옮기는 데 적합하다. 페이지가 캐시에 보관됐다면 나중에 그대로 돌아올 수 있다는 점을 처리 코드에 반영해야 한다.

hidden은 로그아웃이 아니고, 큐 등록은 저장 완료가 아니다

visibilitychange의 hidden은 탭 닫기뿐 아니라 탭 전환, 창 최소화, 모바일 앱 전환 때도 나타난다. 따라서 이 이벤트에 강제 로그아웃이나 계정 세션 삭제를 연결하면 잠깐 다른 화면을 본 사용자를 내보낼 수 있다. 저장할 기회와 사용자가 떠났다는 판정을 분리해야 한다.

소량의 분석 데이터를 보내는 용도에는 sendBeacon이 맞는다. 다음은 페이지가 숨겨졌다는 기록을 보내는 예시다. 서버가 해당 경로를 받아 처리하도록 구현돼 있어야 한다.

document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "hidden") {
    navigator.sendBeacon("/analytics", "page_hidden");
  }
});

sendBeacon은 작은 데이터를 비동기 POST로 보낸다. 반환값 true는 브라우저가 전송 큐에 넣었다는 뜻이며 서버의 저장 완료 응답은 아니다. 서버 응답을 읽거나 POST 외의 메서드가 필요하다면 MDN은 fetch와 keepalive를 쓰는 방향을 안내한다. 어느 쪽이든 탭이 사라진 뒤 화면에 저장 성공을 표시할 수 있다고 전제해서는 안 된다.

내 코드뿐 아니라 라이브러리의 unload도 찾는다

수정은 unload 등록 위치와 그 안의 작업을 찾는 데서 시작한다. 자체 코드에 없어도 외부 라이브러리가 사용할 수 있다. Chrome의 사용처 탐지 안내는 DevTools의 Back/forward cache 검사와 Reporting API 등을 제시한다.

목적별로 코드를 옮겼다면 탭을 바꿨다가 돌아오는 흐름과 뒤로 가기 복원을 각각 확인해야 한다. 전자는 hidden을 종료로 오인한 처리를, 후자는 정리한 자원을 복원하지 않은 문제를 드러낼 수 있다. 종료 직전 한 번 실행될 콜백에 의존하지 않고, 사용 중 상태를 보존하고 복원하는 흐름으로 바꾸는 것이 이번 이전의 핵심이다.