javascript

RequestAnimationFrame이란

하리하링웹 2024. 4. 25. 22:30

개요

프론트엔드에서 애니메이션을 구현할 때 CSS를 사용하는 방법을 주로 사용하지만 Javascript를 사용하는 방법도 있다.

 

물론 CSS에 비해 Javascript는 성능이 떨어지지만 모든것을 CSS로 해결할수 는 없기에 Javascript 를 사용해야만 하는 경우가 있으며 requestAnimationFrame Javascript로 애니메이션을 구현할 때 성능과 UX를 최적화 하기에 좋은 함수이다.

 

requestAnimationFrame는 사용시에 브라우저에게 작업의 실행을 알려주며 내부적으로  requestAnimationFrame 전용 queue에 해당 작업을 집어넣는다.

이후 해당 작업은 대기하고 있다가 다음 repaint 작업 전에 해당 큐의 작업을 처리해주는 방식으로 동작한다. 

 

이를통해 requestAnimationFrame은 브라우저의 repaint 주기에 딱 맞게 함수가 실행되어 프레임 드랍이 일어나지 않도록 도와주는 역할을 해준다.

 

 

사람의 눈은 일반적으로 1초에 60개의 장면이 지나가야 부드럽다고 느끼기에 대부분의 디스플레이는 초당 60번의 화면을 다시 그리도록 설계된다.

브라우저 또한 마찬가지이며 자바스크립트로 애니메이션을 만들어 사용자에게 부드럽다고 느끼게 하려면 1초에 60번 즉 16.6ms마다 코드를 호출하는 식으로 구현해야한다.

  • 사용자의 모니터 주사율에 따라 달라질 수 있음

문법

requestAnimationFrame(callback)

 

 

Argument

  • timestamp: requestAnimationFrame의 실행 시간

Return

  • key: requestAnimationFrame을 식별하는 0이 아닌 정수 값, 이를 사용하여 window.cancelAnimationFrame통해 callback 실행을 취소할 수 있다.

setInterval? setTimeout?

그러면 굳이 requestAnimationFrame 을 사용하지 않고 setTimeout과 setInterval을 사용해서 구현하면 되지 않나?

const performAnimation = () => {
  setTimeout(performAnimation, 1000 / 60);
}

setTimeout(performAnimation, 1000 / 60);

or
const performAnimation = () => {
	...
}
setInterval(performAnimation, 1000 / 60)

하지만 위 두 개의 함수는 1초에 60번을 실행하는 것이 목적이 아니라 단순 지연 시간에 따라 실행되기에 프레임 단위로 실행되는 것을 보장하지 못한다.

 

이는 자바스크립트의 이벤트 루프의 동작을 자세히 알면 더 쉽게 이해할 수 있으며 이는 다음 글에 다루도록 하겠다.

 

어찌 됐건 자바스크립트의 이벤트 루프의 동작 방식으로 인해 프레임 드랍이 일어날 수 있으며 이를 방지하기 위해 브라우저가 다음 프레임을 그리기 전에 실행하여 브라우저 프레임에 맞는 주기의 실행을 보장해주는 requestAnimationFrame을 사용해야 한다.

  let start = new Date().getTime();
  let count = 0
  let callback = function() {
    let ts = new Date().getTime();
    if (ts - 1000 <= start) {
      console.log(count++);
      requestAnimationFrame(callback);
    }
  }
  requestAnimationFrame(callback);

// result
...

58
59 // 60번만 실행되는 모습, setTimeout으로 했을경우 1초 내에 실행될 수 있는만큼 실행함

 

위 코드에서 보이듯이 requestAnimationFrame은 1초에 해당 모니터의 주사율에 수치만큼만 함수를 실행해준다.

장점

  1. 브라우저 탭이 백그라운드에 있는 경우 페이지 화면을 그리는 작업이 브라우저에 의해 일시 중지 되기때문에 requestAnimationFrame의 실행이 중단되어 자원을 절약할 수 있다.
  2. 사용자 디스플레이 주사율에 맞게 실행
    • 사용자가 144hz의 모니터를 사용한다면 requestAnimationFrame은 1초에 144번 실행되어 더 부드러운 화면을 제공해준다.
  3. Animation frames큐 사용
    • 이는 비동기 작업으로 처리되지만 일반적인 task queue가 아니라 animation frame queue 에서 처리된다. 즉 별도의 큐를 사용하기 때문에 실행이 미뤄지는 현상을 줄일 수 있다.

단점

사실 잘 사용한다면 단점은 없다고 말할 수 있지만 그나마 단점이라고 말할 만한 항목들이다.

  • 프레임에 의존적
  • 정확한 타이밍 조절이 어려움