requestAnimationFrame
브라우저의 프레임 처리 방식
브라우저는 화면에 표시되는 내용을 일정한 간격으로 업데이트한다. 일반적으로 초당 60프레임(60fps)으로 화면을 갱신하며, 이는 약 16.66밀리초마다 한 번씩 화면을 새로 그린다는 말이다.
requestAnimationFrame의 동작 원리
requestAnimationFrame()
은 브라우저의 다음 리페인트 주기 전에 전달된 콜백 함수를 실행한다. 즉, 브라우저가 프레임을 생성하기 직전에 애니메이션 업데이트가 이루어지도록 예약된다.
이렇게 함으로써 애니메이션 코드가 브라우저의 리페인트 주기와 정확하게 동기화되어 프레임 드롭이나 끊김 없이 부드러운 애니메이션이 구현된다.
setTimeout()과 setInterval()의 문제점
setTimeout()
과 setInterval()
은 특정 시간 간격으로 함수를 실행하지만, 이 시간 간격은 브라우저의 리페인트 주기와 동기화되지 않는다. 예를 들어, setInterval
을 16ms 간격으로 설정하더라도 브라우저가 정확히 그 간격으로 리페인트하지 않을 수 있다. 따라서 일부 콜백이 리페인트 주기와 일치하지 않으면 프레임 드롭이나 끊김 현상이 발생할 수 있다.
- 프레임 드롭:
setTimeout()
과setInterval()
은 특정 시간 간격으로 함수를 실행한다. 그러나 이 간격이 정확하지 않아서 프레임이 일정하지 않고, 결과적으로 애니메이션이 끊기는 현상을 초래할 수 있다. - 부드러운 애니메이션 구현 어려움: 브라우저는 일반적으로 60fps(초당 60프레임)로 화면을 업데이트한다.
setTimeout()
이나setInterval()
은 브라우저의 리페인트 주기와 일치하지 않아서 부드럽지 않은 애니메이션이 생성될 수 있다. - 비효율적인 프레임 생성: 애니메이션 주기를 16.6ms 미만으로 설정하면 불필요한 프레임이 생성될 수 있다. 이는 오버헤드를 증가시키고 애니메이션의 효율성을 저하시킬 수 있다.
requestAnimationFrame의 장점
- 프레임 동기화
requestAnimationFrame()
은 브라우저의 리페인트 주기와 동기화되어 호출되기 때문에 프레임 드롭을 방지하고 애니메이션이 더 부드럽게 실행된다.- 적응형 프레임률
- 모니터 주사율에 맞춰 프레임률을 자동으로 조정한다. 예를 들어, 모니터가 120Hz를 지원하면 120fps로 애니메이션을 실행한다.
- 효율적인 리소스 사용
- 브라우저가 애니메이션을 렌더링하는 동안에만 콜백을 실행하므로, 비활성화된 탭에서는 애니메이션이 자동으로 일시 중지되어 리소스를 절약할 수 있다.
References
- https://simsimjae.tistory.com/402
- https://velog.io/@koseungbin/Web-Animation-sz0ggmnk
- https://www.youtube.com/watch?v=TRWbGGRvX0Y
- https://jae-kwang.github.io/blog/2019/01/28/requestAnimationFrame
(실제 업무에서 Type Guard를 사용하게 된 경험)
Issue
슬라이드 이미지의 위치와 zoom level이 올바르게 유지되지 않는다.
Case 1.
Case2.
Expected Result
슬라이드 이미지 Toggle 시 기존에 보고 있던 위치와, zoom level을 기억하고 있어야 한다.
Actual Result
슬라이드 이미지 Toggle 시 zoom level이 증가하거나 감소함.
Cause
AI Result에 따라 오른쪽 Action Panel이 마운트 혹은 언마운트 되면서 Viewport가 달라진다.
Conclusion
requestAnimationFrame()
을 사용해 브라우저가 리페인트 되기 전에 해당 애니메이션을 업데이트 했다.