본문 바로가기

Front-End/React

메모이제이션

리액트는 상위 컴포넌트의 sate가 업데이트가 되면 그 하위 컴포넌트까지 제렌더링 된다.

함수가 다시 호출되고, 값을 다시 부른다는 뜻이다.

이렇게 되면 에너지 낭비이기 때문에 리액트에선 3가지 훅을 제공한다.

이 3가지 훅은 값이나 함수를 메모리에 저장해 자원을 아낄 수 있다.

 

useCallback(함수),useMemo(값),useReducer

 

각각 하나씩 살펴보겠다.

 

useCallback

 

두가지 인자를 받는다.

1.메모이제이션

2.의존성 배열

의존성 배열의 값이 변경되지 않는 한 , 동일한 함수 인스턴스를 반환한다.

 

 

사용방법

const 변수선언 = useCallback(()=>{},[])

const increment = useCallback(()->{

	//이 함수 내부에서 발생하는 일이
	//굉장히 비용이 많이 발생하는 코드가 정의되어 있으면 쓴다.
    setCount(()=>prev + 1})
},[])

 

useCallback으로 메모이제이션 할 땐 ,

처음 세팅 그대로 저장한다.

그래서 계속해서 변하는 값을 참조 하고 싶으면 아래와 같이 쓰면 된다.

setCount(값) - 이전 값을 참조하지 않을 때.
setCount(()=>{}) - 이전 값을 참조할 때
뒤에 있는 [] 이놈은 의존성 배열이다.
이놈이 빈 배열이면 한번만 , [count]이렇게 넣으면
count값이 변할 때마다 다시 메모이제이션 된다.

useMemo

 

값의 메모이제이션을 위해 사용된다.

의존성배열에 있는 값이  안변하면 재계산 안함.(불필요한 계산 X , 성능 최적화 목표)

//기본 사용법
const 변수선언 = useMemo(()=>{},[의존성배열])


const memoizedValue = useMemo(() => {
  // 계산할 값
  return someExpensiveCalculation(a, b);
}, [a, b]); // 의존성 배열

 

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

function ExpensiveCalculationComponent() {
  const [count, setCount] = useState(0);

  const expensiveCalculation = (num) => {
    console.log('Calculating...');
    return num * 2;
  };

  const memoizedValue = useMemo(() => expensiveCalculation(count), [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <p>Calculated Value: {memoizedValue}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default ExpensiveCalculationComponent;

 

 


useReducer

리액트에서 상태 관리를 위한 훅이다.

컴포넌트 로컬 상태를 관리할 때 주로 쓰는데, 폼데이터 같은 복잡한 데이터를 관리하는 데 유용하다.

const [state, dispatch] = useReducer(reducer, initialState);

 

 

import React, { useReducer } from 'react';

const initialState = {
  name: '',
  email: '',
  password: ''
};

function reducer(state, action) {
  switch (action.type) {
    case 'setFieldValue':
      return {
        ...state,
        [action.field]: action.value
      };
    case 'reset':
      return initialState;
    default:
      throw new Error('Unknown action type');
  }
}

function RegistrationForm() {
  const [state, dispatch] = useReducer(reducer, initialState);

  const handleChange = (e) => {
    dispatch({ type: 'setFieldValue', field: e.target.name, value: e.target.value });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(state);
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>
          Name:
          <input
            type="text"
            name="name"
            value={state.name}
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <label>
          Email:
          <input
            type="email"
            name="email"
            value={state.email}
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <label>
          Password:
          <input
            type="password"
            name="password"
            value={state.password}
            onChange={handleChange}
          />
        </label>
      </div>
      <button type="submit">Register</button>
      <button type="button" onClick={() => dispatch({ type: 'reset' })}>Reset</button>
    </form>
  );
}

export default RegistrationForm;

 

장점

1.복잡한 에러 처리 : 여러 상태와 액션을 다루는 로직을 깔끔하게 관리할 수 있다.

2.상태 로직 분리 : 상태 업데이트 로직을 컴포넌트에서 분리해  코드의 가독성과 유지보수성을 높힌다.

3.불변성 유지 : 새로운 상태를 변환하여 상태 불변성을 유지한다.

4.확장성 : 상태와 액션을 추가하기 쉽다.

 

다만,복잡성이 증가할 수 있고, 전역상태관리가 필요하면 , redux같은 걸 쓰는 게 좋다.

 

 

 

 

'Front-End > React' 카테고리의 다른 글

서버 띄우는법 , http통신  (0) 2024.07.26
Context API  (0) 2024.07.26
리액트 불변성  (0) 2024.07.25
코드분석(To-do-list)  (3) 2024.07.24
조건부 렌더링  (0) 2024.07.24