📢 들어가며
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을 사용하자.
'Javascript' 카테고리의 다른 글
[Javascript] EventTarget, Node, Element, HTMLElement 간단 정리 (0) | 2025.08.08 |
---|---|
[Javascript] 값이란 무엇인가? 값에 대해 더 알아보기 (0) | 2025.08.02 |
[Javascript] Tailwind와 함께 다크모드 구현 (0) | 2025.05.17 |
[Javascript] 원시타입에 전개연산자 사용 (0) | 2025.04.27 |
[Node] 이메일 전송 (0) | 2025.04.13 |