티스토리 뷰

React

[React] useMemo, useCallback

이채야채 2022. 5. 7. 16:07

*이화랑님 블로그와, 리액트공식문서를 보고 옮겨적은 내용입니다.

 

https://leehwarang.github.io/2020/05/02/useMemo&useCallback.html

 

 

useMemo, useCallback을 하기전에 알아야하는 상식?

 

1. 함수형 컴포넌트는 그냥 함수다. 함수형컴포넌트는 단지 jsx를 반환하는 함수이다.

2. 컴포넌트가 렌더링된다? 누군가 그 함수(컴포넌트)를 호출하였기에 실행된것이다. 

함수가 실행될때마다 내부에 선언되어있는 표현식도(변수, 또다른 함수) 매번 다시 선언되어 사용된다.

3. 컴포넌트는 자신의 state가 변경되거나, 부모에게서 받은 Props가 변경되었을때마다 리렌더링된다. (하위 컴포넌트에서 최적화를 하지 않으면, 리렌더링된다.)

 


useMemo


'메모리제이션된 값을 반환하다' 라는 문장이 핵심이다.

a,b를 부모컴퍼넌트에서 하위컴포넌트가 전달받는다고 가정해보자.

하위컴포넌트는 a,b를 전달받으면 ➡️ a를 가공하고, b를 가공해서 새로운 값을 보여주는 역할을 한다.

하위컴포넌트는 넘겨받은 인자중에 하나라도 변경될때마다 전체 리렌더링이된다.

 

props.a만 변경되었을때.. props.b도 다시 함수를 호출해서 재계산해야할까? 그냥 이전에 있던 값을 쓰고싶은데...

불필요한 호출과 리렌더링인것같은데..?

// App.js

import Info from "./Info";

const App = () => {
  const [color, setColor] = useState("");
  const [movie, setMovie] = useState("");

  const onChangeHandler = e => {
    if (e.target.id === "color") setColor(e.target.value);
    else setMovie(e.target.value);
  };

  return (
    <div className="App">
      <div>
        <label>
          What is your favorite color of rainbow ?
          <input id="color" value={color} onChange={onChangeHandler} />
        </label>
      </div>
      <div>
        What is your favorite movie among these ?
        <label>
          <input
            type="radio"
            name="movie"
            value="Marriage Story"
            onChange={onChangeHandler}
          />
          Marriage Story
        </label>
        <label>
          <input
            type="radio"
            name="movie"
            value="The Fast And The Furious"
            onChange={onChangeHandler}
          />
          The Fast And The Furious
        </label>
        <label>
          <input
            type="radio"
            name="movie"
            value="Avengers"
            onChange={onChangeHandler}
          />
          Avengers
        </label>
      </div>
      <Info color={color} movie={movie} />
    </div>
  );
};

export default App;
// Info.js

const getColorKor = color => {
    console.log("getColorKor");
    switch (color) {
      case "red":
        return "빨강";
      case "orange":
        return "주황";
      case "yellow":
        return "노랑";
      case "green":
        return "초록";
      case "blue":
        return "파랑";
      case "navy":
        return "남";
      case "purple":
        return "보라";
      default:
        return "레인보우";
    }
  };

  const getMovieGenreKor = movie => {
    console.log("getMovieGenreKor");
    switch (movie) {
      case "Marriage Story":
        return "드라마";
      case "The Fast And The Furious":
        return "액션";
      case "Avengers":
        return "슈퍼히어로";
      default:
        return "아직 잘 모름";
    }
  };


const Info = ({ color, movie }) => {
  const colorKor = getColorKor(color);
  const movieGenreKor = getMovieGenreKor(movie);

  return (
    <div className="info-wrapper">
      제가 가장 좋아하는 색은 {colorKor} 이고, <br />
      즐겨보는 영화 장르는 {movieGenreKor} 입니다.
    </div>
  );
};

export default Info;

 

원래는 getColorKor, getMovieGenreKor이 함께 렌더링되나,

 

useMemo를 사용한다면?

import React, { useMemo } from "react";

const colorKor = useMemo(() => getColorKor(color), [color]);
const movieGenreKor = useMemo(() => getMovieGenreKor(movie), [movie]);

 

이전과는 다르게 변경되는 함수 하나만 호출이된다.

 

사이드프로젝트 처럼 간단한 프로젝트는 차이가 미미하여, useState와 useEffect만을 주로 사용하지만

프로젝트가 커질수록 호출 함수의 재계산하는 로직이 복잡하다면 불필요하게 비싼 계산을 하는 것을 막을 수 있다.


useCallback


'메모리제이션된 함수를 반환한다'라는 문장이 핵심이다.

  • useMemo => 메모리제이션된  반환
  • useCallback => 메모리제이션된 함수 반환

useMemo와 useCallback을 배우기 전에 알아야 하는 것들 중 두 번째로 컴포넌트가 렌더링 될 때마다 내부에 선언되어 있던 표현식(변수, 또다른 함수 등)도 매번 다시 선언되어 사용된다. 라고 되어있다.

 

그렇다면 App.js안에있는 onChangeHandler 는 App.js안에있는 useState가 변경될때마다 다시 재선언되고 사용되야할 필요가 있을까?

 

// App.js

import Info from "./Info";

const App = () => {
  const [color, setColor] = useState("");
  const [movie, setMovie] = useState("");

  const onChangeHandler = e => {
    if (e.target.id === "color") setColor(e.target.value);
    else setMovie(e.target.value);
  };

 

이럴때! useCallback을 사용한다.

 

// App.js

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

const onChangeHandler = useCallback(e => {
    if (e.target.id === "color") setColor(e.target.value);
    else setMovie(e.target.value);
  }, []);

 

 

 

하위 컴포넌트에 최적화 설정을 해주지 않으면 부모에게서 받는 props가 변경되지 않았더라도 리렌더링 되는게 기본이다.

=> 이게싫다? => react Memo를 사용하면된다.

 

  • 함수는 오로지 자기 자신만이 동일하기 때문에 상위 컴포넌트에서 callback 함수를 (같은 함수이더라도) 재선언한다면 props로 callback 함수를 넘겨 받는 하위 컴포넌트 입장에서는 props가 변경 되었다고 인식한다.

 

https://ui.toast.com/weekly-pick/ko_20190731

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2025/09   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함