Memoization
νμ΅ ν€μλ
memoization
React.memo
useCallback
useMemo
μ»΄ν¨ν° νλ‘κ·Έλ¨μ΄ λμΌν κ³μ°μ λ°λ³΅ν΄μΌ ν λ, μ΄μ μ κ³μ°κ°μ λ©λͺ¨λ¦¬μ μ μ₯ν¨μΌλ‘μ¨ λμΌν κ³μ°μ λ°λ³΅μνμ μ κ±°νμ¬ νλ‘κ·Έλ¨ μ€ν μλλ₯Ό λΉ λ₯΄κ² νλ κΈ°μ
React.memo
μ»΄ν¬λνΈ
λ₯Ό λ©λͺ¨μ΄μ μ΄μ ν λ μ¬μ©νλ€.μ»΄ν¬λνΈμ propκ° λ³κ²½λμ§ μλ κ²½μ° λ¦¬λ λλ§μ νμ§ μλλ€.
const MemoizedComponent = React.memo(SomeComponent, arePropsEqual?)
π©π»βπ» μμ
import { useState } from 'react';
const Count = ({ count }: { count: number }) => {
console.log('Count Rendered');
return (
<div>
<h1>Count Component</h1>
<h2>Count : {count}</h2>
</div>
);
};
export default function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
return (
<div>
<Count count={count} />
<button type="button" onClick={() => setCount(count + 1)}>
count μ¦κ° λ²νΌ
</button>
<input
type="text"
placeholder="input μ
λ ₯νλ©΄ μ΄λ»κ² λ κΉ? "
value={text}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setText(e.target.value)
}
/>
</div>
);
}
ν΄λΉ μ½λλ input μμμ μ
λ ₯νκ² λλ©΄ Count
μ»΄ν¬λνΈκ° λΆνμνκ² λ¦¬λ λλ§μ΄ μΌμ΄λλ€. Count
μ»΄ν¬λνΈμ 리λ λλ§μ΄ μΌμ΄λλ μ΄μ λ μμ μ»΄ν¬λνΈ App
μ textμ μνκ°μ΄ μ
λ°μ΄νΈ λλ©΄μ 리λ λλ§μ΄ μΌμ΄λκ² λλ κ²μ΄λ€.
import { useState, memo } from 'react';
const Count = ({ count }: { count: number }) => {
console.log('Count Rendered');
return (
<div>
<h1>Count Component</h1>
<h2>Count : {count}</h2>
</div>
);
};
const MemoCount = memo(Count); // ππ» λ©λͺ¨μ΄μ μ΄μ
ν μ»΄ν¬λνΈ
export default function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
return (
<div>
<MemoCount count={count} />
<button type="button" onClick={() => setCount(count + 1)}>
count μ¦κ° λ²νΌ
</button>
<input
type="text"
placeholder="input μ
λ ₯νλ©΄ μ΄λ»κ² λ κΉ? "
value={text}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setText(e.target.value)
}
/>
</div>
);
}
Count
μ»΄ν¬λνΈκ° λΆνμνκ² λ¦¬λ λλ§μ λ§κΈ° μν΄ React.memo
λ₯Ό νμ©ν΄ μ»΄ν¬λνΈλ₯Ό λ©λͺ¨μ΄μ μ΄μ
νμΌλ―λ‘ propsκ° λ³κ²½λμ§ μλ ν Count
μ»΄ν¬λνΈλ 리λ λλ§ λ°μνμ§ μλλ€.
useCallback
ν¨μ
λ₯Ό λ©λͺ¨μ΄μ μ΄μ ν λ μ¬μ©νλ€.리λ λλ§ κ°μ ν¨μμ μ μλ₯Ό μΊμ±ν΄μ£Όλ React Hook
const cachedFn = useCallback(() => {}, dependencies);
π©π»βπ» μμ
import { memo, useState } from 'react';
const Count = ({ count }: { count: number }) => {
console.log('Count Rendered');
return (
<div>
<h1>Count Component</h1>
<h2>Count : {count}</h2>
</div>
);
};
const Button = ({ onClick }: { onClick: () => void }) => {
console.log('Button Rendered');
return (
<button type="button" onClick={onClick}>
count μ¦κ° λ²νΌ
</button>
);
};
const MemoCount = memo(Count);
const MemoButton = memo(Button);
export default function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
const onClickHandler = () => {
setCount(count + 1);
};
return (
<div>
<MemoCount count={count} />
<MemoButton onClick={onClickHandler} />
<input
type="text"
placeholder="input μ
λ ₯νλ©΄ μ΄λ»κ² λ κΉ? "
value={text}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setText(e.target.value)
}
/>
</div>
);
}
ν΄λΉ μ½λλ input μμμ μ
λ ₯νκ² λλ©΄ μ»΄ν¬λνΈκ° λΆνμνκ² λ¦¬λ λλ§μ λ§κΈ° μν΄ memoλ₯Ό μ¬μ©νλ€. νμ§λ§, Button
μ»΄ν¬λνΈλ μ
λ ₯μ κ³μ 리λ λλ§μ΄ λ°μλλ€. κ·Έμ΄μ λ 무μμΌκΉ? Button
μ»΄ν¬λνΈλ ν¨μλ₯Ό propsλ‘ λ°κ³ μλ€. ν¨μλ μ°Έμ‘°μλ£νμΌλ‘ λ©λͺ¨λ¦¬μ μ£Όμκ°μ μ μ₯νλ€. μ¦, μμ μ»΄ν¬λνΈ App
μ 리λ λλ§ νκ² λλ©΄ onClickHandler
ν¨μλ μ΄μ κ³Ό κ°μ ν¨μκ° μλ μλ‘μ΄ ν¨μλ‘ μμ±λμ΄ Button
μ»΄ν¬λνΈκ° 리λ λλ§ λκ² λλ€.
const onClickHandler = useCallback(() => {
setCount(count + 1);
}, []);
onClickHandler
ν¨μλ₯Ό useCallback
μ μ¬μ©ν΄ λ©λͺ¨μ΄μ μ΄μ
νκ² λλ©΄ input μμμ μ
λ ₯μ λμ΄μ 리λ λλ§μ΄ λμ§ μλλ€.
π¨ μμμΉ λͺ»ν μ΄μ
λΆνμν 리λ λλ§μ μμ§λ§, count μ¦κ° λ²νΌ
ν΄λ¦μ count κ°μ΄ 1λ‘ νλ²λ§ μ
λ°μ΄νΈλκ³ , Count
μ»΄ν¬λνΈκ° λμ΄μ μ
λ°μ΄νΈ λμ§ μλλ€. κ·Έμ΄μ λ 무μμΌκΉ? useCallback
μ μμ‘΄μ±λ°°μ΄μ κ°μ λΉκ°μ΄μ¬μ μ΄κΈ° λ λλ§μμλ§ ν΄λΉ ν¨μλ₯Ό μμ±νκ³ κ·Έ μ΄νμλ λμ΄μ ν¨μλ₯Ό μ¬μμ±νμ§ μλλ€. μ΄λ useCallback μΈμλ‘ μ λ¬λ°μ μ½λ°±ν¨μμμ count μ΄κΈ°κ° 0μ μ°Έμ‘°νκ³ μλ€. count μ¦κ° λ²νΌ
λ₯Ό ν΄λ¦νλ©΄ count
μνκ°μ 1λ‘ λ³κ²½λμ΄ λ¦¬λ λλ§μ΄ λ°μλλ€. λ€μ νλ² count μ¦κ° λ²νΌ
ν΄λ¦νλ©΄ useCallback μΈμλ‘ μ λ¬λ°μ μ½λ°±ν¨μμ countλ λ³κ²½λ μν 1μ΄ μλ count μ΄κΈ°κ° 0 μ°Έμ‘°ν΄μ κ³μ°ν΄μ setCount(count + 1)
λμνλ©΄ 1μ΄κΈ° λλ¬Έμ Count
μ»΄ν¬λνΈμ propsλ λ³κ²½λμ§ μμκΈ°μ 리λ λλ§ λ°μνμ§ μκ³ , count
μνκ°λ μ
λ°μ΄νΈ λμ§ μλλ€.
const onClickHandler = useCallback(() => {
setCount((prev) => prev + 1); // ππ» μ΄μ μ μνκ°μ μ°Έμ‘°νλλ‘ λ³κ²½
}, []);
μ΄κΈ° λ λλ§ μ count μ΄κΈ°κ° μνλ₯Ό μ°Έμ‘°νλκ² μλλΌ, μ΄μ μ countμ μνκ°μ μ°Έμ‘°ν μ μλ μ½λ°±ν¨μλ₯Ό μ¬μ©ν΄μ setCount ν¨μκ° μ
λ°μ΄νΈ λλλ‘ λ³κ²½ν΄μΌ Count
μ»΄ν¬λνΈλ 리λ λλ§ λ°μνκ² λλ€.
useMemo
κ°
λ₯Ό λ©λͺ¨μ΄μ μ΄μ ν λ μ¬μ©νλ€.리λ λλ§ μ¬μ΄μ κ³μ° κ²°κ³Όλ₯Ό μΊμ±ν μ μκ² ν΄μ£Όλ React Hook
λΉμ©μ΄ λμ λ‘μ§μ μ¬κ³μ° μλ΅
const cachedValue = useMemo(calculateValue, dependencies);
π©π»βπ» μμ
import { useState } from 'react';
// 3000λ§κ°μ λ°°μ΄ λ°μ΄ν°
const initialItems = new Array(29_999_999).fill(0).map((_, i) => {
return {
id: i,
selected: i === 29_999_998,
};
});
export default function App() {
const [count, setCount] = useState(0);
// 3000λ§κ°μ λ°°μ΄ λ°μ΄ν°λ₯Ό λ λλ§ λ§λ€ μ¬μμ±νκ³ μμ
const [items] = useState(initialItems);
const selectItems = items.find((item) => item.selected);
return (
<div>
<h1>Count : {count}</h1>
<button type="button" onClick={() => setCount((prev) => prev + 1)}>
μ¦κ°
</button>
<p>{selectItems?.id}</p>
</div>
);
}
ν΄λΉμ½λλ App
μ»΄ν¬λνΈκ° 리λ λλ§μ ν λ λ§λ€ 3000λ§κ°μ λ°°μ΄ λ°μ΄ν°λ₯Ό μ¬μμ±νκ³ μλ€. μ¦κ° λ²νΌμ ν΄λ¦μ 3000λ§κ°μ λ°°μ΄ λ°μ΄ν°λ₯Ό μ¬μμ±νλ€λ³΄λ μ°μ° λΉμ©μ΄ ν¬κΈ°λλ¬Έμ count μν μ
λ°μ΄νΈμ νλ©΄μ μ
λ°μ΄νΈ κ°μ΄ μΆλ ₯λμ§ μκ³ μλ€.
const selectItems = useMemo(() => items.find((item) => item.selected), []);
useMemo
λ₯Ό ν΅ν΄ λ©λͺ¨μ΄μ μ΄μ
ν κ°μ 리λ λλ§μ μ¬μ¬μ©νκΈ° λλ¬Έμ νλ©΄ μ
λ°μ΄νΈκ° λΉ λ₯΄κ² λμνκ² λμλ€.
Last updated