본문 바로가기
Frontend/React

[React] Hooks : optimizing 성능 최적화(2) - useMemo

by pin9___9 2022. 12. 22.
728x90

useMemo란?

useMemo는 컴포넌트의 성능을 처적화시킬 수 있는 대표적인 react hooks 중 하나입니다. useMemo에서 Memo는 Memoizaion을 뜻합니다. Memoization이란 기존에 수향하 연산의 결과값을 어딘가에 저장해 두고 동일한 입력이 들어오면 재활용하는 프로그래밍 기법입니다.

 

🔥기억하기!!

  • 컴포넌트가 렌더링 된다는 것은 누군가가 그 함수(컴포넌트)를 호출하여 실행되는 것을 뜻합니다. 심지어 하위 컴포넌트에 최적화 설정을 해주지 않으면 부모에게 받은 props가 변경되지 않았더라도 리렌더링 됩니다.
  • 컴포넌트는 자신의 state가 변경되거나, 부모에게서 받은 props가 변경될 때마다 리렌더링 됩니다. 심지어 하위 컴포넌트에 최적화 설정을 하지 않으면 부모에게 받는 props가 변경되지 않았더라도 리렌더링 됩니다.

 

useMemo 사용하기

// src/App.jsx

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

const App = () => {
  const [value, setValue] = useState("");

  const onChangeHandler = (e) => {
    setValue(e.target.value);
  };

  const data = [
    {
      id: 1,
      title: "react",
    },
  ];

  return (
    <div>
      <input type="text" value={value} onChange={onChangeHandler} />
      <List data={data} />
    </div>
  );
};

export default App;

 

// src/components/List.jsx

import React, { memo } from "react";

const List = ({ data }) => {
  console.log("리렌더링되고 있어요.");
  return (
    <div>
      {data.map((todo) => (
        <div key={todo.id}>{todo.title}</div>
      ))}
    </div>
  );
};

export default memo(List);

App.js 에서 data라는 배열을 List라는 자식 컴포넌트에 넘겨주고 있습니다. List가 memo를 사용하고 있음에도 계속 리렌더링이 될텐데요. 그 원인은 props로 받은 배열이 App.js가 리렌더링될때마다 재생성되고 있기 때문입니다.

 

data 라는 배열을 useMemo를 통해서 재성생되지 않도록 해줍니다. 아래의 변경코드처럼 useMemo를 사용하면 App.js가 리렌더링을 하더라도 재생성되지 않기 때문에 Button.js도 리렌더링을 하지 않습니다.

 

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

const App = () => {
  const [value, setValue] = useState("");

  const onChangeHandler = (e) => {
    setValue(e.target.value);
  };

  const data = useMemo(() => {
    return [
      {
        id: 1,
        title: "react",
      },
    ];
  }, []);

  return (
    <div>
      <input type="text" value={value} onChange={onChangeHandler} />
      <List data={data} />
    </div>
  );
};

export default App;

 

 

728x90

댓글