useEffect와 useLayoutEffect는 둘 다 React에서 사이드 이펙트(Side Effect)를 처리하기 위한 Hook이지만, 그 동작 시점과 목적이 조금 다르다. 이때 사이드 이펙트(Side Effect)란 리액트 컴포넌트가 화면에 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 말한다. 대표적인 예시로, 어떤 데이터를 가져오기 위해 외부 API를 호출하는 경우, 화면에 렌더링할 수 있는 것은 먼저 렌더링하고 실제 데이터는 비동기로 가져오는 것이 권장된다. 요청 즉시 먼저 렌더링을 하면서 API 응답이 늦어지거나 없을 경우에도 영향을 최소화할 수 있다. useEffect와 useLayoutEffect 두 Hook의 차이점을 이해하기 위해서는 렌더링 과정에서 언제 실행되는지와 그 결과가 화면에 반영되는 시점이 중요한 요소이다.
useLayoutEffect는 render -> useLayoutEffect -> paint 순서로 실행된다.
즉, DOM이 업데이트 된 직후, 브라우저가 화면을 그리기 전에 실행된다.
useLayoutEffect는 동기적으로 실행되며, 내부의 코드가 모두 실행된 후 paint 작업을 거친다.
paint가 되기 전에 실행되기 때문에 DOM을 조작하는 코드가 존재해도 화면이 깜빡이거나 렌더링이 지연되는 현상을 방지할 수 있다.
하지만, 로직이 복잡할 경우 사용자가 layout을 보는데까지 시간이 오래걸릴 수 있기 때문에 useEffect만을 사용하는 것이 권장된다.
레이아웃을 측정하거나, DOM을 조작하는 작업에서 주로 사용
동기적으로 작동하므로, 화면이 렌더링되기 전에 DOM 조작이 필요한 경우(예: 엘리먼트 크기 측정, 스크롤 위치 조정) 적합\
03. useEffect vs useLayoutEffect 차이 예시
import { useState, useEffect, useLayoutEffect, useRef } from 'react'
const Effect = () => {
const [size, setSize] = useState(100)
const boxRef = useRef<HTMLDivElement>(null)
// useEffect: 화면 렌더링 후 1초 지연 후 실행
useEffect(() => {
const timer = setTimeout(() => {
if (boxRef.current) {
console.log('useEffect - Box height after render:', boxRef.current.clientHeight)
}
}, 1000) // 1초 지연 후 실행
return () => clearTimeout(timer) // 타이머 정리
}, [size])
// useLayoutEffect: 화면이 그려지기 전에 실행
useLayoutEffect(() => {
if (boxRef.current) {
console.log('useLayoutEffect - Box height before render:', boxRef.current.clientHeight)
}
}, [size])
return (
<div>
<div
ref={boxRef}
style={{
width: '200px',
height: `${size}px`,
backgroundColor: 'lightcoral',
transition: 'height 0.3s',
}}
>
Box
</div>
<button onClick={() => setSize(size + 50)}>Increase Height</button>
</div>
)
}
export default Effect
위 코드에서 useLayoutEffect는 브라우저가 화면을 그리기 전에 DOM의 높이를 즉시 확인한다.
useEffect는 1초 지연 후 DOM의 높이를 확인한다. useLayoutEffect 실행과 useEffect 차이를 더 명확하게 알기 위해서 useEffect에는 1초의 지연 시간을 설정하였다. 이 지연을 통해 useLayoutEffect가 먼저 실행된 후, 브라우저가 화면을 업데이트한 후 useEffect가 실행되는 것을 확인할 수 있을 것이다.
즉, 버튼을 클릭하면, 먼저 useLayoutEffect에서 DOM 업데이트 직후 높이가 출력된다. 1초 후, useEffect에서 DOM이 렌더링된 후의 높이가 출력된다.
useLayoutEffect: "useLayoutEffect - Box height before render"가 실행되어, 버튼을 눌러 높이가 변경되기 전에 DOM의 높이를 콘솔에 출력
useEffect: "useEffect - Box height after render"가 실행되어, 브라우저가 화면을 업데이트한 후에 DOM의 높이를 출력
[React] useEffect vs useLayoutEffect
useEffect와 useLayoutEffect는 둘 다 React에서 사이드 이펙트(Side Effect)를 처리하기 위한 Hook이지만, 그 동작 시점과 목적이 조금 다르다. 이때 사이드 이펙트(Side Effect)란 리액트 컴포넌트가 화면에 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 말한다. 대표적인 예시로, 어떤 데이터를 가져오기 위해 외부 API를 호출하는 경우, 화면에 렌더링할 수 있는 것은 먼저 렌더링하고 실제 데이터는 비동기로 가져오는 것이 권장된다. 요청 즉시 먼저 렌더링을 하면서 API 응답이 늦어지거나 없을 경우에도 영향을 최소화할 수 있다. useEffect와 useLayoutEffect 두 Hook의 차이점을 이해하기 위해서는 렌더링 과정에서 언제 실행되는지와 그 결과가 화면에 반영되는 시점이 중요한 요소이다.
01. useEffect
useEffect는 render -> paint -> useEffect 순서로 실행된다.
즉, 브라우저가 화면에 렌더링을 완료한 후, 컴포넌트가 화면에 그려지고 난 뒤에 사이드 이펙트를 처리한다.
이때, render, paint과정은 다음과 같다.
useEffect는 비동기적으로 실행되며, paint 된 후 실행되기 때문에, useEffect 내부에 DOM에 영향을 주는 코드가 있을 경우 사용자 입장에서는 화면의 깜빡임을 보게 된다.
02. useLayoutEffect
useLayoutEffect는 render -> useLayoutEffect -> paint 순서로 실행된다.
즉, DOM이 업데이트 된 직후, 브라우저가 화면을 그리기 전에 실행된다.
useLayoutEffect는 동기적으로 실행되며, 내부의 코드가 모두 실행된 후 paint 작업을 거친다.
paint가 되기 전에 실행되기 때문에 DOM을 조작하는 코드가 존재해도 화면이 깜빡이거나 렌더링이 지연되는 현상을 방지할 수 있다.
하지만, 로직이 복잡할 경우 사용자가 layout을 보는데까지 시간이 오래걸릴 수 있기 때문에 useEffect만을 사용하는 것이 권장된다.
03. useEffect vs useLayoutEffect 차이 예시
위 코드에서 useLayoutEffect는 브라우저가 화면을 그리기 전에 DOM의 높이를 즉시 확인한다.
useEffect는 1초 지연 후 DOM의 높이를 확인한다. useLayoutEffect 실행과 useEffect 차이를 더 명확하게 알기 위해서 useEffect에는 1초의 지연 시간을 설정하였다. 이 지연을 통해 useLayoutEffect가 먼저 실행된 후, 브라우저가 화면을 업데이트한 후 useEffect가 실행되는 것을 확인할 수 있을 것이다.
즉, 버튼을 클릭하면, 먼저 useLayoutEffect에서 DOM 업데이트 직후 높이가 출력된다. 1초 후, useEffect에서 DOM이 렌더링된 후의 높이가 출력된다.
'ASAC > Front-End' 카테고리의 다른 글