๊ด€๋ฆฌ ๋ฉ”๋‰ด

Soony's House

[React] useMemo (ft. ์žฌ์—ฐ์‚ฐ ์ตœ์ ํ™”) ๋ณธ๋ฌธ

โš™๏ธFrontend/REACT

[React] useMemo (ft. ์žฌ์—ฐ์‚ฐ ์ตœ์ ํ™”)

soonybutter 2025. 5. 28. 15:55
728x90

 

 

 

 

 

๐Ÿ’ก์ตœ์ ํ™”  

์ฝ”ํ…Œ๋ฅผ ์ค€๋น„ํ•˜๋ฉด์„œ๋„, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ํ•˜๋ฉด์„œ๋„ ํ•ญ์ƒ ์‹ ๊ฒฝ์จ์•ผํ•œ๋‹ค๊ณ  ๋ˆ„๋ˆ„ํžˆ ๋“ค์€ ์ฝ”๋“œ ์ตœ์ ํ™”.. ! ๋‘๋‘ฅ.. 

๋ฆฌ์•กํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ๋•Œ ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค.

 

 

๋ฆฌ์•กํŠธ์—์„œ๋Š” '๋ Œ๋”๋ง๊ณผ ์—ฐ์‚ฐ'์ด ์„ฑ๋Šฅ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค.

ํŠนํžˆ, ์ƒํƒœ( state) ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ์ด๋‚˜ ๋ Œ๋”๋ง์ด ๋ฐ˜๋ณต๋˜๋ฉด ์ „์ฒด ์„ฑ๋Šฅ์ด ์ €ํ•˜๋  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

 

 

๋ฆฌ์•กํŠธ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ์ง€์–‘ํ•ด์•ผํ•  ์š”์†Œ๋“ค์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

1. ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง

2. ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ

3. ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ ๋ถˆํ•„์š”ํ•œ ํ•จ์ˆ˜ ์žฌ์ƒ์„ฑ

 

 

 

 

์ด์ค‘ useMemo ํ›…์€ React์˜ ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ์„ ๋ง‰์•„ ์ตœ์ ํ™”ํ•œ๋‹ค.

 

 

 

 

 

 


 

 

 

๐Ÿ’กuseMemo 

: ํŠน์ • ์—ฐ์‚ฐ์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”๋ชจ์ด์ œ์ด์…˜(memoization) ํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ(์žฌ์—ฐ์‚ฐ)์„ ๋ฐฉ์ง€ํ•˜๋Š” React Hook.

-> ์˜์กด์„ฑ ๋ฐฐ์—ด์— ๋ช…์‹œ๋œ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ์—๋งŒ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ํ•ด๋‹น ์—ฐ์‚ฐ์„ ๋‹ค์‹œ ์ˆ˜ํ–‰ํ•œ๋‹ค.

๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, ์ด์ „์— ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•จ.

 

 

*์›๋ž˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋ ๋•Œ๋งˆ๋‹ค ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์—ฐ์‚ฐ์ด ํ•ญ์ƒ ์žฌ์‹คํ–‰๋˜๋Š”๋ฐ,

์ด ๊ณผ์ •์—์„œ ๋ฌด๊ฑฐ์šด ์—ฐ์‚ฐ์ด ๋ฐ˜๋ณต๋˜๊ฑฐ๋‚˜ ๋ถˆํ•„์š”ํ•œ ๋ฐฐ์—ด ํƒ์ƒ‰์ด ์ง€์†์ ์œผ๋กœ ๋ฐœ์ƒํ•˜๋ฉด ์„ฑ๋Šฅ์— ๋ถ€๋‹ด์ด๋จ.

 

 

 

 

 

 

useMemo๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง„๋‹ค.

const memoizedValue = useMemo(() => {
  // ์—ฐ์‚ฐํ•  ๋‚ด์šฉ
  return ๊ณ„์‚ฐ๋œ๊ฐ’;
}, [์˜์กด์„ฑ๊ฐ’1, ์˜์กด์„ฑ๊ฐ’2]);

 

 

  • ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋Š” ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
  • ๋‘ ๋ฒˆ์งธ ์ธ์ž์ธ ์˜์กด์„ฑ ๋ฐฐ์—ด์€, ํ•ด๋‹น ๊ฐ’๋“ค ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ๋งŒ ์ฒซ ๋ฒˆ์งธ ํ•จ์ˆ˜๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋˜๋„๋ก ํ•œ๋‹ค.
  • useMemo๋Š” ๊ณ„์‚ฐ๋œ ๊ฐ’์„ memoizedValue์— ์ €์žฅํ•˜๊ณ , ํ•„์š” ์‹œ ์ด๋ฅผ ์žฌ์‚ฌ์šฉํ•œ๋‹ค.

 

 

 

 

 

 

