Side Effect
- side effect란 함수가 받은 인자 외에 외부에서 함수의 출력에 영향을 주는 모든 상태 변경을 의미한다
예를 들어 함수의 내부에서 Math.random(), Date.now()를 사용하여 실행할 때마다 결과가 달라지는 것이 대표적인 side effect이다. 그 외에도 함수 내부에서 인자로 받지 않은 외부의 상태를 참조하거나 API로 서버의 데이터를 가져오는 등의 작업도 side effect에 포함된다.
- useEffect와 useLayoutEffect 모두 컴포넌트에서 side effect가 있는 작업을 수행할 때 사용할 수 있다.
useEffect
- useEffect 는 컴포넌트들이 render 와 paint 된 후 실행됩니다. 비동기적(asynchronous) 으로 실행됩니다. paint 된 후 실행되기 때문에, useEffect 내부에 dom 에 영향을 주는 코드가 있을 경우 사용자 입장에서는 화면의 깜빡임을 보게됩니다.

- 리액트 앱에서 렌더링이 트리거 됨 (dependency 수정됨)
- 리액트가 컴포넌트를 렌더링함
- 브라우저가 화면을 새로 그림
- useEffect가 백그라운드에서 실행됨
- useEffect 안에서 DOM 노드 ref를 조작함
- 리렌더링, 이펙트가 DOM을 수정하는 동안 잠시 화면이 빔.
- 브라우저가 화면을 새로 그림
useLayoutEffect
- useLayoutEffect 는 컴포넌트들이 render 된 후 실행되며, 그 이후에 paint 가 됩니다. 이 작업은 동기적(synchronous) 으로 실행됩니다. paint 가 되기전에 실행되기 때문에 dom 을 조작하는 코드가 존재하더라도 사용자는 깜빡임을 경험하지 않습니다.

- 리액트 앱에서 렌더링이 트리거 됨 (dependency 수정됨)
- 리액트가 컴포넌트를 렌더링함
- useLayoutEffect가 실행됨
- useLayoutEffect가 끝나기를 기다림
- 브라우저가 화면을 새로 그림
차이
- useEffect는 컴포넌트 렌더링과 브라우저 페인팅이 끝난 후 비동기적으로 실행되며, useLayoutEffect는 컴포넌트 렌더링 후 동기적으로 실행되어 작업이 완료되면 브라우저 페인팅이 시작된다.
- 따라서 로직이 복잡할 경우 사용자가 레이아웃을 보는데까지 시간이 오래걸린다는 단점이 있어, 기본적으로는 항상 useEffect 만을 사용하는 것을 권장드립니다. 구체적인 예시로는
데이터 fetch
event handler
state reset
등의 작업은 항상 useEffect 를 사용하되,
화면이 깜빡거리는 상황일 때, 예를들어 위와같이 state 이 존재하며, 해당 state 이 조건에 따라 첫 painting 시 다르게 렌더링 되어야 할 때는 useEffect 사용 시 처음에 0이 보여지고 이후에 re-rendering 되며 화면이 깜빡거려지기 때문에 useLayoutEffect 를 사용하는 것이 바람직 합니다.
언제 사용?
- 브라우저 페인트 전 DOM 조작, 혹은 레이아웃 정보를 읽어야 할 때
- 스크롤 위치 확인
- 화면이 깜빡이는 상황
- 예를들어, 바로 b라는 데이터를 보여야 될 때 ->처음에 a가 보여지고 이후에 리랜더링이 되므로 이때 사용해야 한다.
- 그 외: ref가 업데이트 되기 전 이전 값 확인
+ 내용
.React 18부터 useEffect에 전달된 함수는 클릭과 같은 개별 사용자 입력의 결과이거나 로 래핑된 업데이트의 결과인 경우 레이아웃 및 페인트 전에 동기적으로 실행됩니다. (전달된 함수가 호출되는 타이밍에만 영향을 미칩니다. useEffect이러한 효과 내에서 예약된 업데이트는 여전히 지연e됨)
https://ko.reactjs.org/docs/hooks-reference.html#useeffect
참고 링크
https://medium.com/@jnso5072/react-useeffect-%EC%99%80-uselayouteffect-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C-e1a13adf1cd5
https://woojeongmin.com/2022/study-log/useeffect-uselayouteffect/