React에서 컴포넌트를 만들다 보면 useEffect와 useLayoutEffect라는 두 훅(Hook)을 마주하게 된다. 이름은 비슷하지만 실행 타이밍과 용도, 그리고 렌더링 성능에 미치는 영향까지 완전히 다르다. 
이번 포스팅에서는 이 둘의 차이점, 실행 순서, 사용 시 주의점, 그리고 실전 예제까지 한 번에 정리해본다.
📌 핵심 요약
| 항목 | useEffect | useLayoutEffect | 
| 실행 시점 | 화면 그린 뒤 (비동기) | 화면 그리기 직전 (동기) | 
| 렌더 차단 여부 | ❌ 렌더 차단 안 함 | ✅ 렌더 차단함 | 
| 목적 | API 호출, 로깅 등 비 UI 작업 | DOM 측정, 스타일 조정 등 UI 관련 작업 | 
| 성능 영향 | 렌더링 후 실행 → 퍼포먼스에 유리 | 렌더링 전에 실행 → 렌더 지연 가능성 | 
| SSR(Server Side Rendering) | SSR 안전 | 권장되지 않음 (경고 발생) | 
🧪 실행 타이밍 흐름
[Render Phase]
 → 브라우저가 실제로 DOM을 그리기 전
[Commit Phase]
 → DOM 반영 완료 → 그 다음 순서:
1. useLayoutEffect (즉시 실행)
2. 브라우저 화면 그리기 (Paint)
3. useEffect (비동기 실행)
즉, useLayoutEffect는 브라우저가 DOM을 그리기 전에 실행되고, useEffect는 브라우저가 화면을 그린 후 실행된다. 
🧬 실전 예제: 차이 확인하기
import { useEffect, useLayoutEffect, useState } from 'react';
function Example() {
  const [value, setValue] = useState(0);
  useLayoutEffect(() => {
    console.log('🟨 useLayoutEffect 실행');
    setValue(100); // 동기적 실행
  }, []);
  useEffect(() => {
    console.log('🟩 useEffect 실행');
    setValue(200); // 비동기적 실행
  }, []);
  console.log('🔄 컴포넌트 렌더링');
  return <div>{value}</div>;
}
🧾 로그 출력 순서:
🔄 컴포넌트 렌더링
🟨 useLayoutEffect 실행
🟩 useEffect 실행
useLayoutEffect는 렌더링을 멈추고 바로 실행됨 → 동기적 
useEffect는 렌더링 후 브라우저가 그린 다음 실행됨 → 비동기
✅ 언제 useLayoutEffect를 써야 할까? 
useLayoutEffect는 정말 특별한 경우에만 써야 한다. 대표적인 예시는 다음과 같다: 
📏 DOM 측정
useLayoutEffect(() => {
  const height = elementRef.current.offsetHeight;
  setHeight(height);
}, []);
🎯 레이아웃 "깜빡임" 방지 
스타일 수정, 애니메이션, 포지션 조정 등 "렌더 후 스타일이 바뀌면 안 되는 상황" 에서 사용 
⚠️ 주의할 점 
useLayoutEffect는 렌더링을 블로킹하므로, 남용 시 성능 저하 발생 
SSR 환경에선 useLayoutEffect가 경고를 발생시킬 수 있음 (브라우저가 없기 때문에) 
기본적으로는 useEffect를 사용하고, 정말 필요한 경우에만 useLayoutEffect로 바꿔야 한다 
🎯 결론: 정리표
| 상황 | 어떤 Hook? | 이유 | 
| API 호출, 로깅, 타이머 등록 | useEffect | 화면 그린 후 실행돼도 상관없음 | 
| DOM 위치, 크기 측정 | useLayoutEffect | 브라우저가 그리기 전에 정확한 정보 필요 | 
| CSS 기반 애니메이션 조정 | useLayoutEffect | 레이아웃 깜빡임 방지 | 
| 성능이 중요한 경우 | useEffect | 렌더링 블로킹 방지 | 
| 서버사이드 렌더링 환경 | useEffect | useLayoutEffect는 경고 발생 가능 | 
'개발 > Javascript & Typescript' 카테고리의 다른 글
| [React] 리액트 useEffect 호출 시점, 제대로 정리해봤다 (67) | 2025.07.14 | 
|---|---|
| [Javascript] 자바스크립트 호이스팅(Hoisting) 완전 정복 - 변수, 함수, let vs var의 차이까지! (64) | 2025.07.10 | 
| [React] 리액트의 Render Phase와 Commit Phase 완벽 정리 (63) | 2025.07.07 | 
| [React] React에서 key로 index를 쓰면 안 되는 이유 (60) | 2025.07.04 | 
| [React] Strict Mode 완전 정복 - 사이드이펙트, 더블 렌더링, Deprecated 감지까지 (63) | 2025.07.03 |