밝을희 클태

<Canvas> 애니메이션 중단 시 requestAnimationFrame()의 비동기 문제 해결 본문

사이드 프로젝트/도라에몽 잡기 [React]

<Canvas> 애니메이션 중단 시 requestAnimationFrame()의 비동기 문제 해결

huipark 2024. 11. 3. 00:03

Canvas로 도라에몽을 움직이는 애니메이션을 구현하던 중, 도라에몽을 잡으면 게임이 종료되고 ‘클리어’ 표시가 나오는 기능을 추가하려고 했다. 그러나 이 과정에서 다음과 같은 문제가 발생했다

문제

게임 종료 조건이 충족되면 setIsSuccess(true)가 호출되어 isSuccess 상태가 true로 변경되고, Canvas를 담당하는 useEffect의 리렌더링이 발생한다.

리렌더링 후 useEffectclean-up 함수에서 clearRect()Canvas를 지우도록 구현했지만, 이전 애니메이션 프레임들이 남아 있어 피격 효과와 이미지가 전부 지워지지 않아 Canvas가 멈춘 듯 보인다.

원인

requestAnimationFrame을 사용하여 애니메이션을 구현할 때는 브라우저 렌더링 스케줄에 따라 애니메이션 프레임이 예약된다. 문제가 발생한 이유는 useEffectclean-up 함수가 실행될 때 이미 예약된 애니메이션 프레임이 남아 있어, clearRect() 호출 이후에도 애니메이션이 계속 실행되기 때문이다.

해결법

  • useRef로 애니메이션 상태 관리: isSuccess 상태는 useState가 아닌 useRef로 관리하여, 리렌더링 없이도 현재 게임 종료 상태를 바로 감지할 수 있도록 했다.
  • 조건부 애니메이션 실행: requestAnimationFrame을 호출할 때 isSuccessRef.current를 확인해 게임 종료 시 애니메이션이 중단되도록 처리했다.
  • clean-up 함수에서 애니메이션 요청 취소: 리렌더링이 발생하면 useEffect의 clean-up 함수가 cancelAnimationFrame을 호출해 모든 애니메이션 프레임 요청을 취소하도록 했다.

해결!