useEffect
는 비동기적으로 실행되지만,
useLayoutEffect
는 DOM 변경 직후, 브라우저 페인트 전에 동기적으로 실행되고
useInsertionEffect
는 스타일이 삽입되기 전에 실행돼.
성능과 렌더링 타이밍에 영향을 줄 수 있는 중요한 훅들이야.
import { useLayoutEffect, useEffect } from 'react';
const LayoutExample = () => {
useEffect(() => {
console.log('✅ useEffect 호출');
}, []);
useLayoutEffect(() => {
console.log('⚡️ useLayoutEffect 호출');
}, []);
return <div>렌더링 타이밍 테스트</div>;
};
✅ 콘솔 출력 순서를 보면 useLayoutEffect → useEffect 순서로 실행됨.
useLayoutEffect
는 레이아웃 조정이 필요한 작업에 적합.
import { useRef, useLayoutEffect, useState } from 'react';
const BoxSize = () => {
const boxRef = useRef<HTMLDivElement>(null);
const [height, setHeight] = useState(0);
useLayoutEffect(() => {
if (boxRef.current) {
setHeight(boxRef.current.getBoundingClientRect().height);
}
}, []);
return (
<>
<div ref={boxRef} style={{ height: '120px', background: '#eee' }}>
박스
</div>
<p>높이: {height}px</p>
</>
);
};
✅ DOM 크기를 읽고 상태를 업데이트할 때는 useLayoutEffect를 사용해야 레이아웃 깨짐 없이 반영 가능해.
const ResizeExample = () => {
const ref = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
if (ref.current) {
ref.current.style.width = '400px';
}
}, []);
return <div ref={ref} style={{
width: '100px',
height: '50px',
background: 'skyblue'
}} />;
};
✅ 스타일을 강제로 바꾸거나 측정하는 경우에는 useLayoutEffect를 써야 렌더링 전에 처리돼서 깜빡임 없이 적용돼.
import { useInsertionEffect, useRef } from 'react';
const StyleEffect = () => {
const ref = useRef<HTMLDivElement>(null);
useInsertionEffect(() => {
if (ref.current) {
ref.current.style.setProperty('color', 'red');
}
}, []);
return <div ref={ref}>useInsertionEffect 적용</div>;
};
✅ useInsertionEffect는 스타일 시스템과 직접 연관 있는 라이브러리 (예: Emotion, styled-components 등)에서 내부적으로 자주 사용돼.