본문 바로가기

프론트엔드/React

useLayoutEffect로 최초 렌더링 UX 개선하기

반응형
  • 프로젝트: 공우 홈페이지
  • 키워드: useLayoutEffect, useEffect, react hook flow
  • 상황
    1. 공우 홈페이지에서 한글/영어 번역을 지원하고자 한다.
    2. 기획상 한글/영어 페이지를 각각의 URL로 분리하는 것이 아니라, 하나의 페이지에서 상태 값을 이용하여 언어를 결정한다. (다크모드와 비슷한 구조)
      상단 우측 ENG/KOR toggle 버튼
    3. 현재 언어를 localStorage에 저장해두어 새로 고침을 하거나 사이트를 벗어났다가 돌아와도 언어가 유지되도록 구현했다.
        const [language, setLanguage] = useState<Language>('Korean'); // 기본 값은 Korean
      
      useEffect(() => {
        setLanguage(localStorage.getItem('language') ?? 'Korean');
      }, []);​
    4. 언어를 '영어'로 설정하고 새로고침을 하면, 기본값인 '한글'로 잠깐 보였다가 useEffect hook으로 인해 영어로 바뀌면서 화면이 깜빡이는 현상이 발생했다.
  • 해결 방법
    1. React hook 중에서 useEffect를 사용한 렌더링이 문제를 일으키고 있으니, 그와 비슷한 useLayoutEffect에 대해 알아보았다.
      https://ko.reactjs.org/docs/hooks-reference.html#uselayouteffect
      useLayoutEffect의 내부에 예정된 갱신은 브라우저가 화면을 그리기 이전 시점에 동기적으로 수행될 것입니다.
    2. 위의 문서를 더 자세히 이해하기 위해 React Hook을 이용하여 화면을 렌더링하는 과정을 알아보았다.

      React Hook Flow Diagram
      Diagram과 같이 React가 렌더링되고 -> DOM을 업데이트하고 -> 그 내용을 실제로 스크린에 paint 한 후 -> useEffect 를 실행한다.
      즉, 상황 3에서 '한글'로 먼저 렌더링, DOM update, paint까지 끝낸 후에야 상태값을 '영어'로 바꾸고 리렌더링이 일어나기 때문에 깜빡임이 발생하는 것이다.
      하지만 useLayoutEffect를 사용하면 렌더링 -> DOM 업데이트 -> useLayoutEffect에서 동기적으로 리렌더링 -> 그 내용을 스크린에 paint -> useEffect이 있다면 실행하기 때문에 화면 깜빡임없이 영어로 번역된 화면을 볼 수 있게 된다.
    3. 실제로 아래 코드를 실행하면,
        const [state, setState] = useState(false);
      
      console.log('render');
      
      useEffect(() => {
        console.log('effect');
      }, []);
      
      useLayoutEffect(() => {
        console.log('layout effect');
        setState(!state);
      }, []);​

      render -> layout effect -> effect -> render 순서로 log가 찍히는 것을 확인할 수 있다!

 

 

 

반응형