Frontend/React

React.js - useEffect vs useLayoutEffect 차이점 알아보기

둉이 2022. 4. 24. 18:21

React로 개발을 하다 보면 정말 유용하게 많이 사용되고 있는 useEffect 훅에 대해 알아보자.

 

useEffect 훅은 클래스형 컴포넌트의 componentDidMount + componentDidUpdate + componentWillUnmount의 기능을 담당하는 훅이다.

 

함수 컴포넌트 내에서 사이드 이펙트를 일으키는 함수들을 실행시키고자 할 때 사용된다.

// 클래스형 컴포넌트 예시
class Example extends Component {
  componentDidMount() {
    // 컴포넌트가 마운트 되었을 때 실행되는 코드
  }
  
  componentDidUpdate() {
    // 컴포넌트 리렌더링이 완료되었을 때 실행되는 코드
  }
  
  componentWillUnmount() {
    // 컴포넌트가 언마운트 되었을 때 실행되는 코드
  }
}

// 함수 컴포넌트 useEffect 예시
useEffect(() => {
  // 컴포넌트가 마운트 or 리렌더링이 완료되었을 때 실행되는 코드
  
  return () => {
    // 컴포넌트가 언마운트 되었을 때 실행되는 코드
  }
}, [state, props, variables]);  // 해당 사이드 이펙트 함수의 의존성 배열, 해당 의존성 배열의 요소 값이 변경되면 useEffect 실행

 

componentDidMount + componentDidUpdate에 해당하는 코드들은 useEffect에 전달되는 함수 내에 작성하면 되며, componentWillUnmount에 해당하는 코드들은 함수 형태로 return하게끔 작성하면 된다.

 

 

useEffect 내에서 아래 코드와 같이 스크롤 위치 등의 DOM 요소를 조작해야 하는 경우가 있을 것이다.

useEffect(() => {
  // ...

  current.style.scrollBehavior = "auto";
  current.scrollLeft = nextPosition;
  setPosition(nextPosition);
}, [filter.filterSelected]);

 

이런 경우, useEffect를 사용하여 DOM을 조작하게 되면 간헐적으로 화면이 깜빡거리는 현상(flicker)이 나타나게 된다.

깜빡거리는 useEffect

 

이유는 useEffect 자체가 화면이 다 그려진 이후(paint와 layout 과정이 이루어진 후)에 실행되기 때문에 그렇다.

 

이러한 경우에는 useLayoutEffect 훅을 사용하면 깜빡거리는 현상을 해결할 수 있다.

 

useLayoutEffect는 useEffect와 사용 방법에 있어서는 동일하나 실행되는 시점이 다르다.

 

useLayoutEffect는 paint 과정이 일어나기 전에 실행되므로 DOM 조작 코드가 실행된 이후에 업데이트된 화면을 조회하게 된다. 따라서 깜빡거리는 현상이 일어나지 않는다.

화면이 깜빡거리지 않는 useLayoutEffect



 

위 상황 외에도 컴포넌트 렌더링 이후 setState 함수를 실행하여 기존 state 값을 변경하는 경우를 예시로 들어보자.

 

변경된 state를 화면에 표출하기 위해 useEffect 내에서 setState를 함수를 호출하는 경우, 짧은 시간 동안 이전 state 값이 노출되면서 화면이 깜빡이는 문제점이 발생할 수 있다.

잦은 useEffect 호출 시 발생할 수 있는 깜빡임

이러한 경우에도 useLayoutEffect를 적용하게 된다면 깜빡임 문제를 해결할 수 있다.

useLayoutEffect를 사용한 깜빡임 개선

 

 

React의 렌더링 과정에 대해 좀 더 알아보자.

 

React Hook 동작 순서

 

React에서는 컴포넌트를 마운팅한 후 해당 컴포넌트를 렌더링한다.

 

마운팅 단계에서는 useState와 useReducer 등의 훅이 동작한다.

 

이후 렌더링이 완료되면 DOM에 업데이트를 반영하고 LayoutEffect가 실행된다.

 

그 다음에 브라우저에서 paint 과정이 일어나게 되고, paint 과정 이후에 비로소 useEffect가 실행된다.

 

그 외에도 useEffect는 비동기적으로 실행되며, useLayoutEffect는 동기적으로 실행된다는 차이점이 있다.

 

 

결론

따라서, DOM을 변경해야 하는 경우나 계산된 state 값을 화면에 표출해야 하는 경우에는 useLayoutEffect를 사용하는 것이 좋다.

 

그 외 데이터 fetch 함수 실행 혹은 이벤트 핸들러, state를 다루는 작업 등 모든 경우에는 useEffect를 사용하면 된다.

 

 

참고 자료

 

Hooks API Reference – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

GitHub - donavon/hook-flow: A flowchart that explains the new lifecycle of a Hooks component. https://dwe.st/hf

A flowchart that explains the new lifecycle of a Hooks component. https://dwe.st/hf - GitHub - donavon/hook-flow: A flowchart that explains the new lifecycle of a Hooks component. https://dwe.st/hf

github.com