dukDukz

21.07.12 React useMemo / useCallback 본문

웹 개발/React

21.07.12 React useMemo / useCallback

헤일리_HJ 2021. 7. 12. 16:47

useMemo 와 useCallback을 사용하는 이유는?

/0712/vifo.html
DP : 다이나믹 프로그래밍 - 어려운 알고리즘 중 하나라고 볼 수 있다.
코테 마지막 문제에서 자주 출제되고 
그래프 + DP 로 출제가 된다.

그러면 DP가 뭐냐?
- 규칙을 찾는거라고 보면 된다.


* 피보나치 수열 문제 - 메모이제이션을 쓰는 이유 (최적화를 위해)

더보기
function fibo(n){
	if(n == 1) return 1
	if(n == 2) return 1
    
	return fibo(n-2) + fibo(n-1)
}

이렇게 쓰면 연산을 너무 많이 하게 된다.

개복잡함 - 그래서 이걸 메모제이션 으로 바꾸자

let memo = {}

function fibo(n) {
    if (n in memo) {
        let result = memo[n]
    }else{
        if(n == 1 || n == 2){
            result = 1
        } else {
            result = fibo(n-2) + fibo(n-1)
        }
        memo[n] = result
    }
    return result
}

memo를 쓴 코드

메모제이션 
- 내가 한번 구했던(연산했던) 내용을 어딘가에 넣어놓는것 - 나중에 또 쓴다
- 다시 계산하지 않는다

 

 


Webpack5

/component/memo/memo.jsx

 

원래 ver

import React, { useState } from 'react'

const Memo = () => {
    const [username, setUsername] = useState('')   //React 가 빠진 이유는 위에 import 때문
    const [list, setList] = useState([])

    
    const change = (e) => {
        let { value } = { ...e.target }
        setUsername(value)
    }
    
    const submit = (e) => {
        e.preventDefault()
        const newList = [...list]
        newList.push(username)
        setList(newList)
        setUsername('')
    }
    
    const renderList = () => {
        return(
            list.map((v,k)=>{
                return <li key={k}>{v}</li>
            })
        )
    }

    const userCount = useMemo (()=>{
        return list.length
    },[list.length])

    return (
        <>
            <h2>회원리스트 ({userCount})</h2>
            <form onSubmit={submit}>
                <input
                    type="text"
                    name="username"
                    value={username}
                    onChange={change}
                />
                <button type="submit">
                    추가
                </button>
            </form>
            <ol>
                {
                    renderList()
                }
            </ol>
        </>
    )
}

export default Memo

함수형 컴포넌트이므로 사용되지 않는 상황에서도 계속 함수가 재생성된다.

 

 

useMemo 와 useCallback을 사용한 ver

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

const Memo = () => {

    const [username, setUsername] = useState('')
    const [list, setList] = useState([])

    const change = useCallback((e) => {
        let { value } = { ...e.target }
        setUsername(value)
    }, [])

    const submit = useCallback((e) => {
        e.preventDefault()
        const newList = [...list]
        newList.push(username)
        setList(newList)
        setUsername('')
    }, [list, username])

    const renderList = useCallback((v, k) => {
        let newArr = list.map((v, k) => {
            return (
                <li key={k}>{v}</li>
            )
        })
        return newArr
    }, [list])


    const userCount = useMemo(() => {
        return list.length
    }, [list.length])

    return (
        <>
            {console.log('render')}
            <h2>회원리스트 ({userCount})</h2>
            <form onSubmit={submit}>
                <input
                    type="text"
                    name="username"
                    value={username}
                    onChange={change}
                />
                <button type="submit">
                    추가
                </button>
            </form>
            <ol>
                {
                    renderList()
                }
            </ol>
        </>
    )
}

export default Memo

useMemo 
결과값을 어딘가에 저장해서 불러오는 형태 - 그렇다는 것은 메모리를 사용한다는 뜻이다

그 의미는 최적화하기 위해 남발하면 메모리 낭비를 할 수 있다는 뜻이다. 남발하지 말자!

 

어떻게 쓰는지 보자

const userCount = useMemo (()=>{
        return list.length
},[list.length])

인자값이 두개이다. 하나는 함수 하나는 배열

[list.length] 상태가 바뀔때만 함수를 재 생성합니다.

즉 배열안에 있는 녀석이 바뀔 때만 해당 함수를 재 생성 한다는 의미이다.

빈 배열일 경우엔 이 컴포넌트가 최초에 실행될때만 실행하겠다는 의미

 

사용할때는 <h2>회원리스트 ({userCount})</h2>

이렇게 사용함
뒤에 괄호 붙여서 함수처럼 실행하면 오류난다. - 함수가 아니라는 오류남 - 함수가 아니라 변수이기 때문이다.

 

useMemo and useCallback
똑같은 거임 근데 뭐가 다를까?
useMemo : 변수를 메모리이에이션 사용할때
useCallback : 함수를 메모리이에이션 사용할때

 

함수형 컴포넌트는 렌더 될때마다 안에 함수를 재생성한다.
그래서 최초에 한번 실행됐을때 그거를 생성해놓고 갖다 쓰는 방식을 하려고 useCallback을 쓴다