Post

useEffect와 useLayoutEffect

useEffect와 useLayoutEffect

React를 사용하다 보면 가장 자주 마주치는 훅 중 하나가 useEffect이다.
하지만 가끔은 React 문서나 커뮤니티에서 useLayoutEffect를 함께 언급하는 것을 볼 수 있다.
두 훅은 모두 “렌더링 이후”에 실행된다는 공통점이 있지만, 실행 타이밍용도가 완전히 다르다.


⚡ 1. useEffect — 렌더링 후 비동기적으로 실행

useEffect렌더링이 완전히 끝나고, 실제로 브라우저가 화면을 그린 이후에 비동기적으로 실행된다.

즉,

  • 컴포넌트가 렌더됨
  • DOM이 그려짐
  • 브라우저가 화면 업데이트 완료
  • 그 다음에 useEffect 실행

이 순서로 동작합니다.

따라서 useEffect는 다음과 같은 화면에 직접적인 영향을 주지 않는 작업에 적합하다.

  • API 호출 (데이터 패칭)
  • 로깅, 분석 이벤트 전송
  • DOM 조작이 필요 없는 이벤트 리스너 등록
  • setTimeout / setInterval
  • 전역 객체(window, document) 관련 부수 효과 관리

✔️ 예시: API 데이터 패칭에 적합

1
2
3
useEffect(() => {
  fetchData().then(response => setData(response));
}, []);

이런 작업은 화면이 먼저 렌더링되어도 무방하고, 렌더링 이후 로직이 실행되어도 문제되지 않기 때문에 useEffect가 자연스럽다.


⚡ 2. useLayoutEffect — 렌더링 후 DOM이 그려지기 직전 동기 실행

반면 useLayoutEffect는 조금 다르다.

  • React가 렌더링을 완료
  • DOM 업데이트 직전(페인트 직전)에 동기적으로 실행
  • 이 함수가 끝날 때까지 브라우저는 화면을 그리지 않음
  • 모든 레이아웃 관련 작업이 끝난 뒤 브라우저가 화면을 그림

즉, 사용자가 화면을 보기 전에 레이아웃 작업을 강제로 완료시키는 역할을 합니다.

어떤 경우에 필요한가?

화면이 그려지기 전에 DOM의 크기, 위치 정보를 수집해야 할 때 또는 그 정보에 맞춰 DOM을 즉시 조정해야 할 때.

  • 요소의 height/width 측정
  • 스크롤 위치 조정
  • 화면 깜빡임(Flickering) 방지
  • 애니메이션 초기 위치 계산
  • 포커스 위치 조정 등

✔️ 예시: DOM 높이를 계산해 레이아웃에 반영

1
2
3
4
useLayoutEffect(() => {
  const height = ref.current.offsetHeight;
  setHeight(height);
}, []);

이 작업을 useEffect로 하면?

  • 화면이 먼저 그려짐
  • 이후 useEffect가 실행됨
  • setState → 다시 렌더링
  • 화면이 두 번 깜빡일 수 있음

그래서 반드시 useLayoutEffect가 필요하다.


⚠️ useLayoutEffect는 성능에 영향을 준다

useLayoutEffect는 동기적으로 실행되기 때문에, 여기에 많은 작업이 들어가면 렌더링을 “막아버린다.” 브라우저가 화면을 그리기 전에 기다려야 하므로 성능이 떨어질 수 있다.

언제 어떤 훅을 써야 할까?

비교 항목useEffectuseLayoutEffect
실행 시점렌더 → 브라우저 페인트 렌더 → 브라우저 페인트 직전
실행 방식비동기동기
화면 영향화면 변경 ❌화면 변경 ⭕ (깜빡임 방지)
주 사용 목적데이터 패칭, 이벤트 등록, 비동기 작업DOM 측정, 레이아웃 조정, 스크롤/포커스
성능 영향적음높음(남용 금지)

기본은 useEffect 레이아웃 계산이나 화면 깜빡임을 막아야 하는 경우에만 useLayoutEffect 사용


Summary

렌더링 후 “비동기적” 작업 → useEffect 렌더링 후 화면이 그려지기 전 “동기적” 작업 → useLayoutEffect


END

This post is licensed under CC BY 4.0 by the author.