본문 바로가기
Javascript

[Javascript] setInterval과 requestAnimationFrame

by 맨날개발 2025. 8. 3.

📢 들어가며

requestAnimationFrame(이하 rAF)이 등장하기 전에는 setInterval을 활용해 애니메이션을 구현했다.

하지만 rAF이 등장고나서부터는 부드러운 애니메이션을 구현하기 위해 rAF를 주로 사용하게 되었다. 어떤 차이가 존재하는지 알아보자.

 

 

🎤 호출 타이밍

두 함수 모두 특정 트리거에 따라 호출될 함수를 예약한다.

setInterval은 지정된 시간 간격마다 타이머 이벤트가 트리거되어 반복적으로 콜백을 호출한다.

rAF는 브라우저의 VSync 신호를 트리거로 하여 다음 리페인트 시점에 맞춰 콜백을 한 번 실행한다.

 

예를 들어, 아래와 같이 간격을 설정하면 1초에 약 60번 호출되어 60프레임의 애니메이션을 표현할 수 있다.

setInterval(() => {

}, 1000 / 60);

 

setInterval의 문제는 VSync와 무관하게 실행된다는 것이다.

임의로 1000 / 60와 같은 간격을 설정하더라도 매 VSync 타이밍에 정확히 맞춰 실행된다는 보장은 없다.

이 말인 즉, 디스플레이 프레임 갱신 주기와 동기화되지 않기 때문에, 실제 애니메이션 프레임이 어긋날 가능성이 높다.

 

 

rAF와 setInterval 모두 메인 스레드가 바쁘면 프레임 드랍이 발생할 수 있다.

하지만 차이점은 다음과 같다.

  • rAF는 메인 스레드의 작업이 끝난 직후, 가장 가까운 VSync 타이밍에 맞춰 실행이 보장된다.
  • setInterval은 지정한 시간 간격이 되면 즉시 실행을 시도하지만, 이 시점에 메인 스레드가 바쁘면 실행이 밀리게 된다

 

아래와 같이 콘솔을 확인해보면 실제로 16.7 보다 적은 간격에 호출이 되기도 하고, 큰 간격에 호출이 되기도 한다.

setInterval(() => {
  console.log(performance.now());
}, 1000 / 60);

 

아래 코드는 rAF와 setInterval을 사용하여, 10초 동안 각 프레임마다 1px씩 공을 이동시키는 애니메이션을 구현한 예제입니다.

 

See the Pen Untitled by suld2495 (@suld2495) on CodePen.

 

 

위 코드를 실행 해보면 rAF의 동작에 비해 setInterval의 동작은 끊김이 보인다. 왜냐하면, 1 프레임에 두번 호출되는 경우가 존재하기 때문이다.

 

 

🎧 탭 비활성화 시

setInterval은 탭이 비활성화되는 경우 지속적인 실행을 최소 1000ms 간격으로 제한한다. 그 이하에서는 1000ms 간격을 가지게 된다.

setInterval(() => {
  console.log(performance.now());
}, 1000 / 60);

 

코드 실행 후 다른 탭으로 이동한 상태에서 콘솔을 확인해보면 1초 간격으로 출력되는 것을 확인할 수 있다.

 

rAF는 탭이 비활성화되는 경우 호출 자체가 되지 않는다.

const animateRAF = () => {
  console.log(performance.now());
  requestAnimationFrame(animateRAF);
}

animateRAF();

 

rAF는은 화면에 무언가를 렌더링할 때 호출되도록 설계된 API이기 때문에, 탭이 비활성화된 상태에서는 렌더링할 필요가 없어 브라우저가 이를 자동으로 멈추도록 최적화한다.

 

 

 

🎯 정리

  • 애니메이션을 표현하기 위한 용도로는 setInterval 대신 requestAnimationFrame을 사용하자.