(SEB_FE) Section4 Unit3 useMemo & useCallback 간단 실습

PYM·2023년 5월 22일
0

(SEB_FE) SECTION4

목록 보기
8/24

💜useMemo를 이용하여 앱 최적화하기

💟최적화 전 App.js

import React, { useState } from "react";
import "./styles.css";
import { add } from "./add";

export default function App() {
  const [name, setName] = useState("");
  const [val1, setVal1] = useState(0);
  const [val2, setVal2] = useState(0);
  const answer = add(val1, val2);

  return (
    <div>
      <input
        className="name-input"
        placeholder="이름을 입력해주세요"
        value={name}
        type="text"
        onChange={(e) => setName(e.target.value)}
      />
      <input
        className="value-input"
        placeholder="숫자를 입력해주세요"
        value={val1}
        type="number"
        onChange={(e) => setVal1(Number(e.target.value))}
      />
      <input
        className="value-input"
        placeholder="숫자를 입력해주세요"
        value={val2}
        type="number"
        onChange={(e) => setVal2(Number(e.target.value))}
      />
      <div>{answer}</div>
    </div>
  );
}

💟최적화 전 add.js

export const add = (num1, num2) => {
  console.log("숫자가 들어옵니다.");
  return Number(num1) + Number(num2);
};

최적화 전 실행 화면

실제로 연산 로직에 영향을 주는 값은 val1val2 값인데,
보다시피 그 두 값이 아닌 name 값을 수정해도 add 함수가 계속 같은 결과값을 리턴함에도 불구하고 불필요하게 계속 호출되고 있는 상태이다.

useMemo를 사용해서 add 함수의 호출을 최소화할 수 있다.
즉 이름을 입력할 때는 add 함수가 호출되지 않아야 최적화가 된 컴포넌트인 것.

💟최적화 후 App.js (add.js 파일은 변경 없음)

import React, { useState, useMemo } from "react";
import "./styles.css";
import { add } from "./add";

export default function App() {
  const [name, setName] = useState("");
  const [val1, setVal1] = useState(0);
  const [val2, setVal2] = useState(0);
  // const answer = add(val1, val2);

  const answer = useMemo(() => add(val1, val2), [val1, val2]);
 // 이 줄 아래 코드는 최적화 전과 동일 

기존의 answer 변수를 useMemo를 사용해서 val1val2의 값이 변할때만 새로이 add 함수를 실행하고 그렇지 않을 경우에는 memoization 해 둔 answer값을 재사용하도록 해주었다.

최적화 후 실행 화면

최적화를 하고 나니, 이제는 더이상 이름 값이 변경하더라도 add 함수가 실행되지 않는 것을 확인할 수 있다!


💜useCallback를 이용하여 앱 최적화하기

💟최적화 전 App.js

import { useState } from "react";
import "./styles.css";
import List from "./List";

export default function App() {
  const [input, setInput] = useState(1);
  const [light, setLight] = useState(true);

  const theme = {
    backgroundColor: light ? "White" : "grey",
    color: light ? "grey" : "white"
  };

  const getItems = () => {
    return [input + 10, input + 100];
  };

  const handleChange = (event) => {
    if (Number(event.target.value)) {
      setInput(Number(event.target.value));
    }
  };

  return (
    <>
      <div style={theme} className="wall-paper">
        <input
          type="number"
          className="input"
          value={input}
          onChange={handleChange}
        />
        <button
          className={(light ? "light" : "dark") + " button"}
          onClick={() => setLight((prevLight) => !prevLight)}
        >
          {light ? "dark mode" : "light mode"}
        </button>
        <List getItems={getItems} />
      </div>
    </>
  );
}

💟최적화 전 List.js

import { useState, useEffect } from "react";

function List({ getItems }) {
  /* Initial state of the items */
  const [items, setItems] = useState([]);

  /* This hook sets the value of items if 
     getItems object changes */
  useEffect(() => {
    console.log("아이템을 가져옵니다.");
    setItems(getItems());
  }, [getItems]);

  /* Maps the items to a list */
  return (
    <div>
      {items.map((item) => (
        <div key={item}>{item}</div>
      ))}
    </div>
  );
}

export default List;

최적화 전 실행 화면

보다시피 최적화 전에는 숫자 값이 아닌 다크모드 & 라이트모드 변경 테마 버튼을 클릭해도 getItem 함수가 불필요하게 실행되어 콘솔창에 "아이템을 가져옵니다."가 찍히는 것을 확인할 수 있다.

이 동작의 이유는 버튼을 누를 때도 앱이 리렌더링 되므로, App 내부의 getItems() 함수가 다시 만들어진다. 새로이 만들어진 함수는 이전의 함수와 참조 비교 시 다른 함수이기 때문에 List 구성 요소 내에서 useEffect Hook은 setItems를 호출하고 종속성이 변경됨에 따라 “아이템을 가져옵니다.”를 출력하는 것.

💟최적화 후 App.js (List.js 파일은 변경 없음)

import { useCallback, useState } from "react";
import "./styles.css";
import List from "./List";

export default function App() {
  const [input, setInput] = useState(1);
  const [light, setLight] = useState(true);

  const theme = {
    backgroundColor: light ? "White" : "grey",
    color: light ? "grey" : "white"
  };

  const getItems = useCallback(() => {
    return [input + 10, input + 100];
  }, [input]);
// 아래 코드는 모두 동일 

최적화 후 실행 화면

useCallback을 사용해서 getItems 함수를 input의 값이 바뀔때만 실행하도록 하면 테마 값이 바뀌어도 불필요하게 getItems 함수가 호출되지 않는 것을 확인할 수 있다.

profile
목표는 "함께 일하고 싶은, 함께 일해서 좋은" Front-end 개발자

0개의 댓글