Programming/React

[React] Hooks - useMemo

Bam_t 2021. 11. 16. 19:03
728x90

1. useMemo

이번에 소개할 Hook인 useMemo는 컴포넌트 내부 중에서도 연산에 대해서 최적화를 하는 Hook입니다. Memo라는 것은 우리가 간단하게 남기는 쪽지라기보단, 메모이제이션(memoization)이라는 용어에서 왔습니다. 이 메모이제이션은 컴퓨터공학 용어로 연산을 반복할 때 이전의 수행했던 값을 따로 저장해 반복 수행을 줄여 최적화를 하는 기술입니다.

우선 useMemo를 사용하지 않은 예제로 input에 입력한 숫자 값을 계속 더해서 출력하는 컴포넌트를 만들었습니다.

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

const getTotal = numbers => {
    let total = 0;

    console.log('getTotal() 호출');

    numbers.forEach(value => {
        total += value;
    });

    return total;
};

const AddInputNum = () => {
    const [numbers, setNumbers] = useState([]);
    const [input, setInput] = useState('');

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

    const onInsert = e => {
        const nextNumber = numbers.concat(parseInt(input));

        setNumbers(nextNumber);
        setInput('');
    };

    return (
        <Fragment>
            <input value={input} onChange={onChange}/>
            <button onClick={onInsert}>입력</button>
            <div>
                <span>총합: </span>{getTotal(numbers)}
            </div>
        </Fragment>
    );
};

export default AddInputNum;

결과는 제대로 나오지만 한가지 문제점이 발생합니다. console을 확인해보니 getTotal이 입력 버튼을 눌러서 실제로 더해야할 때만 호출되는 것이 아닌 input 폼에 변경이 있을 때마다 호출이 됩니다. 이렇게 되면 쓸데없는 호출이 굉장히 많아져서 성능 저하를 보일 수 있습니다. 당장 위의 예제도 3번밖에 안더했지만, getTotal은 11번이나 호출이 되었습니다.

 

 

2. useMemo 사용

이 문제가 많은 코드를 useMemo Hook를 통해 최적화 해보겠습니다. 우선 useMemo의 사용법은 다음과 같습니다.

useMemo(함수, 의존성 값);

useMemo함수에는 최적화 시킬 대상인 함수를 전달합니다. 그리고 두번째 인자로는 의존성 값을 받게 되는데, 의존성 값은 함수에서 실행되어질 수 있는 값들을 넣는 값을 말합니다. 지난번에 다룬 useEffect의 두 번째 인자도 의존성 값을 사용하는 의존성 배열이었습니다.

이제 useMemo의 사용법을 배웠으니 위의 코드를 고쳐보겠습니다. 코드가 길고 하이라이팅이 안되서 변경 부분 표시가 난해한데, 수정된 부분은 return 구문 앞에 useMemo구문을 추가했고 return의 JSX 내부에 총합 표시하는 부분의 자바스크립트 표현식을 수정했습니다.

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

const getTotal = numbers => {
    let total = 0;

    console.log('getTotal() 호출');

    numbers.forEach(value => {
        total += value;
    });

    return total;
};

const AddInputNum = () => {
    const [numbers, setNumbers] = useState([]);
    const [input, setInput] = useState('');

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

    const onInsert = e => {
        const nextNumber = numbers.concat(parseInt(input));

        setNumbers(nextNumber);
        setInput('');
    };

    const total = useMemo(() => getTotal(numbers), [numbers]);

    return (
        <Fragment>
            <input value={input} onChange={onChange}/>
            <button onClick={onInsert}>입력</button>
            <div>
                <span>총합: </span>{total}
            </div>
        </Fragment>
    );
};

export default AddInputNum;

이제 우리가 입력 버튼을 눌러 값을 전달할 경우에만 getTotal 함수가 호출된다는 것을 볼 수 있습니다.


참조

https://react.vlpt.us/basic/17-useMemo.html

 

17. useMemo 를 사용하여 연산한 값 재사용하기 · GitBook

17. useMemo 를 사용하여 연산한 값 재사용하기 이번에는 성능 최적화를 위하여 연산된 값을 useMemo라는 Hook 을 사용하여 재사용하는 방법을 알아보도록 하겠습니다. App 컴포넌트에서 다음과 같이 co

react.vlpt.us

https://ko.reactjs.org/docs/hooks-reference.html#usecallback

 

Hooks API Reference – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

728x90