[React] 컴포넌트 최적화(1) : useMemo

2024. 12. 3. 22:17·React

useMemo


값의 연산 결과를 Memoization하여, 불필요한 재계산을 방지하는 훅

 

* Memoization?

동일한 값을 리턴하는 함수를 반복적 호출할 경우

맨 처음 계산 할때 메모리에 저장해뒀다 필요할때마다 다시 계산이 아니라 메모리에서 꺼내 재사용하는것

 

왜 필요한가?


함수형 컴포넌트도 함수.

함수형 컴포넌트 렌더링 ->  컴포넌트 함수 호출 -> 내부 모든 변수 초기화

만약 state 와 props의 변화로 인해 수많은 렌더링을 거친다면 렌더링 될때마다 변수가 초기화가 됨

function calculate(){
    return 1
}

function MyComponent(){
    const value = calculate();
    return <div>{value}</div>
}

 

렌더링 마다 value 변수 초기화, calculate() 함수 호출 -> 비효율적

 

! useMemo 값 재활용하기 위해서 따로 메모리를 소비해서 저장하기 때문에 남용시 성능에 좋지않아 필요시 적절히 사용!

 

*React.memo vs. useMemo

React.memo 컴포넌트 불필요한 컴포넌트 재렌더링 방지 props 변경x -> 렌더링x 같은 props로 렌더링 결과가 같을 때 사용
useMemo 값 (변수) 연산 비용이 큰 값을 메모이제이션 의존성 배열 값 변경x ->  이전 값 재사용 비싼 연산 결과를 저장할 때 사용

 

 

구조


const value = useMemo(() => {
	return calculate();
}, [item])
  • 첫 번째 인자: 메모이제이션할 값을 반환하는 함수
  • 두 번째 인자: 의존성 배열로, 배열 안의 값이 변경될 때만 첫 번째 인자 호출
    • 빈 배열일 경우: 컴포넌트가 마운트시만 값을 계산하고, 이후에는 메모이제이션된 값만을 재사용

 

사용


const calculate = (num) => {
  console.log("무거운 작업");
  for (let i = 0; i < 99999999; i++) {}//딜레이
  return num + 10000;
}

function App() {
  const [num, Setnum] = useState(1);
  const result = calculate(num);

  const [render, SetRender] = useState();
  
  return (
    <div>
      <input type="number" value={num} onChange={(e)=>Setnum(parseInt(e.target.value))} />
      <span> + 10000 = {result}</span>

      <div>
        <button onClick={()=> SetRender(!render)}>렌더</button>
      </div>
    </div>
  );
}

이경우 App 컴포넌트가 렌더링때마다 result 변수 초기화, calculate함수가 호출됨

그러면 num 변경에만 calculate함수 불리게 해보자

//const result = calculate(num);
  const result = useMemo(()=>{
    return calculate(num);
  }, [num])

 

좀더 알아보자


function App() {
  const [render, setRender] = useState();
  
  const [prove, setProve] = useState(false);
  const result = prove? "진실" : "거짓";

  useEffect(() => {
    console.log("useEffect 호출");
  }, [result]);

  return (
    <div>
      <div>
        <button onClick={()=>setRender(!render)}>렌더</button>
      </div>
      <hr />

      <p>진혹거 : {result}</p>
      <button onClick={() => setProve(!prove)}>변경!</button>
      <p></p>
    </div>
  );
}

이 경우에는 result 변수 변경시에만 콘실이 찍힘

 

그렇다면 객체일 경우에는?

function App() {
  const [render, setRender] = useState();
  
  const [prove, setProve] = useState(false);

  //const result = prove? "진실" : "거짓";
  const result = {
    first: prove? "진실" : "거짓",
  };

  useEffect(() => {
    console.log("useEffect 호출");
  }, [result]);

  return (
    <div>
      <div>
        <button onClick={()=>setRender(!render)}>렌더</button>
      </div>
      <hr />

      <p>진혹거 : {result.first}</p>
      <button onClick={() => setProve(!prove)}>변경!</button>
      <p></p>
    </div>
  );
}

result 변수 변경하지 않았음에도 콘솔이 찍힘

왜?

원시가 아닌 객체타입은 주소값을 저장하는데 똑같아 보이는 형태여도 주소값이 다르면 다른 객체임

//원시타입
const one = 1;
const one2 = 1;
console.log(one === one2) //true

//객체타입
const one = { 1:1 };
const one2 = { 1:1 };
console.log(one === one2) //false

App함수가 호출되면서 형태가 똑같이 생겼지만 주소값이 다른 객체를 할당받았기때문!

 

주소가 변경되지않도록 해보자

//const result = prove? "진실" : "거짓";
// const result = {
//   first: prove? "진실" : "거짓",
// };
const result = useMemo(()=>{
	return {first: prove? "진실" : "거짓"}
},[prove])

'React' 카테고리의 다른 글

[React] TanStack Query(React Query)  (0) 2024.12.10
[React] React with Typescript  (0) 2024.12.05
[React] useRef  (0) 2024.12.02
[React] Styled-Components에서 애니메이션, 테마  (0) 2024.11.28
[React] Styled Components  (0) 2024.09.24
'React' 카테고리의 다른 글
  • [React] TanStack Query(React Query)
  • [React] React with Typescript
  • [React] useRef
  • [React] Styled-Components에서 애니메이션, 테마
Naah
Naah
  • Naah
    blueprint
    Naah
  • 전체
    오늘
    어제
    • 분류 전체보기 (106)
      • Java (28)
      • Kotlin (0)
      • TypeScript (7)
      • React (22)
      • Next.js (1)
      • Spring (22)
      • JPA (12)
      • Spring Data JPA (6)
      • Querydsl (1)
      • Error (7)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
    • manage
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Naah
[React] 컴포넌트 최적화(1) : useMemo
상단으로

티스토리툴바