본문 바로가기

React

[React] useEffect vs useLayoutEffect: Panning 기능 개선 사례

두 문서나 이미지 등을 비교하는 뷰어에 Panning 기능이 있는데, 최근에 이 기능에 대한 개선요청이 들어왔다.
요청사항은 아니었지만 기능을 살펴보던 중 두 작업물에 싱크가 걸려있는 상태에서 Panning 기능을 수행하면, 싱크가 깨지는 문제를 발견했다. 또 각 뷰어에 중복된 코드가 존재해서 코드 공통화와 함께 싱크 문제를 해결해보기로 했다.

 

싱크 문제 해결: useEffect 활용

useEffect(() => {
  element?.style.transform = `matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ${xx}, ${yy}, 0, 1)`;
  element_right?.style.transform = `matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ${xx_right}, ${yy_right}, 0, 1)`;
}, [xx, yy, xx_right, yy_right, element, element_right]);

동일한 useEffect 블록에서 elementelement_right를 모두 업데이트 하고 있기 때문에 문제가 있을 수 있겠다 라고 생각했는데 아니나 다를까 싱크는 되지만 움직일 때 딜레이가 발생하는 것처럼 보였다.

 

딜레이 문제 해결: useLayoutEffect 활용

useLayoutEffect(() => {
    element?.style.transform = `matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ${xx}, ${yy}, 0, 1)`;
    element_right?.style.transform = `matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ${xx_right}, ${yy_right}, 0, 1)`;
}, [xx, yy, xx_right, yy_right, element, element_right]);

useEffect는 비동기로 실행되는 훅으로 렌더링 이후에 실행되는 반면,
useLayoutEffect는 동기로 실행되는 훅으로 렌더링 이후에 화면에 그려지기 전에 실행된다.
따라서, 두 element의 값이 전부 바뀐 후 paint되서 화면상의 딜레이가 사라진 것처럼 보였다.

 

주의사항

useLayoutEffect에 대한 공식문서(https://react.dev/reference/react/useLayoutEffect)를 읽어보면 제일 상단에 성능을 저하시킬 수 있기 때문에 가능하면 useEffect를 사용하라고 쓰여있다.
이번 경우엔 문제 없이 쓸 수 있었는데 사용할 땐 항상 신중히 사용하는게 좋을 것 같다.