🦈 react

[React로 화이트보드] React에서 Canvas로 선그리기

읏차 2024. 1. 9. 17:11

개발환경은 React, Typescript, SCSS를 사용하여 시작했다. 처음에 tailwindcss를 사용하려 하였으나 Canvas picking을 위하여 랜덤color를 key값으로 사용해야 하는데 tailwind에서 이 부분을 처리하기가 난해하여 불가피하게 scss를 사용하기로 했다.

 

useEffect(() => {
    drawElement();
    window.addEventListener("mousemove", onMouseMove);
  }, []);

 

 

제일 먼저 마우스 이동에 따라 Canvas에 선을 그려주려했는데 선이 제대로 그려지지 않았다. 로그를 보니 마우스 이동시 마다 path를 배열에 추가하고 있는데 이 배열이 늘어나지 않는다. 이것저것해보고 고민하다보니 closure의 특성때문에 onMouseMove <-- 이 이벤트핸들러가 선언될때의 path값에서 변하지 않는게 문제였다. mouse의 위치값을 dependency array에 추가해주니 잘 동작했다.

 

  useEffect(() => {
    drawElement();
    window.addEventListener("mousemove", onMouseMove);
  }, [currentSite, isDrag]);

 

 

선은 잘 그려지는데 선이 조금만 늘어나도 브라우저가 급격하게 느려졌다. 이것저것 확인해봤는데 딱히 문제를 찾지 못하다가 useEffect의 return구문에서 이벤트핸들러를 해제하니 정상적으로 동작했다.

그런데 이상한점이 addEventListener 사용 시 핸들러함수를 익명함수를 쓰지않고 명시해주면 다음에 이벤트핸들러를 등록하더라도 같은 메모리를 참조하기 때문에 성능상에 문제는 없다고 알고 있었는데 이상했다. 고민해보니 이것도 closure 때문인것으로 추측된다. path정보를 lexical environment로 가지고 있기 때문에 핸들러가 등록될 때마다 다른 메모리에 계속해서 쌓이는 듯하다.

useEffect의 return 구문을 사용하면서 return이 실행되는 순간도 정확하게 알게되었다. 단순히 useEffect의 실행구문 이후에 return 이 실행되는 줄 알았는데, 그렇다면 바로 이벤트 핸들러를 지워주게 되는데 어떻게 동작이 되는건가 이상한 생각이 들어 확인해보니 dependency array가 비워져있다면 component가 unmount될 때 denpendency array에 상태값이 있다면 해당 상태가 변경되어 useEffect의 실행구문이 실행되기 전에 return안의 내용이 실행되고 그 이후에 useEffect의 실행구문이 실행되는 것을 알 수 있었다.

useEffect에서 이벤트핸들러를 사용할 시 주의하자