์ฐ ์˜ˆ์‹œ๋กœ ์ฝ”๋“œ ๋™์ž‘์„ ํŒŒ์•…ํ•ด๋ณด์ž! 

 

ex.

Todo List ์•ฑ์—์„œ ์™„๋ฃŒํ•œ ์ผ, ์™„๋ฃŒํ•˜์ง€ ์•Š์€ ์ผ, ์ „์ฒด ํ•  ์ผ์˜ ๊ฐœ์ˆ˜๋ฅผ ํ™”๋ฉด์— ๋ Œ๋”๋ง ํ•˜๋Š” ์ฝ”๋“œ์—์„œ useMemo๋ฅผ ์ ์šฉ์‹œํ‚ฌ ๊ฒƒ์ž„.

 

const { totalCount, doneCount, notDoneCount } = useMemo(() => {
  console.log("getAnalyzedData ํ˜ธ์ถœ!");
  const totalCount = todos.length;
  const doneCount = todos.filter((todo) => todo.isDone).length;
  const notDoneCount = totalCount - doneCount;

  return {
    totalCount,
    doneCount,
    notDoneCount
  };
}, [todos]);
  • todos ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ์—๋งŒ ์—ฐ์‚ฐ์„ ๋‹ค์‹œ ์ˆ˜ํ–‰ํ•จ.  -> ์˜์กด์„ฑ ๋ฐฐ์—ด
  • ์™„๋ฃŒ๋œ ํ•ญ๋ชฉ๊ณผ ๋ฏธ์™„๋ฃŒ ํ•ญ๋ชฉ์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋กœ์ง์€ filter()๋ฅผ ํ†ตํ•ด ๋ฐ˜๋ณต ์—ฐ์‚ฐ์„ ํฌํ•จํ•˜๋ฏ€๋กœ, ์ƒํƒœ๊ฐ€ ์ž์ฃผ ๋ณ€๊ฒฝ๋  ๊ฒฝ์šฐ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ฆฌ๋ Œ๋”๋ง ๋น„์šฉ์ด ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. (๋ฐฐ์—ด์„ ๊ณ„์†ํ•ด์„œ ์ „์ฒด ํƒ์ƒ‰ํ•˜๊ธฐ ๋•Œ๋ฌธ..;) 
  • ์ด๋ฅผ useMemo๋กœ ๊ฐ์‹ธ๋ฉด, todos๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ํ•œ ์ด์ „์˜ ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋ Œ๋”๋ง ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

 

 

 

 

 

๊ทผ๋ฐ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ์ „์— ์ „์— filter()๋กœ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ ๋งŒ๋“ค์–ด ๋†“์•˜๋˜๊ฒŒ ์ƒ๊ฐ๋‚ฌ๋‹ค.

๐Ÿ’ก๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ๊ณผ useMemo๋Š” ํ•จ๊ป˜ ์จ์•ผ ํ• ๊นŒ?

const getFilteredData = () => {
  if (search === "") return todos;
  return todos.filter((todo) =>
    todo.content.toLowerCase().includes(search.toLowerCase())
  );
};

const FilteredTodos = getFilteredData();

 

๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์˜ filter() ์—ญ์‹œ useMemo๋Š” ํ•จ๊ป˜ ์“ฐ๋Š”๊ฒŒ ์ข‹์„๊นŒ? ๊ถ๊ธˆํ•ด์„œ ์ฐพ์•„๋ณด์•˜์Œ.

 

๊ฒฐ๋ก :

ํ•„ํ„ฐ๋ง ๋กœ์ง ์ž์ฒด์™€, ์ž…๋ ฅ๊ฐ’( ๊ฒ€์ƒ‰์ฐฝ์— ์ž…๋ ฅ๋˜๋Š” ๊ฐ’) ์ด ๋ณ€๊ฒฝ ๋  ๋•Œ๋งˆ๋‹ค ๋™์ž‘ํ•˜๋Š” ๊ฒƒ๊นŒ์ง€๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด  UX ํ๋ฆ„์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

 

BUT , 

