React.memo,useCallback,useMemo

개발자지망생·2023년 10월 26일
0

React

목록 보기
12/24
post-thumbnail

1 React.memo

컴포넌트를 메모리에 저장한다.

React.memo는 부모 컴포넌트가 변경될 때 자식 컴포넌트가 바뀐게 없는데 바뀌면서 렌더링이 일어날 경우를 방지하기 위해 사용된다.

코드 예시

아래의 코드를 살펴보면 +버튼과 -버튼을 누를 경우 아래 있는 Box1 컴포넌트도 같이 랜더링 된다.

import React, { useState } from "react";
import Box1 from "./components/Box1"

const boxesStyle = {
  display: "flex",
  marginTop: "10px",
};

function App() {
  console.log("App 컴포넌트가 렌더링되었습니다!");

  const [count, setCount] = useState(0);

  // 1을 증가시키는 함수
  const onPlusButtonClickHandler = () => {
    setCount(count + 1);
  };

  // 1을 감소시키는 함수
  const onMinusButtonClickHandler = () => {
    setCount(count - 1);
  };

  return (
    <>
      <h3>카운트 예제입니다!</h3>
      <p>현재 카운트 : {count}</p>
      <button onClick={onPlusButtonClickHandler}>+</button>
      <button onClick={onMinusButtonClickHandler}>-</button>
      <div style={boxesStyle}>
        <Box1 />
      </div>
    </>
  );
}

export default App;

이를 방지하기위해 React.memo를 사용하는대 사용방법은 간단하다.

아래 코드에서 export default Box1 하는 곳을
export default React.memo(Box1)로 변경해 주면 메모리에 저장되어 +,- 버튼을 눌러서 숫자가 바껴도 Box1은 리 렌더링 되지 않는다.

import React from "react";

const boxStyle = {
  width: "100px",
  height: "100px",
  backgroundColor: "#91c49f",
  color: "white",

  // 가운데 정렬 3종세트
  display: "flex",
  justifyContent: "center",
  alignItems: "center",
};

function Box1() {
  console.log("Box1이 렌더링되었습니다.");
  return <div style={boxStyle}>Box1</div>;
}

export default React.memo(Box1);

2 useCallback

useCallback은 인자로 들어오는 함수 자체를 메모리에 저장한다.

코드 예시

아래 코드를 보면 props를 이용해서 initCount를 보내주고있습니다. React.memo가 되어있는 상태에서도 +,- , 초기화
버튼을 누를때마다 Box1 컴포넌트가 리렌더링 됩니다.

그 이유는 불변성에 있습니다. props로 내려주고 있는 함수는
App컴포넌트가 리 랜더링 될 때 마다 메모리에서 새로운 주소가 할당되어 변경되는 거로 인식되기 때문입니다.


	// count를 초기화해주는 함수
  const initCount = () => {
    setCount(0);
  };

  return (
    <>
      <h3>카운트 예제입니다!</h3>
      <p>현재 카운트 : {count}</p>
      <button onClick={onPlusButtonClickHandler}>+</button>
      <button onClick={onMinusButtonClickHandler}>-</button>
      <div style={boxesStyle}>
        <Box1 initCount={initCount} />
      </div>
    </>
  );
}

function Box1({ initCount }) {

  const onInitButtonClickHandler = () => {
    initCount();
  };

  return (
    <div style={boxStyle}>
      <button onClick={onInitButtonClickHandler}>초기화</button>
    </div>
  );
}
export default React.memo(Box1)

적용 방법

아래 코드처럼 변경하고 나면 Box1은 다시 관계없이 리 렌더링 되지않습니다.

// 변경 전
const initCount = () => {
  setCount(0);
};

// 변경 후
const initCount = useCallback(() => {
  setCount(0);
}, []);

3 useMemo

값 , value 를 메모리에 저장한다.

코드 예시

아래 코드에서 heavyWork함수는 단순히 100을 리턴하는 함수이지만 리렌더링 시에 계속 for문 작업을 진행함으로서 계속 느려질수있습니다.

useMemo를 사용해서 값을 메모리에 저장해두면 바로바로 리 렌더링이 되는걸 볼수있습니다.

import React, { useState, useMemo } from "react";

function HeavyButton() {
  const [count, setCount] = useState(0);

  const heavyWork = () => {
    for (let i = 0; i < 1000000000; i++) {}
    return 100;
  };

	// CASE 1 : useMemo를 사용하지 않았을 때
  const value = heavyWork();

	// CASE 2 : useMemo를 사용했을 때
  // const value = useMemo(() => heavyWork(), []);

  return (
    <>
      <p>나는 {value}을 가져오는 엄청 무거운 작업을 하는 컴포넌트야!</p>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        누르면 아래 count가 올라가요!
      </button>
      <br />
      {count}
    </>
  );
}

export default HeavyButton;

주의사항

useMemo를 너무남용할시 별도의 메모리 확보를 너무 많이 하게 되기 때문에 오히려 성능이 안 좋아질 수 있습니다.

profile
프론트엔드개발자를 목표로 공부중입니다.

0개의 댓글