html,css,js 공부/React

React 메모이제이션

ari0930 2024. 3. 20. 18:37

React 메모이제이션

App이라는  컴포넌트가 있으면 아래 child1,2,3,4, 의 하위 컴포넌트가 존재 한다 

App컴포넌트가 랜더링 되면 아래의 하위 컴포넌트도 모두다 랜더링 되게에 메모리를 많이 소비하게 된다 이러한 문제점을 해결하기 위해 memo,useCallback,useMemo를 사용하여 상위 컴포넌트가 랜더링 되어도

랜더링 하게 하는걸 막을수 있다 

 

폴더 구조

App코드

import { Child1 } from './components/Child1.jsx';
import { Child4 } from './components/Child4.jsx';

export const App = memo(() => {
  console.log("APP 랜더링")

  const [num, setNum] = useState(0);

  const onClickButton = () => {
    setNum(num + 1);
  };


  return (
    <>
      <button onClick={onClickButton}>버튼</button>
      <p>{num}</p>
      <Child1  />
      <Child4 />
    </>
  );
});

각 부분 마다 현재 랜더링 하고있는지 에대한 콘솔 값을 기입하였다,

그렇기에 app가 랜더링 되면 그 아래에 포함된 모든 컴포넌트들은 랜더링 되어야한다 

app에 있는 버튼을 누를때 마다 랜더링 되게이 그 아래 있는 모든 컴포넌트들도 랜더링 된다 

이걸 막기 위해 memo를 이용한다 

 

child1에만 memon를 적용해보면 

export const Child1 = memo((props) => {} ))

app 의 버튼을 클릭하면 

app 자기 자신과 child4만 랜더링 된다 

 

 

 함수에 대해서 메모이제이션 useCallback

import { Child1 } from './components/Child1.jsx';
import { Child4 } from './components/Child4.jsx';

export const App = memo(() => {
  console.log("APP 랜더링")

  const [num, setNum] = useState(0);

  const onClickButton = () => {
    setNum(num + 1);
  };

  const onClickReset = () => {
    setNum(0);
  };

  return (
    <>
      <button onClick={onClickButton}>버튼</button>
      <p>{num}</p>
      <Child1 onClickReset={onClickReset} />
      <Child4 />
    </>
  );
});

child1에서 app 의 값을 초기화 하기위해 onclickReset라는 함수를 만들었다 

 

child1의 코드는

import "./Child.css";
import { useState,memo,useMemo  } from 'react';
import {Child2} from './Child2.jsx';
import {Child3} from './Child3.jsx';

const style2 ={
    backgroundColor : "Lightblue",
}
export const Child1 = memo((props) => {
    console.log("Child1 랜더링")

    //props로 부터 받음 함수 전개 
    const {onClickReset} = props;
  
    return (<>
    <div className="child1" style={style2}> 
            <button onClick={onClickReset}>리셋</button>
    
        
            <p>child1 <button >child2버튼</button> 


        <Child2 />
        <Child3}/>
        
    </div>

    </>)
  })

이렇게 app의 함수를 받아오게 된다면 app버튼 클릭시 

memo를 사용하였더라도 child1도 랜더링 된다 이때 이걸 막기 위해 usecallback 을 사용한다 

 

app 부분에서

  const onClickReset =useCallback ( () => {
    setNum(0);
  },[]);

이렇게 수정해주면 child1이 app로 부터 함수를 받아도 랜더링이 되지 않는다 

 

변수에 대해서 메모이제이션 useMemo

이번에는 child1에서 시작할거면 child2,3는 memo 되어있는  상태이다 

child1의 코드는 

export const Child1 = memo((props) => {
    console.log("Child1 랜더링")
    const [num2,setNum]=useState(0);
    const [num3,setNum3]=useState(0);

    //props로 부터 받음 함수 전개 
    const {onClickReset} = props;

    
    const onClickButton = ()=>{
      setNum(num2+1)
    }   
    const memoizedNum2 = useMemo(() => num2, []);

    const onClickButton2 = ()=>{
        setNum3(num3+1)
      } 

  
    return (<>
    <div className="child1" style={style2}> 
            <button onClick={onClickReset}>리셋</button>
    
        
            <p>child1 <button onClick={onClickButton}>child3버튼</button> 
            <span>{num2}</span></p>
            <p><button onClick={onClickButton2}>child2버튼</button>
            <span>{num3}</span> </p>

        <Child2 year={num3}/>
        <Child3 year={memoizedNum2}/>
        
    </div>

    </>)
  })

num3라는 변수는 child2에 그냥 상속하고

num2는 memoizedNum2라는 함수에 의해 메모라이제이션을 거쳐서 child3로 넘어간다 

 

이때 child3버튼을 누르면 child1만 랜더링 된다

child2버튼을 누르면 child1과 child2 모두다 랜더링이 된다.

 

 

이걸 이용하면 불필요한 랜더링을 줄일수 있으면 자기가 원하는 함수 변수에 대해서만 랜더링을 진행할수 있다 

반응형