본문 바로가기
React

[React] useLayoutEffect vs useEffect: 언제, 왜 사용하는가?

by haheehee 2025. 2. 5.
728x90

React에서 useEffect와 useLayoutEffect는 비슷해 보이지만 동작 방식에서 중요한 차이가 있음
이 차이를 이해하면 UI가 깜빡이는 문제(Flickering) 등을 방지 가능

1. 기본 개념 정리

 ▶ useEffect

  • 비동기적으로 실행됨 (렌더링 후 실행됨)
  • 화면이 먼저 업데이트된 후에 실행됨
  • 사용자에게 먼저 UI가 보이고 그 후에 실행되는 효과를 적용할 때 사용

 ▶ useLayoutEffect

  • 동기적으로 실행됨 (렌더링 직후, 화면이 그려지기 전에 실행됨)
  • DOM 업데이트가 적용되기 전에 실행됨
  • UI가 깜빡이는 것을 방지하고 레이아웃이 변경되기 전에 실행해야 할 경우 사용

2. 실행 순서 차이

 ▶ useEffect 실행 순서

  1. 컴포넌트가 렌더링됨
  2. 브라우저가 화면을 업데이트함
  3. useEffect 실행됨
import { useState, useEffect } from "react";

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("useEffect 실행");
  });

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increase</button>
    </div>
  );
}

export default Example;

- 버튼을 클릭하면 화면이 먼저 업데이트된 후에 useEffect가 실행됨
따라서 console.log("useEffect 실행")은 UI 업데이트 후에 실행됨.


 ▶ useLayoutEffect 실행 순서

  1. 컴포넌트가 렌더링됨
  2. useLayoutEffect 실행됨
  3. 브라우저가 화면을 업데이트함
import { useState, useLayoutEffect } from "react";

function Example() {
  const [count, setCount] = useState(0);

  useLayoutEffect(() => {
    console.log("useLayoutEffect 실행");
  });

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increase</button>
    </div>
  );
}

export default Example;

- useLayoutEffect는 화면이 업데이트되기 전에 실행되므로 사용자가 UI 변경을 보기 전에 효과를 적용 가능


3. 언제 useLayoutEffect를 사용해야 할까? 

 DOM 크기나 위치를 즉시 측정해야 할 때

  • useEffect는 화면이 렌더된 후 실행되므로, 레이아웃이 바뀔 수 있음
  • useLayoutEffect를 사용하면 화면이 깜빡이는 현상(Flickering) 을 방지할 수 있음
import { useState, useEffect, useLayoutEffect, useRef } from "react";

function Example() {
  const [width, setWidth] = useState(0);
  const boxRef = useRef<HTMLDivElement>(null);

  useLayoutEffect(() => {
    if (boxRef.current) {
      setWidth(boxRef.current.offsetWidth);
    }
  });

  return (
    <div>
      <div ref={boxRef} style={{ width: "200px", height: "100px", background: "lightblue" }}>
        박스
      </div>
      <p>박스의 너비: {width}px</p>
    </div>
  );
}

export default Example;

- useEffect를 사용하면 화면이 먼저 업데이트된 후에 값이 설정되므로, 너비가 처음엔 0px으로 표시됐다가 변경됨
- useLayoutEffect를 사용하면 렌더링 직후, 즉시 값을 설정해서 깜빡임을 방지할 수 있음


 ▶ 스타일이나 애니메이션 변경을 즉시 적용해야 할 때

import { useState, useEffect, useLayoutEffect } from "react";

function Example() {
  const [color, setColor] = useState("red");

  useLayoutEffect(() => {
    document.body.style.backgroundColor = color;
  }, [color]);

  return (
    <button onClick={() => setColor(color === "red" ? "blue" : "red")}>
      Change Background
    </button>
  );
}

export default Example;

- useEffect를 사용하면 색이 깜빡거리면서 바뀌는 걸 볼 수 있음
- useLayoutEffect를 사용하면 깜빡임 없이 부드럽게 전환됨


4. 결론 !!

기능 useEffect useLayoutEffect
실행 시점 화면이 렌더링된 이후 화면이 렌더링된 즉시 (UI 업데이트 전)
비동기 여부 비동기적 동기적
주요 사용 목적 데이터 가져오기, 이벤트 핸들링 레이아웃 측정, 애니메이션, 깜빡임 방지
UI 깜빡임 방지 ❌ 방지 불가 ✅ 방지 가능
  • 대부분의 경우 useEffect를 사용하고,
  • UI 깜빡임을 방지하거나 레이아웃을 조정할 필요가 있을 때만 useLayoutEffect를 사용하면 됨
728x90

댓글