이전에는 원래 useEffect만을 사용하다가, 사이드 프로젝트 진행 중 스크롤에 반응하는 네비게이션을 구현할 때 useLayoutEffect를 알게 되었고 특정한 경우에는 useEffect보다 useLayoutEffect가 더 효율적으로 작동한다는 것을 알게 되었다. 그래서 이참에 해당 내용을 블로그에 정리하려고 한다.

 

useEffect

리액트를 쓰고 있는 사람이라면 모를수가 없는 useEffect이다. 함수형 컴포넌트와 Hooks의 조합에서 클래스형 컴포넌트에서의 componentDidMountcomponentDidUpdate 와 componentWillUnmount의 역할을 제공 해준다.

물론 100% 완벽하게 똑같지는 않다. componentDidMount, componentDidUpdate와는 다르게 useEffect 전달된 함수는 화면에 렌더링이 완료된 후에 수행되게 된다. 이는 대부분의 작업이 브라우저에서 화면을 업데이트하는 것을 차단해서는 안되기 때문이다. 실제로 이러한 동작 방식은 웬만한 경우에 더 효율적으로 작용할 것이다.

 

하지만, 만약 사용자에게 노출되는 DOM을 변경하는 경우에는 화면이 렌더링 되기 전에 동기화를 시켜주어야 한다. 그렇지 않으면 먼저 화면에 렌더링이 되고난 후에 변경이 되기 때문에 깜빡이는 현상이 나타날 것이다. 이렇게 DOM을 변경시키는 작업을 할 때는 useEffect보다 useLayoutEffect를 사용하는 것이 더 효율적이다.

 

useLayoutEffect

useLayoutEffect앞서 언급한 바와 같이 DOM이 변경되고나서 동기적으로 실행이 된다. 즉 브라우저가 화면을 그리기 전에 실행이된다. 그렇기 때문에 useLayoutEffect는 스크롤 위치를 얻어오거나 다른 DOM 엘리먼트의 스타일을 조작할 때 사용할 때 효율적이다. 이는 클래스형 컴포넌트에서 componentDidMountcomponentDidUpdate와 동일한 역할을 제공한다.

 

정리하자면, useLayoutEffect내의 함수는 DOM이 업데이트 되면 바로 동기적으로 실행이 되고 이러한 과정은 브라우저가 화면에 렌더링하기 이전에 수행된다. 따라서 사용자는 업데이트 되기 전의 화면을 보지 않게 된다.

 

const ref = React.useRef()
React.useEffect(() => {
  ref.value = 'some value'
})

React.useLayoutEffect(() => {
  console.log(ref.value) // 'some value' 이전 값 (useLayoutEffect가 먼저 수행되기 때문)
})

 

결론

useLayoutEffect는 사용자에게 노출되는 DOM을 변형시킬 때 사용하면 더 효율적이다.

useEffect는 DOM을 변형시키지 않는 대부분의 경우에 사용한다.

 

참고


생강강

,