📚 CS/React

[React] useEffect, useLayoutEffect 비교하기

dev.daisy 2025. 9. 14. 12:33
useEffect, useLayoutEffect 훅의 차이점을 자세히 파고들어 보니 React 컴포넌트의 렌더링 과정브라우저의 페인트(Paint) 과정에 깊게 연결되어 있다는 것을 알게 되었습니다.

이번 기회를 통해 React 훅의 단순한 사용법을 넘어, React가 사용자 경험을 최적화하기 위해 얼마나 섬세하게 설계되었는지 다시 한번 깨닫게 되었습니다. 단순히 기능만 외우는 것이 아니라, 그 기능이 왜 존재하고 어떤 문제를 해결하는지 이해하는 것이 정말 중요하다는 것을 느꼈습니다.

useEffect와 useLayoutEffect는 둘 다 렌더링 이후에 특정 작업을 실행하는 React 훅이지만, 실행되는 시점에 중요한 차이가 있습니다.

1. useEffect

useEffect는 브라우저가 화면을 그린 후비동기적으로 실행됩니다.

  • 시점: 렌더링 -> DOM 업데이트 -> 브라우저가 화면을 그림 (페인트) -> useEffect 실행
  • 특징: 비동기적으로 실행되기 때문에 화면 업데이트를 차단하지 않습니다. 따라서 성능에 영향을 덜 주며, 대부분의 경우에 사용됩니다. 네트워크 요청, 구독 설정, 타이머 등 DOM을 직접 조작하지 않거나 조작하더라도 화면 깜빡임이 발생하지 않는 작업에 적합합니다.
반응형 값을 의존성으로 추가하기

1) 의존성 배열 전달하기
의존성을 명시하면 Effect는 초기 렌더링 이후, 그리고 의존성 값 변경과 함께 리렌더링이 된 후 동작합니다.
useEffect(() => {
  // ...
}, [a, b]); // a나 b가 다르면 다시 실행됨​


2) 빈 의존성 배열 전달하기
만약 Effect가 정말 어떤 반응형 값도 사용하지 않는다면 그것은 초기 렌더링 이후 한번만 실행됩니다.

useEffect(() => {
  // ...
}, []); // 다시 실행되지 않음 (개발 환경에서만 한번 실행)


개발 환경에서는 빈 의존성 배열이 있더라도 버그를 찾기 위해 설정과 정리가 한번 더 실행됩니다.

3) 의존성 배열을 전달하지 않았을 때
의존성 배열을 아예 사용하지 않을 경우, Effect는 컴포넌트의 모든 렌더링과 리렌더링마다 동작합니다.

useEffect(() => {
  // ...
}); // 항상 다시 실행됨

2. useLayoutEffect

useLayoutEffect는 브라우저가 화면을 그리기 전동기적으로 실행됩니다.

  • 시점: 렌더링 -> DOM 업데이트 -> useLayoutEffect 실행 -> 브라우저가 화면을 그림 (페인트)
  • 특징: 동기적으로 실행되기 때문에 useEffect보다 먼저 실행되며, 화면 업데이트를 차단합니다. DOM을 읽거나 직접 조작하여 화면 깜빡임 (Flicker)을 방지해야 할 때 주로 사용됩니다. 예를 들어, 요소의 크기나 위치를 측정한 후 그 값을 기반으로 스타일을 변경해야 하는 경우 유용합니다.
useLayoutEffect의 남용이 왜 성능 문제를 일으킬 수 있는지 자세히 설명해주세요.

useLayoutEffect는 동기적으로 실행되기 때문에, 훅 내부의 콜백 함수가 완료될 때까지 브라우저의 페인트(Paint) 작업이 늦춰집니다. 만약 콜백 함수가 복잡한 DOM 조작이나 반복적인 계산을 수행하는 무거운 작업이라면, 프레임 드롭(frame drop)이 발생하여 UI가 끊기는 것처럼 보일 수 있습니다.

요약

  useEffect useLayoutEffect
실행 시점 브라우저가 화면을 그린 후 (비동기) 브라우저가 화면을 그리기 전 (동기)
화면 차단 여부 ❌ (비차단) ✅ (차단)
주요 사용 사례 대부분의 부수 효과 (데이터 페칭, 타이머 등) DOM 조작으로 인한 화면 깜빡임을 방지해야 할 때
useLayoutEffect가 useEffect보다 먼저 실행되는 이유는 무엇인가요?

useLayoutEffect는 브라우저가 화면에 레이아웃을 계산하고 그리기 전에 DOM 상태를 최종적으로 확정해야 하는 작업에 사용됩니다. 이 작업이 선행되어야만 브라우저가 올바른 레이아웃을 화면에 그릴 수 있기 때문에 useEffect보다 먼저 실행됩니다.
useEffect, useLayoutEffect훅은 각각 언제 사용되나요?

useEffect는 컴포넌트 렌더링이 완료된 후에 특정 작업을 수행할 때 사용합니다. 주로 데이터 가져오기(fetching), 이벤트 리스너 등록, 타이머 설정, 또는 외부 API와 상호작용하는 등 비동기적인 작업에 적합합니다.
useLayoutEffect는 컴포넌트가 렌더링된 직후에, 하지만 브라우저가 화면을 그리기 전에 DOM과 관련된 작업을 동기적으로 수행할 때 사용합니다. DOM의 크기를 측정하거나, 스크롤 위치를 조정하거나, 특정 DOM 노드의 스타일을 즉시 변경해야 할 때 유용합니다.


React 공식문서
에서도 useEffect를 사용하는 것을 권장하고 있습니다!

왜 대부분의 경우 useEffect를 사용하는 것이 권장되나요?

useLayoutEffect동기적으로 실행되기 때문에 훅 내부에 무거운 작업이 있으면 렌더링을 차단하여 사용자에게 화면 지연이나 깜빡임 같은 불편한 경험을 줄 수 있습니다. 반면, useEffect비동기적으로 작동하여 렌더링을 방해하지 않고 사용자 경험을 해치지 않기 때문입니다.

3. References

https://ko.react.dev/reference/react/useEffect

https://ko.react.dev/reference/react/useLayoutEffect
https://ko.react.dev/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development