• ABOUT
  • POSTS
  • GUESTBOOK

© 2025 BlueCool12 All rights reserved.

2025.09.24React

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

리액트는 컴포넌트 렌더링 과정에서 발생하는 부수 효과(side effect)를 처리하기 위해 useEffect 와 useLayoutEffect 훅을 제공한다. 

둘 다 렌더링 이후에 실행되지만 실행 시점과 사용 목적에서 차이가 있다. 
 



1) useEffect 
- 렌더링 결과가 실제 DOM에 반영되고 브라우저가 화면을 그린 이후 실행된다. 
- 실행이 비동기적으로 예약되기 때문에 렌더링 과정을 막지 않고 UI가 먼저 사용자에게 보인다. 

2) useLayoutEffect 
- 렌더링 후 DOM 업데이트 직후 브라우저가 화면을 그리기 전에 동기적으로 실행된다. 
- 실행이 끝날 때까지 브라우저는 페인트를 멈추므로 화면 깜빡임(flicker)을 방지할 수 있다. 

따라서 useEffect는 데이터 가져오기(fetching), 이벤트 리스너 등록/해제, 로그 기록처럼 화면에 즉각적인 레이아웃 변경이 필요 없는 작업에 적합하다. 

실행 시점이 브라우저 페인트 이후이기 때문에 UI를 먼저 사용자에게 보여주고 그 뒤에 작업이 이루어진다. 
 

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;


반면 useLayoutEffect는 DOM의 크기나 위치를 측정한 후 레이아웃을 보정해야 할 때 혹은 애니메이션 초기화 같은 상황에서 유용하다. 

DOM이 실제로 준비된 직후 화면에 그리기 전에 실행되므로 UI에 직접적이고 즉각적인 영향을 주는 작업에 유용하다. 
 

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. 리액트가 DOM 변경 (가상 DOM → 실제 DOM 업데이트) 
2. useLayoutEffect 실행 (동기)
3. 브라우저 화면에 그리기 (paint) 
4. useEffect 실행 (비동기) 

주의할 점은 useLayoutEffect의 경우 동기적으로 실행되기 때문에 너무 남용할 경우 렌더링이 느려질 수 있다. 따라서 기본적으로 useEffect를 사용하되 레이아웃에 영향을 주는 작업만 useLayoutEffect로 처리하는 것이 좋다. 
 

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