Notice
Recent Posts
Recent Comments
관리 메뉴

즐겁게, 코드

useLayoutEffect 훅에 대하여 본문

🎨 프론트엔드/React.js

useLayoutEffect 훅에 대하여

Chamming2 2021. 2. 15. 23:20

최근 깃허브 스타 1k를 돌파한 hook-flow 라는 프로젝트가 있습니다.

리액트 훅의 모호한 실행 순서가 보기좋게 정리되어 있어 저도 이미지를 저장해서 보고 있습니다. 😁

그런데 이상하게도, LayoutEffects라는 낯선 이름이 하나 보이네요.

오늘은 useLayoutEffect 라는 생소한 훅을 소개해 보겠습니다.

useLayoutEffect

useLayoutEffect(() => {
  effect
  return () => {
    cleanup
  };
}, [input])

useLayoutEffect를 인텔리센스가 자동으로 완성한 모습입니다.

그런데 어디서 많이 본 형태 아닌가요?

useEffect(() => {
  effect
  return () => {
    cleanup
  }
}, [input])

맞습니다! useEffectuseLayoutEffect 훅의 형태는 완전히 동일합니다.

그럼 이 둘의 차이점이 무엇인지 알아보도록 하겠습니다.

이펙트의 호출 시기

잠깐 리액트 공식 문서 중 useEffect의 설명을 짚고 가겠습니다.

useEffect 훅을 사용할 경우 DOM의 레이아웃 배치와 페인트가 끝난 후 이펙트 함수를 호출하는데요, 따라서 상태값이 이펙트에 의존할 경우 약간 불편한 사용자 경험으로 이어질 수 있습니다.

import { useEffect, useState } from "react";

function App() {
  const [age, setAge] = useState(0);
  const [name, setName] = useState("");
  
  useEffect(() => {
    setAge(25);
    setName("찬민");
  }, []);
  
  return (
    <>
      <div className="App">{`그의 이름은 ${name} 이며, 나이는 ${age}살 입니다.`}</div>
    </>
  );
}

export default App;

useEffect를 사용한 위 코드는 다음 순서대로 동작합니다.

 

1. <div>그의 이름은 이며, 나이는 0살 입니다.</div> 를 페인트

2. 이펙트 내부의 setNumber, setName 호출

3. 재렌더링 수행 -> <div>그의 이름은 찬민이며, 나이는 25살 입니다.</div>

눈썰미가 좋으신 분이라면 데이터가 바뀜을 눈치챌 수 있을 것입니다.

물론 이렇게 간단한 DOM 구조라면 금방 렌더링할 수 있겠지만, 화면이 복잡해지면 체감할 수 있을 정도로 렌더링 시간이 증가하게 됩니다.

그럼 사용자는 화면에서 "그의 이름은 이며, 나이는 0살 입니다." 라는 텍스트를 오랫동안 보면서 만감이 교차하겠죠.

 

useLayoutEffect 훅은 바로 이런 문제를 해결하기 위해 등장한 훅입니다.

import { useLayoutEffect, useState } from "react";

function App() {
  const [age, setAge] = useState(0);
  const [name, setName] = useState("");

  useLayoutEffect(() => {
    setAge(25);
    setName("찬민");
  }, []);

  return (
    <>
      <div className="App">{`그의 이름은 ${name} 이며, 나이는 ${age}살 입니다.`}</div>
    </>
  );
}

export default App;

레이아웃 이펙트는 브라우저가 화면에 DOM을 그리기 전에 이펙트를 수행하는데요, 따라서 위 코드의 실행 순서도 달라지게 됩니다.

 

1. 레이아웃 이펙트 내부의 setNumber, setName 호출

2. <div>그의 이름은 찬민이며, 나이는 25살 입니다.</div> 를 페인트

어떤가요? 더이상 "그의 이름은 이며, 나이는 0살 입니다." 이라는 텍스트가 황급히 데이터를 교체하는 모습을 보지 않아도 됩니다.

TL;DR

- useEffect의 이펙트는 DOM이 화면에 그려진 이후에 호출된다.

- useLayoutEffect의 이펙트는 DOM이 화면에 그려지기 전에 호출된다.

- 따라서 렌더링할 상태가 이펙트 내에서 초기화되어야 할 경우, 사용자 경험을 위해 useLayoutEffect를 활용하자!

 

반응형
Comments
소소한 팁 : 광고를 눌러주시면, 제가 뮤지컬을 마음껏 보러다닐 수 있어요!
와!! 바로 눌러야겠네요! 😆