본문 바로가기
JavaScript

JavaScript - 애니메이션 최적화하기 (requestAnimationFrame)

by 새발개발JA 2024. 2. 1.
반응형

 

 

 

 

자연스러운 애니메이션을 구현하기 위해 사투를 벌인 스토리를 포스팅해보려고 한다

 

애니메이션은 여러 사진을 연속적으로 연결한 것이다. 그리고 그 사진을 프레임(Frame) 이라고 한다

1초 동안 보여줄 수 있는 최소한의 자연스러운 프레임의 갯수는 60 프레임 정도가 된다

그래서 Frame Per Seconds 라고 해서 60fps 라고도 한다

 

시계침 애니메이션을 구현하는 중이었다. 초침의 경우 초단위로 360도씩 돈다

처음에는 타이머 함수인 setInterval()를 사용하였더니 이슈가 생겼다

다른 이벤트와 겹치니 1초마다 움직여야할 애니메이션이 누락되어 뚝뚝 끊겨버렸다

 

JavaScript 로 애니메이션을 실행하면 Reflow 가 일어난다. (애니메이션으로 인해 Dom이 변경되기 때문에)

"Reflow" 로  { 레이아웃 - 리페인트 - 컴포짓 } 의 과정을 다시 수행하게 되면서

타이머의 시간이 수행시간보다 빠르다면 프레임이 누락되는 일이 발생하였다 🤔

 

  useEffect(() => {
    const interval = setInterval(() => {
      setRotate(seconds * 6); // 1초에 6도씩 움직인다
    }, 60);

    return () => clearInterval(interval);
  });

 

 

고민이 되는 순간, 
requestAnimationFrame 함수를 사용하여
누락없이 매끄러운 애니메이션을 구현할 수 있었다

 

 

JavaScript - 애니메이션 최적화하기 (requestAnimationFrame)

 

setInterval 대신 requestAnimationFrame 함수를 사용하여 누락없이 매끄러운 애니메이션을 구현할 수 있었다

useEffect(() => {
    const animateClock = () => {
      setRotate(seconds * 6);
      requestAnimationFrame(animateClock); // 재귀호출
    };

    const animationID:number = requestAnimationFrame(animateClock); // 변수 할당과 동시에 함수 호출
    return () => cancelAnimationFrame(animationID); // 클린업함수
  });

 

요 함수는 최적화된 애니메이션 타이밍에 맞춰 호출해준다. 한마디로 알아서 1초에 60 프레임씩 실행해주는거다 😃

일정한 간격으로 리페인트 전에 렌더링이 되도록 보장해주어서 프레임 누락이나 밀림 현상을 방지해준다

또한 백그라운드에서는 브라우저에 의해 일시 중지된다 → CPU 리소스나 배터리 수명을 낭비하지 않는다

(setInterval 같은 경우 계속 타이머가 돌아 콜백을 호출 → CPU 리소스나 전력 낭비 )

 

 

1. 함수가 실행되면

2. 브라우저는 다음 프레임이 그려지기 전에 함수를 실행하도록 예약한다

3. 각 프레임이 정확히 16.6ms 간격으로 렌더링 된다 

 

 

 

** 일반적으로 디스플레이 refresh rate 에 맞추어 실행된다. 60hz(초당 60사이클/프레임)이지만 75hz, 120hz 및 144hz도 사용된다

 

 

 

 

 

 

 

반응형

댓글