๋งŒ์•ฝ Todo ํ•ญ๋ชฉ์ด ์ˆ˜ ๋ฐฑ๊ฐœ ์ด์ƒ์œผ๋กœ ๋Š˜์–ด๋‚˜๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด, ์ด๊ฑด ๋”์ด์ƒ ๋‹จ์ˆœ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— useMemo๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์œ ๋ฆฌํ•ด์ง! 

 

 

 

 

search ๋˜๋Š” todos๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ํ•„ํ„ฐ๋ง ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก u

seMemo๋กœ ๊ฒ€์ƒ‰๊ธฐ๋Šฅ์„ ๊ฐ์‹ธ ๋ณด์•˜๋‹ค.

const filteredTodos = useMemo(() => {
  if (search === "") return todos;
  return todos.filter((todo) =>
    todo.content.toLowerCase().includes(search.toLowerCase())
  );
}, [search, todos]); 

 

์œ„์ฒ˜๋Ÿผ useMemo๋กœ ๊ฐ์‹ธ๋Š” ๊ฒฝ์šฐ,

์˜์กด์„ฑ ๋ฐฐ์—ด์— ํฌํ•จ๋œ search์™€ todos๋Š” ๋‘˜ ์ค‘ ํ•˜๋‚˜๋งŒ ๋ณ€๊ฒฝ๋˜์–ด๋„ ์—ฐ์‚ฐ์ด ๋‹ค์‹œ ์ˆ˜ํ–‰๋จ.

 

search ๊ฐ€ ๋ฐ”๋€Œ๋ฉด → ํ•„ํ„ฐ๋ง ๊ธฐ์ค€(๊ฒ€์ƒ‰์–ด)์ด ๋‹ฌ๋ผ์ง, ์—ฐ์‚ฐ ๋‹ค์‹œ ์ˆ˜ํ–‰

todos๊ฐ€ ๋ฐ”๋€Œ๋ฉด → ํ•„ํ„ฐ๋ง ๋Œ€์ƒ ๋ชฉ๋ก์ด ๋ฐ”๋€œ, ์—ฐ์‚ฐ ๋‹ค์‹œ ์ˆ˜ํ–‰

 

 

 

ํ•˜์ง€๋งŒ ๊ธฐ์–ตํ•  ๊ฑด ๋ฌด์กฐ๊ฑด useMemo๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, 

์ฝ”๋“œ ํ๋ฆ„ , ์„ฑ๋Šฅ์„ ๋”ฐ์ ธ๊ฐ€๋ฉฐ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ โ˜บ๏ธ

 

 

 

 

 

 


 

๐Ÿ’ก์ •๋ฆฌ

 

React์˜ useMemo ํ›…์€ ๋‹จ์ˆœํžˆ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ ๋„๊ตฌ๊ฐ€ ์•„๋‹ˆ๋ผ,

์ปดํฌ๋„ŒํŠธ์˜ ๋™์ž‘์„ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค๊ณ  ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๋Š” ์ค‘์š”ํ•œ ์ˆ˜๋‹จ.

 

 

Q. ์–ธ์ œ ์”๋‹ˆ๊นŒ?

  • ๋ฐ˜๋ณต์ ์ธ ์—ฐ์‚ฐ์ด ์žˆ๋Š” ๊ฒฝ์šฐ
  • ์—ฐ์‚ฐ ๊ฒฐ๊ณผ๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š์•„๋„ ์ž์ฃผ ๋ Œ๋”๋ง๋˜๋Š” ์ปดํฌ๋„ŒํŠธ
  • ๋ฆฌ์ŠคํŠธ๋‚˜ ํ…Œ์ด๋ธ”์ฒ˜๋Ÿผ ํ•ญ๋ชฉ์ด ๋งŽ์•„์งˆ ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ

์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ๋Š” useMemo์˜ ๋„์ž…์ด ํ•„์ˆ˜์ ์ด๋‹ค.

๋‹จ, ๋ชจ๋“  ๊ณ„์‚ฐ์— ๋ฌด์กฐ๊ฑด์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์˜คํžˆ๋ ค ์ฝ”๋“œ ๋ณต์žก๋„๋งŒ ๋†’์ผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์—ฐ์‚ฐ ๋น„์šฉ๊ณผ ๋นˆ๋„๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

*Ref

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

 

useMemo – React

The library for web and native user interfaces

ko.react.dev

์„ค๋ช…์ด ๋ถ€์กฑํ•œ ๋ถ€๋ถ„์ด๋‚˜ ํ”ผ๋“œ๋ฐฑ์€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์„ธ์š”!

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค โ˜บ๏ธ

728x90