728x90
반응형

크롬 비활성 탭에서 setInterval이 1분으로 변하는 이유

 

웹 개발하다 보면 이런 거 한 번쯤 겪는다.

setInterval을 5초로 돌려놨는데
어느 순간부터 1분마다 실행됨

다시 탭 눌러도 바로 안 돌아오고
그대로 계속 느리게 돌아가는 경우도 있음

이거 버그 아니고 크롬 정책이다.

 

아래 크롬 디버깅에서 실시간으로 탭 상태를 확인해볼수도 있다.

chrome://discards/


반응형

문제 상황

이런 코드가 있다고 치자

setInterval(() => {
  console.log("실행");
}, 5000);

 

정상이라면 5초마다 찍혀야 한다.

근데 탭을 다른 데로 넘기면

  • 처음엔 정상
  • 어느 순간부터 60초로 바뀜
  • 다시 돌아와도 그대로 유지되는 경우 있음

왜 이러냐

크롬이 일부러 그렇게 만든거다.

탭이 화면에 안 보이면
CPU 아끼려고 타이머를 제한한다.

핵심은 이거 하나임

백그라운드 탭에서는 타이머 최소 실행 간격이 1분까지 늘어날 수 있음

그래서 5초로 줘도 실제로는 60초로 실행된다.

 


상태 개념 간단 정리

크롬에는 페이지 상태가 있다

  • active → 화면에 보이는 상태
  • hidden → 백그라운드
  • frozen → 거의 멈춘 상태

hidden부터 이미 타이머 제한 걸린다.


중요한 포인트

이게 더 문제다.

탭을 다시 눌러서 active로 바꿔도
타이머가 즉시 정상으로 안 돌아올 수 있다.

그래서

  • 몇 시간 켜둠
  • 다시 돌아옴
  • 여전히 1분으로 돌아감

이런 상황이 실제로 발생한다.


해결 방법

이건 막는 게 아니라 대응해야 한다.

1. visibilitychange로 감지

document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "visible") {
    restartTimer();
  }
});

 

2. 타이머 재생성

let interval;

function startTimer() {
  interval = setInterval(() => {
    console.log("실행");
  }, 5000);
}

function restartTimer() {
  clearInterval(interval);
  startTimer();
}

이거 안 하면 계속 1분 유지되는 경우 있음

 

3. 시간 차이로 이상 감지

let last = Date.now();

setInterval(() => {
  const now = Date.now();

  if (now - last > 10000) {
    console.log("타이머 꼬임");
    location.reload();
  }

  last = now;
}, 5000);

타이머가 밀리면 강제로 복구하는 방식

 

4. setTimeout 루프로 바꾸기

function loop() {
  setTimeout(() => {
    console.log("실행");
    loop();
  }, 5000);
}

loop();

상황에 따라 이게 더 안정적일 때도 있다.


못하는 것

비활성화 안 되게 하는 거

이건 거의 불가능하다.

  • 소리 재생 → 일부 효과 있음
  • 강제 활성화 → 안됨

브라우저 정책이라 못 막는다.

 


정리

  • 크롬은 백그라운드에서 타이머를 강제로 늦춘다
  • 다시 활성화해도 자동으로 정상 복구 안 될 수 있다
  • 그래서 반드시 복구 로직을 넣어야 한다

한 줄 요약

setInterval은 정확하지 않다.
특히 백그라운드에서는 더 그렇다.

728x90
반응형

+ Recent posts