• ABOUT
  • PORTFOLIO
  • POSTS
  • GUESTBOOK

© 2025 BlueCool12 All rights reserved.

2025.09.24React

⏱️ useEffect vs useLayoutEffect 완벽 정리 - 실행 시점과 사용법

1. useEffect

useEffect는 렌더링 결과가 실제 DOM에 반영되고 브라우저가 화면을 그린 이후 실행되는 effect이다. 리액트에서는 이를 passive effect라고 부른다.

[특징]

  • DOM 업데이트 이후 실행된다.
  • 일반적으로 브라우저 paint 이후 실행된다.
  • 실행이 비동기적으로 예약되므로 렌더링을 차단하지 않는다.
  • UI가 먼저 사용자에게 보여진 후 effect가 실행된다.

이러한 특성 때문에 데이터 fetching, 이벤트 리스너 등록 및 해제와 같이 레이아웃에 즉각적인 영향을 주지 않는 작업에 적합하다.

import { useEffect, useState } from "react";

function PostList() {
const [posts, setPosts] = useState([]);

// 컴포넌트가 렌더링 된 후 실행
useEffect(() => {
fetch("https://bluecool.pyomin.com/posts")
.then((res) => res.json())
.then((data) => setPosts(data));
}, []);

return (
// ...렌더링
);
}

export default PostList;

이 경우 UI가 먼저 렌더링된 뒤 데이터를 가져와 상태를 업데이트한다.


2. useLayoutEffect

useLayoutEffect는 DOM 업데이트가 완료된 직후 브라우저가 화면을 그리기 전에 동기적으로 실행되는 effect이다. 리액트에서는 이를 layout effect라고 부른다.

[특징]

  • DOM 업데이트 직후 실행된다.
  • 브라우저 paint 이전에 실행된다.
  • 동기적으로 실행되므로 실행이 끝날 때까지 브라우저는 화면을 그리지 않는다.

따라서 DOM의 크기나 위치를 측정하거나 레이아웃을 보정하는 작업에 유용하다.


- 화면 깜빡임(flicker)이 방지되는 이유

useLayoutEffect 내부에서 상태 업데이트가 발생하면 브라우저 paint 이전에 동기적인 재렌더링이 발생한다.

예를 들어 다음 코드가 있다고 가정해보자.

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

function Box() {
const boxRef = useRef(null);
const [width, setWidth] = useState(0);

// DOM이 업데이트된 직후 브라우저가 그리기 전에 실행
useLayoutEffect(() => {
if (boxRef.current) {
const rect = boxRef.current.getBoundingClientRect();
setWidth(rect.width);
}
}, []);

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

export default Box;

실제 실행 흐름은 다음과 같다.

1. 첫 번째 렌더링 수행 (width = 0)
2. DOM 업데이트 완료
3. useLayoutEffect 실행
4. setWidth(rect.width) 호출
5. 브라우저 paint 이전에 React가 동기적으로 재렌더링
6. 최종 DOM 업데이트
7. 브라우저가 화면을 paint

결과적으로 사용자는 width가 0인 상태를 보지 않게 되므로 깜빡임이 발생하지 않는다.


3. 실행 흐름 및 선택 기준

리액트 렌더링 과정을 단순화하면 다음과 같다.

  1. React render phase
  2. commit phase (DOM 업데이트)
  3. useLayoutEffect 실행
  4. 브라우저 paint
  5. useEffect 실행

즉 useLayoutEffect는 paint 이전, useEffect는 paint 이후 실행된다. 단 React 18에서는 클릭이나 키보드 입력과 같은 이산적 이벤트로 인해 업데이트가 발생할 경우 다음 이벤트가 처리되기 전에 상태 일관성을 보장하기 위해 useEffect가 브라우저 paint 이전에 동기적으로 플러시 될 수 있다.

리액트 공식 문서 기준 훅 선택 기준은 가급적 useEffect를 사용하고 레이아웃에 직접적인 영향을 주는 작업에만 useLayoutEffect를 사용할 것을 권장한다.

이전 글
💻 DNS부터 렌더링까지: 웹페이지가 열리는 과정
다음 글
⚙️ 운영 환경까지 고려한 JPA 설정 가이드
장식용 로고