일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- create-next-app
- mock date
- nextjs
- nextjs-performance
- 프로그래머스
- Hermes Engine
- 통신망분석
- 구름톤챌린지
- 구름톤
- JavaScript
- mutationobserver
- 귤 고르기
- 리액트네이티브
- 최솟갑 구하기
- 테이블 해시 함수
- 리액트네이티브 엔진
- 중첩 점
- 구름톤 챌린지
- 과제 진행하기
- Leetcode #javascript #알고리즘 #Algorithms #js
- ResizeObserver
- 날짜 테스트
- Jest uuid syntax
- jest
- 연결 요소 제거하기
- 자바스크립트
- 호텔 대실
- Google 애널리틱스
- 테스트 Date
- 헤르메스 엔진
- Today
- Total
나만보는개발공부블로그
React에서의 RequestAnimationFrame 사용법 본문
requestAnimationFrame이 setTimeOut이나 setInterval보다 더 최적화된 렌더링 업데이트 시간과 스무스한 애니메이션 기법을 만들어낼수있다고 하는데 실제로 어떻게 사용되는지 알아볼려고합니다.
먼저 requestAnimationFrame에 대해서 알아봅시다.
RequestAnimationFrame
웹페이지의 애니메이션을 구현할 때 CSS의 animation, transition, transform 속성을 통해 구현할 수도 있고 Javascript와 함께 사용해서 변화시켜서 구현합니다. 자바스크립트로 하나씩 속성을 변화시키는방법은 성능에 좋지않는데 이럴때 requestAnimationFrame으로 처리하면 더 성능좋은 애니메이션을 만들어 낼 수 있다고 합니다.
requestAnimationFrame에서 Frame단위로 callback을 실행하게되는 특징이 있는데 60Hz의 모니터면 60번의 프레임 단위로 실행합니다.
* 다른 setTimeOut이나 setInterval의 경우 프레임 단위로 실행되는게 아니라서 브라우저에 만약 다른 작업 수행으로 지연되어 버리게 되고 자연스러운 렌더링 업데이트가 불가능하게 된다는 점이 있다. 이전에 배운 Reflow가 일어나버려서 레이아웃계산하고 리페인트 과정이 발생해버려 프레임이 깍여버리는 현상이 나타나게 됩니다.
rAF를 사용하면 밀림현상을 방지해주고 브라우저가 프레임 주기에 맞춰 일정한 간격으로 렌더링 되는것을 보장해줍니다.
그리고 현재 실행중인 페이지가 비활성화 된 상태이면 화면 그리기 작업도 브라우저에 의해 일시 중지되서 CPU 리소스도 낭비하지 않게 됩니다. 디스플레이 주사율에 맞게 호출 횟수가 결정되서 만약 144hz 주사율을 사용하는 모니터에서는 144초 호출되는 현상이 있지만 이러한 방법들은 쓰르톨링기법으로 해결할 수 있습니다.
자바스크립트의 동작 방식에서 microTaskQueue, MacroQueue 그리고 Animation Frames(브라우저 렌더링과 관련된 태스크 처리)가 존재했엇는데 rAF도 비동기 로 분류되 처리되고 여기서 AnimationFrame에 따로 이벤트 루프에 의해 꺼내져서 실행이 뒤쳐지거나 하는 현상을 막을 수 있습니다.
사용 방법은 재귀 호출 하는식으로 처리하는데 브라우저는 애니메이션 프레임을 출력할때 마다 rAF에 등록된 콜백 함수들을 비동기로 호출해서 애니메이션을 부드럽게 출력합니다.
const callback = (timestamp) => {
...
requestAnimationFrame(callback);
}
requestAnimationFrame(callback);
애니메이션을 중지할때는 cancelAnimationFrame으로 requestAnimationFrame을 담는 변수를 넘겨줌으로써 취소할 수 있습니다. callback으로 받는 인자 timestamp는 DOMHightResTimeStamp로 콜백함수가 큐에 의해 실행되는 시점에서의 시간을 보여줍니다.
rAF가 어떤 개념인지 어느정도 알게되었고 이제 React에서는 어떤식으로 사용할지 알아보겠습니다.
React에서의 requestAnimationFrame
리액트에서는 useEffect 훅을 통해서 animation을 함수형 컴포넌트에 requestAnimationFrame을 만들어 낼수 있습니다.
예시로 아래와 같이 코드를 작성할 수 있을것같습니다.
function ExampleComponent() {
const requestId = useRef();
const animate = (timestamp) => {
...
requestId.current = requestAnimationFrame(animate);
};
useEffect(() => {
requestId.current = requestAnimationFrame(animate);
return () => {
cancelAnimationFrame(requestId.current);
};
}, []);
return (
...
);
}
useEffect의 return으로 unmount될시에 rAF를 취소시키고 rAF의 requestId는 useRef 훅으로 저장되고 다시 렌더링되는것을 방지시킬 수 있습니다.
실제 사용 예시로는 스크롤 이벤트를 처리할때 rAF를 사용해서 더 나은 최적화를 만들어 낼 수 있을것같습니다.
function ExampleComponent() {
const requestId = useRef();
const scrollEvent = (timestamp) => {
//scroll event here.
requestId.current = requestAnimationFrame(animate);
};
useEffect(() => {
widnow.addEventListener('scroll', scrollEvent);
return () => {
cancelAnimationFrame(requestId.current);
window.removeEventListener('scroll', scrollEvent);
};
}, []);
return (
...
);
}
리액트 애니메이션 라이브러리 살펴보기
rAF말고도 다른 리액트 애니메이션에 사용하기 위한 라이브러리들이 존재하는데
1. Animated (https://github.com/animatedjs/animated) - 크로스 플랫폼 지원 (리액트 네이티브에서 주로 사용했었습니다)
2. react-motion (https://github.com/chenglou/react-motion) - 스프링 관련 애니메이션 특화(?)된 라이브러리라고 생각됩니다.
3. Framer-motion (https://github.com/framer/motion) - 쉬운 문법, 내장된 SVG 애니메이션 호환 등이 있습니다. (최근에 인기가 많은듯??)
4. react-spring (https://github.com/pmndrs/react-spring) - 가장 인기있는 리액트 애니메이션 라이브러리라고 생각되고 물리 기반 애니메이션이나 복잡한 애니메이션 등 크로스 브라우저, 디바이스도 호환된다고 합니다.
5. Remotion (https://github.com/remotion-dev/remotion#readme) - 브라우저에서 비디오 생성, 애니메이션 등 강력한 라이브러리입니다.
위의 라이브러리 깃헙에서 코드들을 살펴보니 react-motion로 raf라는 라이브러리로 requestAnimationFrame polyfill된 버전으로 다른 브라우저 호환성을 위해서 사용되고 있습니다.
* framer-motion의 경우 rAF가 아니라 자체적으로 Queue를 두개 만들어서 frame의 개념을 사용하는듯합니다. https://github.com/framer/motion/blob/main/packages/framer-motion/src/frameloop/render-step.ts
'Web Development > Front' 카테고리의 다른 글
[RN] 리액트 네이티브에서 환경 변수 처리 (1) | 2024.01.09 |
---|---|
프론트엔드관점에서 헤더 보안 처리 (0) | 2023.12.04 |
Cookie (1) | 2023.11.26 |
React에서의 css최적화 (0) | 2023.11.23 |
Reflow와 Repaint 그리고 css관련 브라우저 최적화 (1) | 2023.11.23 |