ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] useMemo() μ‚¬μš©λ²• _(λ¦¬μ•‘νŠΈ Hooks)
    JavaScript/React 2023. 6. 24. 23:59
    728x90
    λ°˜μ‘ν˜•

     

    🧐 React Hooks의 useMemoλ₯Ό μ•Œμ•„λ³΄μž

     

    μ•ˆλ…•ν•˜μ„Έμš©. μ˜€λŠ˜μ€ λ¦¬μ•‘νŠΈ hooks μ€‘μ—μ„œλ„ 자주 μ‚¬μš©λ˜λŠ” 편인 useMemo에 λŒ€ν•΄μ„œ μ•Œμ•„λ³΄λ €κ³  ν•©λ‹ˆλ‹€.

     

    useMemo() 훅은 Reactμ—μ„œ μ œκ³΅ν•˜λŠ” ν•˜λ‚˜μ˜ μ΅œμ ν™” 기술둜, 계산 λΉ„μš©μ΄ 많이 λ“œλŠ” ν•¨μˆ˜ ν˜ΈμΆœμ„ λ©”λͺ¨μ΄μ œμ΄μ…˜ν•˜λŠ” 데 μ‚¬μš©λ©λ‹ˆλ‹€. 이λ₯Ό 톡해 μ»΄ν¬λ„ŒνŠΈμ˜ λ¦¬λ Œλ”λ§μ„ 쀄이고 μ„±λŠ₯을 ν–₯μƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€λ³Έ ν¬μŠ€νŒ…μ€ react 곡식 λ¬Έμ„œλ₯Ό μ°Έκ³ ν•˜μ—¬ μž‘μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

     

    μ˜€λŠ˜μ€ useMemo Hook에 λŒ€ν•΄ μ•Œμ•„λ³΄κ³  μ‚¬μš©ν•΄ 볼게용 🧐

     

     


     

    🍊 useMemoλŠ” 뭐고, 어디에 μ‚¬μš©λ κΉŒ?

    useMemo()λŠ” React Hook 쀑 ν•˜λ‚˜λ‘œ, ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈμ—μ„œ κ³„μ‚°λŸ‰μ΄ λ§Žμ€ 연산을 μ΅œμ ν™”ν•˜λŠ” μš©λ„λ‘œ μ‚¬μš©λ©λ‹ˆλ‹€. useMemo()λŠ” λ©”λͺ¨λ¦¬μ— 값을 μ €μž₯해두고, ν•΄λ‹Ή 값이 ν•„μš”ν•œ 경우 이전에 κ³„μ‚°ν•œ 값을 가져와 μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— λΆˆν•„μš”ν•œ 계산을 쀄여μ€λ‹ˆλ‹€.

     

    πŸ“ useMemoκ°€ μ‚¬μš©λ˜λŠ” 경우

    useMemo()λŠ” λ‹€μ–‘ν•œ μƒν™©μ—μ„œ μœ μš©ν•˜κ²Œ μ‚¬μš©λ  수 μžˆλŠ”λ°, 주둜 λ‹€μŒκ³Ό 같은 상황에 μ‚¬μš©λ©λ‹ˆλ‹€.

    • 계산이 λ³΅μž‘ν•œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 경우
    • λΆˆν•„μš”ν•œ 계산을 ν”Όν•˜κ³  μ„±λŠ₯을 ν–₯μƒμ‹œν‚€λŠ” 경우
    • Propsλ‚˜ μƒνƒœκ°€ λ³€κ²½λ˜μ—ˆμ„ λ•Œλ§Œ 연산을 μˆ˜ν–‰ν•˜λŠ” 경우

     


     

    🍊 useMemo μ‚¬μš©λ²•

    useMemo()λ₯Ό μ‚¬μš©ν•˜λ €λ©΄ λ‹€μŒκ³Ό 같이 Reactμ—μ„œ μ œκ³΅ν•˜λŠ” 훅을 import ν•΄μ•Ό ν•©λ‹ˆλ‹€.

    import { useMemo } from 'react';

     

    useMemo()λŠ” 첫 번째 인자둜 콜백 ν•¨μˆ˜λ₯Ό λ°›κ³ , 두 번째 인자둜 μ˜μ‘΄μ„± λ°°μ—΄(dependency array)을 λ°›μŠ΅λ‹ˆλ‹€.

    const cachedValue = useMemo(calculateValue, dependencies)

     

    πŸ“ 첫 번째 인자: calculateValue (콜백 ν•¨μˆ˜)

    • Reactμ—μ„œλŠ” μΊμ‹œν•˜κ³ μž ν•˜λŠ” 값을 κ³„μ‚°ν•˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€.
    • 이 ν•¨μˆ˜λŠ” 인자λ₯Ό 받지 μ•Šκ³  μ–΄λ–€ νƒ€μž…μ˜ 값이라도 λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • 초기 λ Œλ”λ§ μ‹œ ReactλŠ” 이 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.
    • κ·Έ ν›„μ—λŠ” μ˜μ‘΄μ„±μ΄ 이전 λ Œλ”λ§ μ΄ν›„λ‘œ λ³€κ²½λ˜μ§€ μ•Šμ•˜λ‹€λ©΄ ReactλŠ” λ™μΌν•œ 값을 λ‹€μ‹œ λ°˜ν™˜ν•©λ‹ˆλ‹€.

     

    πŸ“ 두 번째 인자: dependencies (μ˜μ‘΄μ„± λ°°μ—΄)

    • μ˜μ‘΄μ„± λ°°μ—΄μ—λŠ” 콜백 ν•¨μˆ˜κ°€ μ˜μ‘΄ν•˜λŠ” 값듀을 λ„£μ–΄μ€λ‹ˆλ‹€.
    • μ˜μ‘΄μ„± λ°°μ—΄μ˜ 값이 λ³€κ²½λ˜λ©΄, 콜백 ν•¨μˆ˜κ°€ 호좜되고 κ·Έ 결과값을 λ°˜ν™˜ν•©λ‹ˆλ‹€. 그렇지 μ•ŠμœΌλ©΄ 이전에 κ³„μ‚°ν•œ 값을 μž¬μ‚¬μš©ν•©λ‹ˆλ‹€.

     

     


     

    🍊 이제 useMemoλ₯Ό 직접 μ‚¬μš©ν•΄λ³΄μž

    기본적으둜 λ¦¬μ•‘νŠΈλŠ” μ»΄ν¬λ„ŒνŠΈκ°€ λ¦¬λ Œλ”λ§λ  λ•Œλ§ˆλ‹€ κ·Έ μ»΄ν¬λ„ŒνŠΈ 전체λ₯Ό μž¬μ‹€ν–‰ν•©λ‹ˆλ‹€.

    예λ₯Ό λ“€μ–΄ μ•„λž˜ μ½”λ“œμ—μ„œ todoList의 μƒνƒœκ°€ λ³€ν•˜κ±°λ‚˜ λΆ€λͺ¨λ‘œλΆ€ν„° propλ₯Ό μƒˆλ‘œ λ°›μ•„μ˜¬ λ•Œλ§ˆλ‹€ μ•„λž˜ filterTodos ν•¨μˆ˜λŠ” μž¬μ‹€ν–‰λ©λ‹ˆλ‹€.

    function TodoList({ todos, tab, theme }) {
      const visibleTodos = filterTodos(todos, tab);
      // ...
    }

     

     

    πŸ“ νˆ¬λ‘λ¦¬μŠ€νŠΈ 닀크/라이트 λͺ¨λ“œ

    μ•„λž˜λŠ” 닀크λͺ¨λ“œ, 라이트λͺ¨λ“œ μ „ν™˜μ΄ κ°€λŠ₯ν•œ νˆ¬λ‘λ¦¬μŠ€νŠΈλ₯Ό κ΅¬ν˜„ν•œ μ½”λ“œμž…λ‹ˆλ‹€. filterTodos ν•¨μˆ˜λŠ” μΈμœ„μ μœΌλ‘œ 느리게 μž‘λ™λ˜λ„λ‘ μ§œμ—¬μ Έ μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ useMemoλ₯Ό μ‚¬μš©ν•˜μ—¬ 느린 λ™μž‘ μ›λ¦¬μž„μ—λ„ μ½”λ“œλŠ” λΉ λ₯΄κ²Œ μˆ˜ν–‰λ©λ‹ˆλ‹€.

     

     

     

    πŸ“ TodoList.js

    import { useMemo } from 'react';
    import { filterTodos } from './utils.js'
    
    export default function TodoList({ todos, theme, tab }) {
      const visibleTodos = useMemo(  // useMemo() μ‚¬μš©
        () => filterTodos(todos, tab),
        [todos, tab]
      );
      return (
        <div className={theme}>
          <p><b>Note: <code>filterTodos</code> is artificially slowed down!</b></p>
          <ul>
            {visibleTodos.map(todo => (
              <li key={todo.id}>
                {todo.completed ?
                  <s>{todo.text}</s> :
                  todo.text
                }
              </li>
            ))}
          </ul>
        </div>
      );
    }

     

    πŸ“ App.js

    import { useState } from 'react';
    import { createTodos } from './utils.js';
    import TodoList from './TodoList.js';
    
    const todos = createTodos();
    
    export default function App() {
      const [tab, setTab] = useState('all');
      const [isDark, setIsDark] = useState(false);
      return (
        <>
          <button onClick={() => setTab('all')}>
            All
          </button>
          <button onClick={() => setTab('active')}>
            Active
          </button>
          <button onClick={() => setTab('completed')}>
            Completed
          </button>
          <br />
          <label>
            <input
              type="checkbox"
              checked={isDark}
              onChange={e => setIsDark(e.target.checked)}
            />
            Dark mode
          </label>
          <hr />
          <TodoList
            todos={todos}
            tab={tab}
            theme={isDark ? 'dark' : 'light'}
          />
        </>
      );
    }

     

    πŸ“ utils.js

    export function createTodos() {
      const todos = [];
      for (let i = 0; i < 50; i++) {
        todos.push({
          id: i,
          text: "Todo " + (i + 1),
          completed: Math.random() > 0.5
        });
      }
      return todos;
    }
    
    export function filterTodos(todos, tab) {
      console.log('[ARTIFICIALLY SLOW] Filtering ' + todos.length + ' todos for "' + tab + '" tab.');
      let startTime = performance.now();
      while (performance.now() - startTime < 500) {
        // Do nothing for 500 ms to emulate extremely slow code
      }
    
      return todos.filter(todo => {
        if (tab === 'all') {
          return true;
        } else if (tab === 'active') {
          return !todo.completed;
        } else if (tab === 'completed') {
          return todo.completed;
        }
      });
    }

     

     


    πŸ–πŸ» 잠깐, 주의 사항

    • useMemoλŠ” Hookμ΄λ―€λ‘œ μ»΄ν¬λ„ŒνŠΈμ˜ μ΅œμƒμœ„ λ ˆλ²¨μ΄λ‚˜ 직접 μž‘μ„±ν•œ Hook λ‚΄μ—μ„œλ§Œ ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • λ°˜λ³΅λ¬Έμ΄λ‚˜ 쑰건문 λ‚΄μ—μ„œ ν˜ΈμΆœν•  μˆ˜λŠ” μ—†μŠ΅λ‹ˆλ‹€.
    • 엄격 λͺ¨λ“œ(Strict Mode)μ—μ„œλŠ” μ˜λ„μΉ˜ μ•Šμ€ λΆˆμˆœλ¬Ό(impurity)을 μ°Ύμ•„μ£ΌκΈ° μœ„ν•΄ κ³„μ‚° ν•¨μˆ˜λ₯Ό λ‘ λ²ˆ ν˜ΈμΆœν•©λ‹ˆλ‹€.

     

     


    🍊 μš”μ•½

    이번 ν¬μŠ€νŒ…μ—μ„œλŠ” React의 useMemo() 훅에 λŒ€ν•΄ λ‹€λ£¨μ—ˆμŠ΅λ‹ˆλ‹€. useMemo()λŠ” 계산 λΉ„μš©μ΄ 많이 λ“œλŠ” ν•¨μˆ˜ ν˜ΈμΆœμ„ λ©”λͺ¨μ΄μ œμ΄μ…˜ν•˜μ—¬ μ„±λŠ₯을 ν–₯μƒμ‹œν‚€λŠ” 역할을 ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 λΆˆν•„μš”ν•œ λ¦¬λ Œλ”λ§μ„ λ°©μ§€ν•˜κ³  μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ„±λŠ₯을 μ΅œμ ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸΌμ—λ„ useMemo()λ₯Ό λ‚¨μš©ν•˜λ©΄ μ½”λ“œλ₯Ό λ³΅μž‘ν•˜κ²Œ λ§Œλ“€ 수 μžˆμœΌλ―€λ‘œ, 항상 μ„±λŠ₯ λ¬Έμ œκ°€ μ‹€μ œλ‘œ λ°œμƒν•˜λŠ” κ²½μš°μ—λ§Œ μ‚¬μš©ν•˜λŠ” 것이 μ’‹μ•„μš”!

     

    λ‹€μŒμ—λŠ” 또 λ‹€λ₯Έ λ¦¬μ•‘νŠΈ hook을 주제둜 곡뢀해 λ³΄κ² μŠ΅λ‹ˆλ‹Ή πŸ‘€

     

     

     

    μ°Έκ³ λ¬Έμ„œ

    https://react.dev/reference/react/useMemo

     

    useMemo – React

    The library for web and native user interfaces

    react.dev

    https://react.dev/learn

     

    Quick Start – React

    The library for web and native user interfaces

    react.dev

     

    LIST
Designed by Tistory.