늘 겸손하게

React - useLayoutEffect vs. useEffect 본문

Programming/React

React - useLayoutEffect vs. useEffect

besforyou999 2022. 8. 1. 19:00

useEffect와 useLayoutEffect의 차이점에 대해 알아봅시다

 

우선 useEffect가 무엇인지, useLayoutEffect가 무엇인지 서술하고 차이점을 서술하겠습니다.

 

useEffect

 

함수 컴포넌트에서 side effect를 수행할 수 있게 해주는 hook입니다.

side effect?

 

함수가 실행되면서 함수 외부에 존재하는 값이나 상태 등을 변경시키는 행위. 예로, 함수 외부의 배열 데이터를 바꾸거나 전역변수값 변경, 네트워크를 통한 데이터 송수신, 파일 입출력, 구독 설정하기, 수동으로 React 컴포넌트의 DOM을 수정하는것 등이 side effect입니다.

 

side-effect가 무조건 나쁘다고는 할 수 없지만 함수는 매개변수로 입력받은 인자값에 대해 항상 일관된 출력값을 반환해야 프로그램이 단순해지고 유지보수하기 편해지는데 side-effect는 프로그램을 예측불가능하게 만들기 때문에 함수형(선언형) 프로그래밍에서 side-effect를 줄이려고 노력하고 있습니다.

 

예로 아래와 같은 코드에서 document를 통해 DOM을 수정하는것은 side-effect입니다

 

function appendName(text) {
  const name = "Ted";
  text += name;
  document.title = `${text}`;
  return <div>{text}</div>
}

function getTitle(text) {
  const title = document.title
  const str = `${text} ${title}`
  return <div>{str}</div>
}

 

 

첫 번째 함수의 side-effect로 인해 getTitle 함수는 일관된 출력값을 반환하지 못합니다. 

 

위와 같은 함수는 작은 프로젝트에서는 문제없지만 규모가 큰 프로젝트나 협업을 할 경우 프로그램이 예측하기 어려워진다고 합니다.

 

또한 side-effect가 무거운 작업이었다면 컴포넌트 렌더링이 될때마다 프로그램이 느려지는 일이 발생할 수도 있다고 합니다. 

 

이러한 경우 side-effect 작업을 useEffect 내부에 배치하면 React가 적절한 시점에 side-effect 작업을 수행시켜주어 앱의 성능을 향상시킬 수 있습니다.

 

 

React의 class 생명 주기 메서드인 componentDidMount, componentDidUpdate, componentWillUnmount가 합쳐진 것으로

 

생각해도 좋다고합니다.

 

 

 

useLayoutEffect와 useEffect 차이점

 

useEffect와 비슷하지만 useLayoutEffect는 동기적으로 실행되며 effect를 DOM 변경사항이 적용되기 전에 실행합니다.

 

useEffect는 렌더링된 컴포넌트가 화면에 그려진 후에 effect가 실행되고 비동기적(asynchronous)이지만

 

useLayoutEffect는 렌더링된 컴포넌트가 화면에 그려지기전에 effect가 실행되고 동기적( synchronous)라는 차이점이 있습니다.

 

<예시>

 

import React, { useLayoutEffect, useEffect, useState } from "react"

function App2() {
  const [name, setName] = useState("");
  const [age, setAge] = useState(0)


  useEffect( ()=> {
    setName("Mike");
    setAge(25);
  }, [])

  return (
    <div>
      <div>His name is {name} and his age is {age}</div>
    </div>
  )
}

export default App2;

 

 

위 코드의 실행순서는

 

  1. name, age state 생성
  2. <div>His name is and  his age is 0<div> 렌더링 후 화면에 그려짐
  3. effect 실행 -> 내부 setName, setAge 실행
  4. state 변경됨에 따라 리렌더링 실행

 

화면에 컴포넌트가 그려지고 다시 리렌더링이 발생하는것을 알 수 있습니다. 이는 flickering(화면 깜빡임)을 유발할 수 있습니다.

 

이러한 경우에 useEffect 대신 useLayoutEffect를 사용한다면?

 

화면에 렌더링된 컴포넌트가 그려지기전에 effect가 실행되므로 실행순서는

 

  1. name, age state 생성
  2. <div>His name ... 컴포넌트 렌더링
  3. effect 실행 -> 내부 setName, setAge 실행
  4. 컴포넌트 리렌더링 후 화면에 그려짐

 

화면에 그려지는 작업이 한 번 뿐이므로 flickering이 일어나지 않습니다.

 

 

그러면 언제 useEffect를 사용하고 useLayoutEffect를 사용할까요?

 

해외 블로그에서는 useEffect를 주로 사용하고 필요한 경우에만 useLayoutEffect로 교체하라고합니다.

 

DOM을 직접적으로 건드리지 않거나 DOM 변경이 눈에 보이지 않는다면 useEffect

 

DOM을 적접적으로 건드리거나 퍼포먼스 측정이 필요하다면 useLayoutEffect를 사용하라고합니다.

 

 


 

정리

 

useLayoutEffect는 동기적으로 실행되고 렌더링 결과가 화면에 그려지기 전에 effect가 실행됩니다.

 

useEffect는 비동기적으로 실행되고 렌더링 결과가 화면에 그려진 후에 effect가 실행됩니다. 

 

 

우선 빠르게 레이아웃을 보여주고 무거운 작업(예: data fetching)을 한 뒤에 리렌더링하는 방식이 유리하다면 useEffect

 

화면에 렌더링 결과가 그려지기전에 작업을 마무리하는것이 유리하다면 useLayoutEffect

 

 

 

 

출처

https://ko.reactjs.org/docs/hooks-effect.html

https://velog.io/@yes3427/React-Side-Effect

https://points.tistory.com/86

https://ko.reactjs.org/docs/hooks-reference.html#uselayouteffect

https://merrily-code.tistory.com/46

https://darrengwon.tistory.com/864

'Programming > React' 카테고리의 다른 글

Redux - Redux 장단점  (0) 2022.08.17
React - Context API  (0) 2022.08.02
React - React 18 새로운 점  (0) 2022.08.01
React - React-Query  (0) 2022.07.30
React - 리액트 렌더링 성능 향상을 위해 할 수 있는 일  (0) 2022.07.30