Safari Inactive Page settimeout, setinterval disabled

박상수
6 min readFeb 13, 2019

--

운영하는 홈페이지 중에 session을 최초 발생후 1시간마다 갱신하면서 유지하는 기능을 갖고 있는데 safari브라우저에서 랜덤하게 세션이 유실되는 현상이 발생되었다.

Flow

- 동작은 아래 순서와 같다
1. 접속(세션발생)
2. 활동페이지(세션유지, 1시간 limit, 연장 버튼을 통해 연장가능)
3. 저장(세션확인)

활동페이지의 타이머는 자바스크립트의 setInterval 함수를 이용하여 구현하였고 새 탭 전환 혹은 비활성화시 동작을 하지 않는 것을 간단한 테스트를 통하여 확인 할 수 있었다.

TEST1

  • setInterval 테스트
  • safari브라우저에서 해당페이지를 켜둔 상태로 다른탭 전환 혹은 비활성화시 count가 증가하는지
<div id='time'>0</div>
<script>
//1초마다 setInterval을 통해 1씩 증가
window.onload=function(){
setInterval(function(){
document.getElementById('time').innerHTML = ++(parseInt(document.getElementById('time').innerHTML,10))
},1000);
}
</script>

문득 이런 의문이 들었다.. 혹시.. setinterval이 문제냐..??

TEST2

  • setInterval 함수가 문제일 수 있다? settimeout으로 변경
  • 0부터 100까지 1초마다 증가하는 하도록 소스 작성 후 모바일 사파리에서 테스트
TIMER TEST
<div id="time">0</div>
<script>
//settimeout을 통해 1초씩 증가
window.onload = function(){
var targetEl = function(){
return document.querySelectorAll("#time")[0];
},
getNum = function(){
return parseInt(targetEl().innerHTML,10);
},
setNum = function(num){
targetEl().innerHTML = num;
}
,timeout = function(maxSec){
return function timeout(){
if (!maxSec) return clearTimeout(t);
var t = setTimeout(function(){
var currentNum = getNum();
setNum(currentNum+=1);
maxSec-=1;
timeout();
clearTimeout(t);
},1000);
}();
};
timeout(100);



};
</script>

worker로 하면 동작하지 않을까??

TEST3

  • 0부터 100까지 1초마다 증가하는 하도록 소스 작성 후 모바일 사파리에서 테스트
//main.html
TIMER TEST
<div id="time">0</div>
<script>
window.onload = function(){
var targetEl = function(){
return document.querySelectorAll("#time")[0];
},
getNum = function(){
return parseInt(targetEl().innerHTML,10);
},
setNum = function(num){
targetEl().innerHTML = num;
}
var myWorker = new Worker('worker.js');
myWorker.onmessage = function(num){
setNum(parseInt(num,10));
});

};
</script>
//worker.js
var i = 0;
self.onmessage = function( e ) {
setTimeout( function() {
postMessage( ++i );
}, 1000 );
};

역시나 동작하지 않는다..

문제분석

  • safari 브라우저에서 setInterval, requestAnimationFrame함수 등 여러 자바스크립트가 비활성화 혹은 저성능으로 동작이 된다.

브라우저별 동작

  • Chrome : Chrome 탭이 비활성화된 경우 setInterval의 최소 간격을 약 1000ms로 제한합니다. 간격이 1000ms보다 크면 지정된 간격으로 실행됩니다. 창 초점과 관계없이 일정하게 동작
  • Firefox : Firefox는 Chrome과 마찬가지로 탭(창 제외)이 비활성화된 경우 setInterval의 최소 간격을 약 1000ms로 제한합니다. 그러나 requestAnimationFrame은 탭이 비활성화되면 기하급수적으로 느리게 실행되며 각 프레임은 1초, 2초, 4초, 8초 등이 소요됩니다.
  • Internet Explorer : IE는 탭이 비활성일 때 setInterval의 지연을 제한하지 않지만 비활성 탭에서 requestAnimationFrame을 일시 중지합니다. 창의 초점이 맞지 않는지는 중요하지 않습니다.
  • Edge : Edge 14부터 setInterval은 비활성 탭에서 1000ms로 clamping 됩니다. requestAnimationFrame은 비활성 탭에서 항상 일시 중지됩니다.
  • Safari : Safari 탭전환 혹은 비활성화 시 일시중지 됨. requestAnimationFrame도 일시 중지됩니다.
  • Opera : 웹킷 엔진이 도입된 이후 오페라는 크롬과 같은 동작을 보입니다. setInterval은 1000ms에 clamping이 적용되며, 탭이 비활성화되면 requestAnimationFrame이 일시 중지됩니다.

기타

  • 비활성 탭에서 타임아웃이1000ms에 여러 번 일어날 경우
    -
    부하와 배터리 사용양을 줄이기 위해서, 비활성화 탭들에서 타임아웃이 1초에 여러번 일어나지 않도록 “clamping” 됩니다.
    Firefox는 5버전부터 이 동작을 구현했습니다. (bug 633421참고, 1000ms 상수는 dom.min_background_timeout_value 설정을 통해 수정할 수 있습니다)
    Chrome은 11버전부터 구현했습니다 (crbug.com/66078).
    Android용 Firefox는 bug 736602 이후 버전 14부터 백그라운드 탭에 15분의 타임아웃을 사용하고, 완전히 unload도 할 수 있습니다.

참고

--

--

No responses yet