[ React ] useEffect vs useLayoutEffect

exceed_96·2024년 2월 20일
0

React

목록 보기
5/18
post-thumbnail

React프로젝트를 진행하다보면 사이드 이펙트(Side Effect)를 위한 useEffect훅을 자주 사용할 것이다.

예를 들면 서버에서 데이터를 받아오거나, 혹은 함수 내에서 전역변수나 정적 변수를 수정하는 등의 작업을 할 때 useEffect훅 내부에서 사용하는 케이스를 많이 봤을 것이다.

그와 비슷한 역할을 해주는 훅이 있는데 바로 useLayoutEffect이다.

useEffectuseLayoutEffect는 동작시점에 따라서 미묘한 차이가 있는데 이번 포스팅에서는 두 개의 훅을 비교해보고 어떤식으로 동작하는지 알아보자.



1. useEffect훅이란?

useEffect훅은 컴포넌트 내에서 사이드 이펙트를 수행할 수 있도록 하는 훅이다.

사이드 이펙트는 데이터 가져오기, DOM수정 등등 함수나 프로그램이 실행될 때, 외부에 있는 상태를 변경하거나 다른 외부 동작을 수행하는 것을 의미한다.

주로 useEffect훅은 2가지 조건에 의해서 발동된다.

  1. 페이지가 처음 렌더링 되고 난 후 실행
  2. useEffect훅의 의존성배열에 지정된 값이 변경될 때 실행


2. useEffect훅 사용법

useEffect훅을 사용하기 위해서는 해당 훅을 import해줘야 한다.

import { useEffect } from "react"

useEffect훅을 사용하는 방법은 크게 4가지로 생각할 수 있다.

의존성 배열 x

const Info = (): JSX.Element => {
  const [number, setNumber] = useState<number>(0);

  const btnHandler = () => {
    setNumber((prevState) => prevState + 1);
  };

  useEffect(() => {
    console.log(number);
  }); //의존성 배열 제거

  return (
    <>
      <button onClick={btnHandler}>Count</button>
      <ExamDiv>{number}</ExamDiv>
    </>
  );
};

의존성 배열을 제거하고 사용하는 형태이다.

하지만 위 방법은 주로 사용하지 않는 방법이다.

의존성 배열이 없기때문에 해당 컴포넌트가 업데이트 될 때마다 실행되게 된다.

즉, 원치않은 경우에 사이드 이펙트가 계속 실행되는 것이다.


의존성 배열 원소 X

import { useEffect, useState } from "react";
import styled from "styled-components";

const ExamDiv = styled.div`
  margin-top: 16px;
`;

const Info = (): JSX.Element => {
  const [number, setNumber] = useState<number>(0);

  const btnHandler = () => {
    setNumber((prevState) => prevState + 1);
  };

  useEffect(() => {
    console.log(number);
  }, []); // 빈 의존성 배열

  return (
    <>
      <button onClick={btnHandler}>Count</button>
      <ExamDiv>{number}</ExamDiv>
    </>
  );
};

export default Info;

빈 의존성 배열은 컴포넌트가 렌더링 될때만 실행된다.

즉, 해당 컴포넌트가 렌더링 된 상태에서 컴포넌트가 업데이트 된다고 해도 콜백함수 내에 로직은 실행되지 않는다.


의존성 배열 원소 O

import { useEffect, useState } from "react";
import styled from "styled-components";

const ExamDiv = styled.div`
  margin-top: 16px;
`;

const Info = (): JSX.Element => {
  const [number, setNumber] = useState<number>(0);
  const [active, setActive] = useState<boolean>(false);

  const btnHandler = () => {
    setNumber((prevState) => prevState + 1);
    setActive((prevState) => !prevState);
  };

  useEffect(() => {
    if (active) { 			//active가 true일때만 console.log
      console.log(number);	// 1, 3, 5, 7, 9, 11, 13, 15, 17 .......
    }
  }, [active]); 			//active state를 의존성배열 원소 지정

  return (
    <>
      <button onClick={btnHandler}>Count</button>
      <ExamDiv>{number}</ExamDiv>
    </>
  );
};

export default Info;

컴포넌트를 처음 렌더링 할 때 한번 실행되고 의존성 배열에 있는 원소가 업데이트 될 때마다 실행된다.

배열에는 하나의 원소가 아닌 여러 원소를 정의할 수 있다.


클린업(clean up)함수 정의

import { useEffect } from "react";

const Info = (): JSX.Element => {
  useEffect(() => {
    console.log("component mount");
    return () => { 						//클린업 함수 정의
      console.log("component unmount"); //해당 컴포넌트가 언마운트 될 때 클린업 함수 실행
    };
  }, []);

  return <></>;
};

export default Info;

위와같이 해당 컴포넌트가 언마운트(unmount)될 시 useEffect의 클린업 함수가 동작한다.



2. useLayoutEffect란?

import { useLayoutEffect } from "react";

const Info = (): JSX.Element => {
  useLayoutEffect(() => {
    console.log("component mount");
    return () => { 						//클린업 함수 정의
      console.log("component unmount"); //해당 컴포넌트가 언마운트 될 때 클린업 함수 실행
        }, []);

  return <></>;
};

export default Info;

useLayoutEffect훅도 컴포넌트가 렌더링 된 후 실행된다.

따라서 useEffect훅과 사용법이 완전히 동일하다.


그럼 둘의 차이가 뭐길래 훅이 별도로 존재하는 걸까?



3. useEffect vs useLayoutEffect

useEffect

useEffect는 컴포넌트들이 render, paint된 후 실행된다.

렌더링 된 요소들이 화면에 paint된 후 useEffect콜백함수가 실행되기 때문에, useEffect내부에 DOM을 수정하는 코드가 있을 경우 사용자 시점에서는 화면의 깜빡임을 보게 된다.

따라서 useEffect의 경우 데이터 가져오기, API호출 등 비동기 처리 작업, 렌더링과 관련없는 사이드 이펙트, 이벤트 리스너 등의 비동기 처리 작업에 유용하다.


useLayoutEffect


useLayoutEffect는 컴포넌트들이 render된 후 실행된다.

render된 후 useLayoutEffect 콜백함수를 실행한 다음 paint작업을 해서 사용자에게 보여주게 되는 것이다.

따라서 이런 경우에는 DOM을 조작하는 코드가 있더라도 사용자 시점에서는 화면의 깜빡임을 경험하지 않는다.

다만, 콜백함수 내부에 있는 로직의 실행시간이 오래걸릴수록 UX측면에서 나쁜 경험을 한다는 단점이 있다.

따라서 오랜 시간이 걸리지 않는 DOM요소의 크기, 위치 등 레이아웃 정보를 사용하는 작업처리 등에 유용하다.



4. 마치며

이번 포스팅에서는 useEffect, useLayoutEffect훅에 대해서 간단히 비교해보았다.

사실 useEffect훅으로 데이터를 백에서 받아오면 아주 잠깐 깜빡이는게 싫어서 대체 방법에 대해서 알아보다 useLayoutEffect훅에 대해서 알아냈고 사용해봤지만..

확실히 사이드 이펙트의 사이즈가 클 경우에는 브라우저에 paint작업까지 된 요소들을 렌더링 하기까지 오래걸린다는 단점이 조금 치명적이다고 생각한다.

다만, 사이즈가 작은 사이드 이펙트를 실행하기에는 괜찮은 방법 같다.



5. Reference

https://pubudu2013101.medium.com/what-is-the-real-difference-between-react-useeffect-and-uselayouteffect-51723096dc19

profile
개발진행형

0개의 댓글

관련 채용 정보