useMemo

leekoby·2023년 3월 22일
0

React

목록 보기
4/10
post-thumbnail

🔧변경내용🔨

제목날짜내용
발행일23.03.22



📌들어가기에 앞서

해당 포스트는 useMemo에 대해 학습한 내용을 정리하며 기록한 내용입니다.




컴포넌트는 기본적으로 상태가 변경되거나 부모 컴포넌트가 렌더링이 될 때마다 리렌더링을 하는 구조로 이루어져 있다.

너무 잦은 리렌더링은 앱의 성능에 좋지 않은 영향을 끼친다.

[그림] 너무 많은 렌더링은 앱에 안 좋은 성능을 미치는 극단적인 예

React Hook함수 컴포넌트가 상태를 조작하고 및 최적화 기능을 사용할 수 있게끔 하는 메소드

렌더링 최적화를 위한 Hook도 존재하는데, useCallbackuseMemo가 바로 그 역할을 하는 Hook




📖 useMemo란?

useMemo특정 값(value)를 재사용하고자 할 때 사용하는 Hook

아래 코드를 보면서 useMemo에 대해 좀 더 알아보자.

function Calculator({value}){

	const result = calculate(value);

	return <>
      <div>
		{result}
      </div>
  </>;
}

해당 컴포넌트는 props로 넘어온 value값을 calculate라는 함수에 인자로 넘겨서 result 값을 구한 후, <div> 엘리먼트로 출력을 하고 있다.

만약 여기서 calculate가 내부적으로 복잡한 연산을 해야 하는 함수라 계산된 값을 반환하는 데에 시간이 몇 초 이상 걸린다고 가정해 보자.

그렇다면 해당 컴포넌트는 렌더링을 할 때마다 이 함수를 계속해서 호출할 것이고, 그 때마다 시간이 몇 초 이상 소요가 될 것이다.

이 몇 초의 지연은 렌더링에도 영향을 미칠 것이고, 사용자는 “앱의 로딩 속도가 느리네?”라는 생각을 하게 될 것이다.

/* useMemo를 사용하기 전에는 꼭 import해서 불러와야 합니다. */
import { useMemo } from "react";

function Calculator({value}){

	const result = useMemo(() => calculate(value), [value]);

	return <>
      <div>
			{result}
      </div>
  </>;
}

여기 value 를 인자로 받는 Calculator 컴포넌트가 있다.

value 는 일종의 값으로서, 이 값이 계속 바뀌는 경우라면 어쩔 수 없겠지만, 렌더링을 할 때마다 이 value값이 계속 바뀌는 게 아니라고 생각해 보자.

그럼 이 값을 어딘가에 저장을 해뒀다가 다시 꺼내서 쓸 수만 있다면 굳이 calculate 함수를 호출할 필요도 없을 것이다.

여기서 useMemo Hook을 사용할 수 있다.

이런 식으로 useMemo를 호출하여 calculate를 감싸주면,

이전의 렌더링과 새로운 렌더링의 값을 비교해 value값이 동일할 경우에는 이전 렌더링의 value값을 그대로 재활용할 수 있게 된다.

이는 메모이제이션(Memoization) 개념과 긴밀한 관계가 있다.


Memoization

메모이제이션(Memoization)은 알고리즘에서 자주 나오는 개념

기존에 수행한 연산의 결과값을 메모리에 저장을 해두고, 동일한 입력이 들어오면 재활용하는 프로그래밍 기법

이 메모이제이션을 적절히 사용한다면 굳이 중복 연산을 할 필요가 없기 때문에 앱의 성능을 최적화할 수 있다.

useMemo는 바로 이 개념을 이용하여 복잡한 연산의 중복을 피하고 React 앱의 성능을 최적화시킨다.

직접 메모이제이션 개념을 이용하여 로직을 구현할 수도 있겠으나, useMemo Hook을 호출한다면 이런 로직을 직접 구현하는 것을 대신해주기 때문에 훨씬 간편하다고 할 수 있다.




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

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);
 const answer = useMemo(() => add(val1, val2), [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 함수가 계속해서 호출된다.

불필요한 렌더링을 방지하기 위해서 add 함수를 useMemo 로 감싼 후 의존성을 설정해주었다.

이름을 입력할 때는 렌더링되지 않고 숫자의 값이 변경될 때만 렌더링되게 되었다.




📚 레퍼런스

코드스테이츠 수업자료

useMemo | react 공식문서

Memoization

0개의 댓글