๐ 2024. 03. 29 75์ผ์ฐจ
import React, { useState, useEffect } from "https://cdn.skypack.dev/react@18";
import ReactDOM from "https://cdn.skypack.dev/react-dom@18";
let AppCallCount = 0;
let SubCallCount = 0;
const Sub = ({appNo}) => {
SubCallCount++;
console.log(`Sub ${SubCallCount}๋ฒ ์คํ๋จ`);
const [no, setNo] = useState(0);
const [no2, setNo2] = useState(0);
useEffect(() => {
console.log('effect 1 : ์ต์ด์ ํ๋ฒ๋ง ์คํ');
},[]); // props : ์์ ์ปดํฌ๋ํธ๊ฐ ํ์ ์ปดํฌ๋ํธ์ ๊ฐ์ ์ ๋ฌํ ๋ ์ฌ์ฉํ๋ ์์ฑ
useEffect(() => {
console.log('effect 2 : ๋ถ๋ชจ์ appNo๊ฐ ๋ฐ๋๋๋ง๋ค ์คํ');
},[appNo]);
useEffect(() => {
console.log('effect 3 : ๋(Sub)์ no๊ฐ ๋ฐ๋๋๋ง๋ค ์คํ');
},[no]);
useEffect(() => {
console.log('effect 4 : appNo ํน์ no๊ฐ ๋ฐ๋๋๋ง๋ค ์คํ');
},[appNo, no]);
useEffect(() => {
console.log('effect 5 : ๋งค๋ฒ ์คํ');
});
return (
<>
<button onClick={() => setNo(no + 1)}>Sub ๋ฒํผ(no) : {no}</button>
<button onClick={() => setNo2(no2 + 1)}>Sub ๋ฒํผ(no2) : {no2}</button>
</>
);
};
const App = () => {
AppCallCount++;
console.log(`App ${AppCallCount}๋ฒ ์คํ๋จ`);
const [no, setNo] = useState(0);
return (
<>
<div style={{ border: "5px solid red", padding: 10 }}>
App no : {no}
<Sub appNo={no}/>
<hr />
<button onClick={() => setNo(no + 1)}>App ๋ฒํผ : {no}</button>
</div>
</>
);
};
//์๋ต
// ์์ ํ๋ณ๊ธฐ(๋๊ฒจ์ง ๊ฐ์ด ์์์ธ์ง ์๋์ง)
function isPrimeNumber(num) {
if (num <= 1) return false;
for (let i = 2; i < num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
// 1๋ถํฐ n๊น์ง ์ ์ค์์ ์์๋ง ๋ฐฐ์ด๋ด์์ ๋ฆฌํด
function getPrimeNumbers(maxValue) {
const primeNumbers = [];
for (let i = 1; i <= maxValue; i++) {
if (isPrimeNumber(i)) {
primeNumbers.push(i);
}
}
return primeNumbers;
}
function getPrimeNumbersCount(maxValue) {
return getPrimeNumbers(maxValue).length;
}
const App = () => {
const [inputedNo,setInputedNo] = useState(0);
const primeNumberCount = getPrimeNumbersCount(inputedNo);
const onSubmit = (e) => {
e.preventDefault();
const form = e.target;
form.number.value = form.number.value.trim();
if(form.number.value.length == 0){
alert('์ซ์ ์จ');
form.number.focus();
return;
}
const number = form.number.valueAsNumber;
form.number.focus();
setInputedNo(number);
// alert(`๋ค๊ฐ ์
๋ ฅํ ์ซ์๋ ${number} (์ด)๋ค.`);
}
return (
<>
<form onSubmit={onSubmit}>
<input type="number" name="number" placeholder="์ซ์ ์
๋ ฅํด" defaultValue="0"/>
<button type="submit">ํ์ธ</button>
<div>MAX : {inputedNo}</div>
<hr/>
<div>์์์ ๊ฐฏ์ : {primeNumberCount}</div>
<hr/>
</form>
</>
);
};
//์๋ต
import React, { useState, useEffect } from "https://cdn.skypack.dev/react@18";
// inputedNo ๊ฐ์ด ๋ณ๊ฒฝ ๋์์ ๋๋ง ์ฌ๋๋๋ง
useEffect(() => {
const primeNumberCount = getPrimeNumbersCount(inputedNo);
setPrimeNumberCount(primeNumberCount);
},[inputedNo]);
import React, { useState, useMemo } from "https://cdn.skypack.dev/react@18";
const primeNumberCount = useMemo(() => getPrimeNumbersCount(inputedNo), [inputedNo]);
import React, { useState, useCallback } from "https://cdn.skypack.dev/react@18";
import ReactDOM from "https://cdn.skypack.dev/react-dom@18";
let SubCallCount = 0;
function Sub({ no1, no2, calculateFunc }) {
SubCallCount++;
console.log(`Sub์ด ${SubCallCount}๋ฒ ์คํ`);
return (
<div style={{ border: "10px solid black", padding: 10 }}>
์
๋ ฅ : {no1}, {no2}
<br/>
๊ฒฐ๊ณผ : {calculateFunc(no1,no2)}
</div>
);
}
const MemoizedSub = React.memo(Sub);
// const calculateFunc = (a, b) => a + b;
let AppCallCount = 0;
const App = () => {
AppCallCount++;
console.log(`App์ด ${AppCallCount}๋ฒ ์คํ`);
const [no1, setNo1] = useState(0);
const [no2, setNo2] = useState(0);
// const calculateFunc = useCallback((a,b) => a + b + no1,[]);
// ์์ ๊ฐ์ ๊ฒฝ์ฐ์ ์ต์ด์ ํ๋ฒ๋ง no1์ด ๋ฐ๋์ด๋ ๋ฐ์ ๋์ง ์์, ์ด์ ๋ฒ์ ์ ํจ์๋ฅผ ๊ธฐ์ต ์ค
const calculateFunc = useCallback((a,b) => a + b + no1,[no1]);
// no1์ ๊ฐ์ด ๋ฐ๋๋ฉด ํจ์๋ฅผ ๋ค์ ๋ง๋ค์ด์ ๋ฆฌํด
return (
<>
<button onClick={() => setNo1(no1 + 1)}> ๋ฒํธ1 : {no1}</button>
<hr />
<button onClick={() => setNo2(no2 + 1)}> ๋ฒํธ2 : {no2}</button>
<hr />
<MemoizedSub no1={10} no2={20} calculateFunc={calculateFunc} />
</>
);
};
useMemo์์ memo๋ memoization์ ๋ปํ๋๋ฐ ์ด๋ ๊ทธ๋๋ก ํด์ํ๋ฉด โ๋ฉ๋ชจ๋ฆฌ์ ๋ฃ๊ธฐโ๋ผ๋ ์๋ฏธ์ด๋ฉฐ ์ปดํจํฐ ํ๋ก๊ทธ๋จ์ด ๋์ผํ ๊ณ์ฐ์ ๋ฐ๋ณตํด์ผ ํ ๋, ์ด์ ์ ๊ณ์ฐํ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํจ์ผ๋ก์จ ๋์ผํ ๊ณ์ฐ์ ๋ฐ๋ณต ์ํ์ ์ ๊ฑฐํ์ฌ ํ๋ก๊ทธ๋จ ์คํ ์๋๋ฅผ ๋น ๋ฅด๊ฒ ํ๋ ๊ธฐ์ ์ด๋ค.
์ฝ๊ฒ ๋งํด ๋์ผํ ๊ฐ์ ๋ฐํํ๋ ํจ์๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ํธ์ถํด์ผํ๋ค๋ฉด ์ฒ์ ๊ฐ์ ๊ณ์ฐํ ๋ ํด๋น ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํด ํ์ํ ๋๋ง๋ค ๋ค์ ๊ณ์ฐํ์ง ์๊ณ ๋ฉ๋ชจ๋ฆฌ์์ ๊บผ๋ด์ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
๋ฆฌ์กํธ์์ ํจ์ํ ์ปดํฌ๋ํธ๋ ๋ ๋๋ง => ์ปดํฌ๋ํธ ํจ์ ํธ์ถ => ๋ชจ๋ ๋ด๋ถ ๋ณ์ ์ด๊ธฐํ์ ์์๋ฅผ ๊ฑฐ์น๋ค.
์ปดํฌ๋ํธ ์ต์๋จ์์ useMemo๋ฅผ ํธ์ถ
ํ ๋ฒ ์ฐ์ฐํด๋ณธ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ์ตํด๋๊ณ , ๋ค์ ๋์ผํ ์ ๋ ฅ์ด ๋ค์ด์ค๋ฉด ๊ธฐ์ตํด๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ ๋ฐฉ๋ฒ์ด๋ค.
1+1 ์ ๋ฌด์์ธ๊ฐ?
(๊ณ์ฐ์ค...)
(๊ณ์ฐ์๋ฃ) => 2
๋ค์ ํ๋ฒ๋ 1+1์ ๋ฌด์์ธ๊ฐ?
(์ ์ด๋ ๋์ผํ๋ค? ๊ธฐ์ตํด๋๋๊ฑฐ ๋ฐ๋ก ๋ฐํ) 2
์ ๋ฐฉ์์ฒ๋ผ ์์ฒญ ๋ณต์กํ๊ฑฐ๋ ์ฑ๋ฅ์ ์ก์๋จน๋ ํจ์๋ผ๋ฉด ์ด๋ฌํ ์ฑ๋ฅ์ต์ ํ๊ฐ ํ์ํ๋ค.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
์ด ์ฝ๋๋ ์์ฑ(create) ํจ์์ธ computeExpensiveValue(a, b) ๋ฅผ ํธ์ถํ๋ค.
useMemo๋ ์์กด์ฑ์ธ [a, b]๊ฐ ๋ณ๊ฒฝ๋์์ ๋์๋ง ๋ฉ๋ชจ์ด์ ์ด์
๋ ๊ฐ๋ง ๋ค์ ๊ณ์ฐํ๋ค.
์ฆ, [a, b]๊ฐ ๋ณ๊ฒฝ๋์ง ์์ผ๋ฉด ์ด์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๋ก ๋ฐํํ๋ฏ๋ก ์ด๋ฌํ ์ต์ ํ๋ ๋ชจ๋ ๋ ๋๋ง ์์ ๊ณ ๋น์ฉ ๊ณ์ฐ์ ๋ฐฉ์งํ๊ฒ ํด์ค๋ค.
a์ b์ ์ํ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ๊ทธ๊ฒ์ ์ฌ์ฉํ๋ ๋ชจ๋ ์ปดํฌ๋ํธ๋ ์ฌ๋ ๋๋ง ๋๋ค.
๊ทธ ๋ ์ ๋ถ ๋ ๋๋ง์ด ๋๊ธฐ์ ๊ณ์ฐ๋ ๋ค์ํ์ฌ ๋ ๋๋ง๋๋ค.
ํ์ง๋ง a์ b๊ฐ ์ด์ ๊ฐ๊ณผ ๋์ผํ๋ค๋ฉด ๊ตณ์ด ์ฐ์ฐํ ํ์๊ฐ ์๋ค.
๊ทธ๋์ ์ด useMemo๋ฅผ ์ฐ๋ ๊ฒ์ด๋ค.
๋ง์ฝ useMemo์ ๋๋ฒ์งธ ์ธ์์ธ ์์กด์ฑ ๊ฐ์ ๋น ๋ฐฐ์ด์ด ๋ค์ด๊ฐ๋ค๋ฉด ๋งค ๋ ๋๋ง๋๋ง๋ค ๊ณ์ฐ์ ํ๊ฒ ๋๋ค.
์ด๋ด ๊ฒฝ์ฐ useEffect์ ๋์ผํ๊ฒ ๋์ํ์ง๋ง useEffect์ฒ๋ผ ์ฌ์ฉํ๋ฉด ์๋๋ค.
์ฌ์ด๋ ์ดํํธ(side effects)๋ useEffect์์ ํ๋ ์ผ์ด์ง useMemo์์ ํ๋ ์ผ์ด ์๋๊ธฐ ๋๋ฌธ์ด๋ค.
useMemo ๋ ํน์ ๊ฒฐ๊ณผ๊ฐ์ ์ฌ์ฌ์ฉ ํ ๋ ์ฌ์ฉํ๋ ๋ฐ๋ฉด, useCallback ์ ํน์ ํจ์๋ฅผ ์๋ก ๋ง๋ค์ง ์๊ณ ์ฌ์ฌ์ฉํ๊ณ ์ถ์๋ ์ฌ์ฉํฉ๋๋ค.
const memoizedCallback = useCallback(() => {
doSomething(a, b)
}, [a, b])
useCallback ์์กด์ฑ ๋ฐฐ์ด์ ์๋ ์ํ๋ props๊ฐ ๋ณ๊ฒฝ๋์ง ์๋๋ค๋ฉด, ํด๋น ํจ์๋ ๋ค์ ์์ฑ๋์ง ์๋๋ค.
์ฒซ๋ฒ์งธ ์ธ์๋ก ๋๊ธด ํจ์๋ฅผ ๋๋ฒ์งธ ์ธ์๋ก ๋๊ธด ์์กด์ฑ ๋ฐฐ์ด๋ด์ ๊ฐ์ด ๋ณ๊ฒฝ๋๊ธฐ ์ ๊น์ง ์ ์ฅํ๊ณ ์ฌ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋ค.