[React] ์ฑ๋ฅ ์ต์ ํ React.memo์ ๋ํด์ ์์๋ณด๊ธฐ
๐ ๋ค์ด๊ฐ๋ฉฐ
React์์ ์ฑ๋ฅ์ ์ต์ ํํ๊ธฐ ์ํด ์ฌ์ฉํ ์ ์๋ React.memo์ ๋ํด ์๊ฐํ๊ณ , ๊ธฐ๋ฅ์ ์ด๋ค ์ํฉ์์ ์ ์ฌ์ฉํ๊ณ ๋์์๋ฆฌ์ ์ฌ์ฉ ์์ ์ฝ๋๋ ํจ๊ป ์์๋ณด๊ฒ ์ต๋๋ค.
React.memo๋ โ
memo๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋น ์ปดํฌ๋ํธ์ props๊ฐ ๋ณ๊ฒฝ๋์ง ์์ ๊ฒฝ์ฐ ๋ฆฌ๋ ๋๋ง์ ๊ฑด๋๋ธ ์ ์์ต๋๋ค.
์ฆ, ๋ฉ๋ชจํ๋ ๋ฒ์ ์ ์ปดํฌ๋ํธ๋ก ํด๋น ์ปดํฌ๋ํธ์ props๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ๋ฆฌ๋ ๋๋ง์ ํ ์ ์์ต๋๋ค.
์ปค๋ค๋ ํ๋ชจ์ ์ปดํฌ๋ํธ๋ ๋ณต์กํ ์ํฉ์์ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ๋ง์ ์ฑ๋ฅ์ ์ต์ ํํ ์ ์์ต๋๋ค.
๋์ ์๋ฆฌ ๐ก
React.memo๋ ์ธ์๋ก ๋ค์ด๊ฐ ์ปดํฌ๋ํธ์ ์ด๋ค props๊ฐ ์ ๋ ฅ๋๋์ง ํ์ธํ๊ณ ์ ๋ ฅ๋๋ ๋ชจ๋ props์ ์ ๊ท ๊ฐ์ ํ์ธํ ๋ค ์ด๋ฅผ ๊ธฐ์กด์ props์ ๊ฐ๊ณผ ๋น๊ตํ๋๋ก ๋ฆฌ์กํธ์๊ฒ ์ ๋ฌํ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ props์ ๊ฐ์ด ๋ฐ๋ ๊ฒฝ์ฐ์๋ง ๋ฆฌ๋ ๋๋ง์ด ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋ณ๊ฒฝ๋์์ง๋ง ํด๋น ์ปดํฌ๋ํธ์ props ๊ฐ์ด ๋ฐ๋์ง ์์๋ค๋ฉด ๋ฆฌ๋ ๋๋ง์ ๊ฑด๋๋ฐ๊ฒ ๋ฉ๋๋ค.
์ฌ์ฉ ์์
import React, { memo } from 'react';
const ExpensiveComponent = ({ show }) => {
console.log('ExpensiveComponent๊ฐ ๋ฆฌ๋ ๋๋ง๋ฉ๋๋ค.');
return (
<div>
{show ? '์๋
' : ''}
</div>
);
};
export default memo(ExpensiveComponent);
์ด๋ ๊ฒ ๊ฐ์ธ์ฃผ๊ธฐ๋ง ํ๋ฉด props๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ๋ฆฌ๋ ๋๋ง์ ํฉ๋๋ค.
๊ฐ์ธ์ค ์ปดํฌ๋ํธ์ ์์ ์ปดํฌ๋ํธ๊น์ง ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ๋ง์ ์ ์์ต๋๋ค.
ํ์ง๋ง ์ฌ๊ธฐ์ ์๋ฌธ์ ์ด ๋ฐ์ํฉ๋๋ค.
"๊ทธ๋ผ ์ ์ด๊ฑธ ๋ชจ๋ ์ปดํฌ๋ํธ์ ์ ์ฉํ์ง ์๋ ๊ฑธ๊น?"
์ง๋ฌธ์ ๋ํ ๋ต์ ์ต์ ํ์๋ ๋น์ฉ์ด ๋ฐ๋ฅด๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด memo ๋ฉ์๋๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋ณ๊ฒฝ์ด ๋ฐ์ํ ๋๋ง๋ค ํด๋น ์ปดํฌ๋ํธ๋ก ์ด๋ํ์ฌ ๊ธฐ์กด props ๊ฐ๊ณผ ์๋ก์ด props์ ๊ฐ์ ๋น๊ตํ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ฉด ๋ฆฌ์กํธ๋ ๋ ๊ฐ์ง ์์ ์ ํ ์ ์์ด์ผ ํฉ๋๋ค.
๋จผ์ ๊ธฐ์กด์ props ๊ฐ์ ์ ์ฅํ ๊ณต๊ฐ์ด ํ์ํ๊ณ ๋น๊ตํ๋ ์์ ๋ ํ์ํฉ๋๋ค.
๋ฐ๋ผ์, ์ด ํจ์จ์ ์ด๋ค ์ปดํฌ๋ํธ๋ฅผ ์ต์ ํํ๋๋์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๊ฒ ๋ฉ๋๋ค.
์ปดํฌ๋ํธ๋ฅผ ์ฌํ๊ฐํ๋ ๋ฐ์ ํ์ํ ์ฑ๋ฅ ๋น์ฉ๊ณผ props๋ฅผ ๋น๊ตํ๋ ์ฑ๋ฅ ๋น์ฉ์ ์๋ก ๋ง๋ฐ๊พธ๋ ๊ฒ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ props์ ๊ฐ์์ ์ปดํฌ๋ํธ์ ๋ณต์ก๋, ๊ทธ๋ฆฌ๊ณ ์์ ์ปดํฌ๋ํธ์ ์์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ฏ๋ก ์ด๋ ์ชฝ์ ๋น์ฉ์ด ๋ ๋๋ค๊ณ ํ์ ์ง๊ณ ๋งํ ์ ์์ต๋๋ค.
๊ทธ๋์ ์ํฉ์ ๋ฐ๋ผ ์ ์ ํ ์ฌ์ฉํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๋ถ๋ชจ ์ปดํฌ๋ํธ๋ก๋ถํฐ props๋ก ํจ์๋ฅผ ๋ฐ๋ ์ํฉ โ
// Button.js
const Button = ({ onClick }) => {
console.log('Button RUNNING');
return <button onClick={onClick}>ํด๋ฆญ</button>;
};
export default React.memo(Button);
// App.js
import React, { useState } from 'react';
function App() {
const [toggleState, setToggleState] = useState(false);
console.log('APP RUNNING');
const toggleStateHandler = () => setToggleState((prev) => !prev);
return (
<div className="app">
<Button onClick={toggleStateHandler}>Toggle State</Button>
</div>
);
}
export default App;
์์์ ๋งํ ๋ด์ฉ๋๋ก๋ผ๋ฉด Button ์ปดํฌ๋ํธ์ props๋ ๋ฐ๋์ง ์๊ธฐ ๋๋ฌธ์ ์ต์ด ๋ ๋๋ง ํ ๋ฆฌ๋ ๋๋ง์ด ๋ ์ผ์ด ์์ต๋๋ค.
ํ์ง๋ง ๋ถ๋ชจ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋ ๋๋ง๋ค ๊ฐ์ด ๋ ๋๋ง์ด ๋๋ ์ํฉ์ ๊ฒช์ ์ ์์ ๊ฒ์ ๋๋ค.
์ ๊ทธ๋ด๊น์?
React.memo๊ฐ ์ต์ข ์ ์ผ๋ก ํ๋ ์ผ์ props์ ๊ฐ์ ํ์ธํ๊ณ ๋น๊ตํฉ๋๋ค.
props.show === props.previous.show
์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋น๊ต๋ฅผ ํ๊ฒ ๋ฉ๋๋ค. (์ค์ ๋ก ์ด๋ ๊ฒ ๋น๊ต๋๋ ๊ฒ์ ์๋๋๋ค.)
์ฌ๊ธฐ์ ์์๊ฐ๊ณผ ์ฐธ์กฐ๊ฐ์ ์ดํด๊ฐ ํ์ํฉ๋๋ค.
cosnt str1 = 'hi';
const str2 = 'hi';
console.log(str1 === str2) // true
const arr1 = [1,2,3];
const arr2 = [1,2,3];
console.log(arr1 === arr2) // false
์์ ๊ฐ์ด ๋ฐฐ์ด์ด๋ ๊ฐ์ฒด, ํจ์๋ ์ฐธ์กฐ๊ฐ์ด๊ธฐ ๋๋ฌธ์ ๊ฐ์ ๋ค๋ฅธ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๊ฐ ๋ณด๊ธฐ์ ๋ด์ฉ์ ๊ฐ๋๋ผ๋ ๋น๊ต ์์๋ ๋ค๋ฆ ๋๋ค.
๋ค์ ๋์์์ ํจ์๋ ํ๋์ ๊ฐ์ฒด์ ๋ถ๊ณผํฉ๋๋ค.
๋ถ๋ชจ ์ปดํฌ๋ํธ(App)๊ฐ ์คํ๋ ๋ ์๋ก์ด ํจ์ ๊ฐ์ฒด๊ฐ ์์ฑ์ด ๋๊ณ ์ด ํจ์ ๊ฐ์ฒด๊ฐ onClick props์ ์ ๋ฌ๋ฉ๋๋ค.
์ด๋ ๊ฒ ๋๋ฉด ๋ฒํผ์ props.onClick๊ณผ props.previous.onClick๋ฅผ ๋น๊ตํ๋ ์ ์ธ๋ฐ ์ฐธ์กฐ๊ฐ์ด๊ธฐ ๋๋ฌธ์ ๊ฒฐ๊ตญ ๋์ผํ์ง ์์ต๋๋ค.
์ฆ, React.memo๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ์ด๋ฌํ ๋์ ๋๋ฌธ์ ๊ฐ์ด ๋ณ๊ฒฝ๋์๋ค๊ณ ์ธ์ํ๊ณ ๋ฆฌ๋ ๋๋ง์ด ๋๋ ๊ฒ์ ๋๋ค.
๊ทธ๋ผ ์ด๋ฐ ์ํฉ์ ์ด๋ป๊ฒ ํด๊ฒฐํด์ผ ํ ๊น์?
๋ฐ๋ก useCallback์ผ๋ก ํด๊ฒฐํ ์ ์์ต๋๋ค.
๋ค์ ๊ธ์ useCallback์ ๋ํด์ ์์๋ณด๊ฒ ์ต๋๋ค.