앞서서 먼저 useLayoutEffect
훅에 대해 알아보겠습니다. 위 사진은 리액트 훅의 플로우 다이어그램입니다. 보시면 Render 부분은 가상 돔을 통해 어떤 부분이 바뀔지 확인하고 화면을 그리기(paint) 시작합니다.
useEffect
hook은 화면을 그린 다음에 실행됩니다. 위 사진에서 렌더링 순서를 보면 name이 빈 값이었다가 화면을 paint 후에 useEffect
가 실행되고 이후에 리렌더링 됩니다. 이후 name이 jerry로 새로 paint 되어 잠시 깜빡이는 것이 보이게 됩니다.
useLayoutEffect
는 어떨까요? useLayoutEffect
는 화면을 그리기 전에 실행이 되어 렌더링 화면이 깜빡이는 모습을 볼 수 없습니다.
그렇다면 useLayoutEffect
는 언제 쓸까요? 화면의 깜빡임이 발생해 user experience
를 저하 시킬 때 사용하거나 간발에 차이로 리렌더링이 될 때 사용합니다.
이와 반대로 실행 순서를 뒤로 미루는 경우가 있는데 React 18에 새로운 훅인 useTransition
, useDefferValue
입니다. 위 사진을 확인해보면 10000개 수많은 데이터들을 출력하게 해뒀는데 이럴 경우 input의 setResult가
하나씩 렌더링 되어 렌더링 성능이 떨어집니다.
이것을 해결하기 위해 useTransition
훅이 나왔고 이것은 startTranstion
을 제공해서 바로 업데이트 되어야 할 것과 나중에 업데이트 될 것을 구분합니다. name은 input 값 타이핑 값이고 result는 결과 값입니다. 여기서 타이핑 값 name은 바로바로 렌더링이 되어야하고 result는 업데이트가 좀 느려도 되기 때문에 setResult만 startTransition으로 감싸줍니다. 이럴 경우 리액트가 내부 알고리즘에 의해 중요한 것을 먼저 처리하고 startTransition 내부는 딜레이를 줘서 한번에 처리합니다.
다만 startTransition
이 리액트에서 알아서 처리해준다고 모든 값들을 넣으면 안됩니다. input의 값을 넣어보면 위의 오른쪽 사진과 같은 문제점이 발생합니다. name의 값들을 나중에 처리해도 된다고 해석해서 이상한 값이 나오게 되는 것입니다. 그렇기 때문에 state들을 모두 startTransition에 넣으면 안됩니다.
결론적으로 우선순위가 낮은 것들을 startTransition
에 넣어 좋은 성능을 뽑아낼 수 있습니다. startTransition 앞에 loading은 startTransition을 실행되기 전까지 텀들이 있는데 loading창을 표시하고 싶다면 사용하면 됩니다.
useDeferredValue
는 보통 useMemo
와 함께 많이 사용합니다. 리액트 공식문서에서도 useMemo와 사용을 권장하고 있습니다. 위와 같이 10000번을 반복하기 때문에 랙이 발생하는데 usetransition을 쓰지 않기 때문에 name은 중요하고 result는 중요하지 않다는 것을 표기하지 못합니다. 근데 이걸 덜 중요하게 만들 수 있는 훅이 useDeferredValue
입니다. useDefferedValue
로 만들면 deferredName은 덜 중요한 상태가 됩니다. 따라서 리액트가 판단해서 성능에 여유가 있을 때 덜 중요한 deferredName을 업데이트를 하게 됩니다.