본문 바로가기
웹/(React)리액트

(React) useMemo와 useCallback 사용법

by 공부가싫다가도좋아 2021. 8. 24.
반응형

(React) useMemo와 useCallback 사용법


* 이 포스팅은 개인적인 복습을 위해 정리한 포스팅입니다.

참고 서적: "리액트를 다루는 기술"

참고 링크:

1. useReducer/useCallback/useMemo 제대로 알고 사용하기

2. useCallback 과 useMemo의 차이점  <11:10 부터 useCallback과 useMemo차이점 설명

 

포스팅

1. useMemo & useCallback

2. useMemo에 대해서

3. useCallback에 대해서


useMemo & useCallback

> useMemo와 useCallback은 매우 유사하다.

> 내부에서 발생하는 연산을 최적화한다.

> 특정 값이 바뀌었을 때만 연산을 실행하고, 바뀌지 않았으면 이전에 연산했던 

결과를 다시 사용하는 방식이다.

> 메모제이션용 메모리가 필요하므로 useMemo와 useCallback을 남용하면 안된다.

 

useMemo VS useCallback

> useMemo 는 값을 반환

> useCallback은 함수를 반환

 


useMemo

useMemo 쓰는 형식

const avg = useMemo(() =>{
	//내용
},[값]);

< useMemo를 사용하지 않았을 때 코드 >

Average.js

import React, { useState } from 'react';

const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState('');

  const getAverage = () => {
    console.log('평균값 계산 중...');
    if (list.length === 0) return 0;
    const sum = list.reduce((a, b) => a + b);
    return sum / list.length;
  };
  const onChange = (e) => {
    setNumber(e.target.value);
  };

  const onInsert = () => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber('');
  };


  return (
    <div>
      <input value={number} onChange={onChange} />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>평균값:</b> {getAverage()}
      </div>
    </div>
  );
};

export default Average;

 

App.js

import React from 'react';
import Average from './Average';

const App = () => {
  return <Average />;
};

export default App;

 

<결과>

> 글자 입력 시에도 getAverage함수가 동작하기 때문에 콘솔창에 "평균값 계산중... "이 뜸

> 버튼 클릭시에도 getAverage함수가 동작하기 때문에 콘솔창에 "평균값 계산중..."이 뜸

> 종합적으로, getAverage함수가 필요하지 않은 동작에서도 작동이 됨.

 

< useMemo를 사용했을 때 코드 >

Average.js

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

const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState('');
  
  const getAverage = useMemo(() => {
    console.log('평균값 계산 중...');
    if (list.length === 0) return 0;
    const sum = list.reduce((a, b) => a + b);
    return sum / list.length;
  }, [list]); //list값이 업데이트 될때만 실행

  const onChange = (e) => {
    setNumber(e.target.value);
  };

  const onInsert = () => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber('');
  };

  return (
    <div>
      <input value={number} onChange={onChange} />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>평균값:</b> {getAverage} 
        {/* useMemo는 값을 반환 */} 
      </div>
    </div>
  );
};

export default Average;

> useMemo는 값을 반환 하므로 getAverage() 가 아닌 getAverage로 쓰임.

App.js

import React from 'react';
import Average from './Average';

const App = () => {
  return <Average />;
};

export default App;

 

<결과>

> 첫 렌더링과 값 입력 할때만 렌더링, 즉 [ ] 안에 써준 값 list가 업데이트 될 때만 렌더링.


useCallback

>useMemo를 책에 쓰인 방식으로 바꿔보았습니다.

> onChange와 onInsert함수에 useCallback을 감싸므로,  [ ]<-괄호 안의 값이

바뀌었을 때만 함수를 생성해 줍니다.

(* useCallback을 사용하지 않은 경우 리렌더링 될때마다 함수를 새로 만들어 줍니다.)

Average.js

import React, { useState, useCallback, useMemo } from 'react';

const getAverage = (numbers) => {
  console.log('평균값 계산 중...');
  if (numbers.length === 0) return 0;
  const sum = numbers.reduce((a, b) => a + b);
  return sum / numbers.length;
};

const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState('');

  const onChange = useCallback((e) => {
    setNumber(e.target.value);
  }, []);

  const onInsert = useCallback(() => {
    const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber('');
  }, [number, list]);

  const avg = useMemo(() => getAverage(list), [list]);

  return (
    <div>
      <input value={number} onChange={onChange} />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <div>
        <b>평균값:</b> {avg}
      </div>
    </div>
  );
};

export default Average;

 

App.js

import React from 'react';
import Average from './Average';

const App = () => {
  return <Average />;
};

export default App;

 

반응형

댓글