React study: ๋ฆฌ์•กํŠธ๊ฐ€ ์„ฑ๋Šฅ์„ ๋ณด์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•

@choi2021 ยท January 23, 2023 ยท 14 min read

๐Ÿ˜ ๋ฆฌ์•กํŠธ์˜ ์„ฑ๋Šฅ ๋ณด์žฅ๋ฐฉ์‹

์ €๋ฒˆ ๋ฉด์ ‘ ์‹œ๊ฐ„์— ๋ฆฌ์•กํŠธ์— ๋Œ€ํ•œ ์งˆ๋ฌธ์ด ๋“ค์–ด์™”์„ ๋•Œ, ์•ˆ๋‹ค๊ณ  ์ž์‹ ํ–ˆ์ง€๋งŒ ๋Œ์•„๋ณด๋‹ˆ ๋„ˆ๋ฌด ๋ถ€์กฑํ–ˆ์—ˆ๋˜ ๋ชจ์Šต์— ๋ฆฌ์•กํŠธ ๋ฌธ์„œ ์ž์ฒด๋ฅผ ๋‹ค์‹œ ๊ผผ๊ผผํžˆ ์ฝ๊ณ  ์ •๋ฆฌํ•ด์•ผ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ๊ทธ์ค‘์— ์ด๋ฒˆ์— ๊ธฐ๋ณธ ๋™์ž‘์›๋ฆฌ์™€ ์„ฑ๋Šฅ๊ณผ ๊ด€๋ จ๋œ useMemo์™€ useCallback์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด ๋ณด๋ ค ํ•œ๋‹ค.

โ“ ์™œ ๋ฆฌ์•กํŠธ๋ฅผ ์จ์•ผ ํ• ๊นŒ?

๋จผ์ € ๋ฆฌ์•กํŠธ๋ฅผ ์“ฐ๋ฉด์„œ ๋‚ด๊ฐ€ ์™œ ๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ ๋งŽ์ด ๊ณ ๋ฏผํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.

๊ฐœ์ธ์ ์œผ๋กœ ๋‚ด๊ฐ€ ๋А๋‚€ ๋ฆฌ์•กํŠธ์˜ ์žฅ์ ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ ๊ทน์ ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์ ์ด์—ˆ๋‹ค. ๋ฌผ๋ก  Vue๋„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋ฆฌ์•กํŠธ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ข€ ๋” ์ž์œ ๋กญ๊ฒŒ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  ์ž˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ž์ฒด๋ฅผ ์ข€ ๋” ๊ณต๋ถ€ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. ์ด์ ์ด ์˜คํžˆ๋ ค ๋Ÿฌ๋‹ ์ปค๋ธŒ๊ฐ€ ๋‚ฎ๋‹ค๋Š” ์ ์—์„œ Vue์˜ ์žฅ์ ์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ํ•˜๋‚˜์˜ ์–ธ์–ด๋ฅผ ์ •๋ง ์ž˜ํ•˜๊ณ  ์‹ถ์—ˆ๋˜ ๋‚˜์—๊ฒŒ ์žˆ์–ด์„œ๋Š” ๋ฆฌ์•กํŠธ์˜ ์žฅ์ ์ด ๋˜์—ˆ๋‹ค.

Vue์™€ React๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•ด๋ณด์•˜๋‹ค๋ฉด ๋” ์ž˜ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„, ์ดํ›„์— ์กฐ๊ธˆ์”ฉ ์‹œ๋„ํ•˜๋ฉด์„œ ์ง์ ‘ ๋А๊ปด๋ณด๊ณ  ์ •๋ฆฌํ•ด๋ณด๋ฉด ์ข‹์„ ์ฃผ์ œ๋ผ๊ณ  ์ƒ๊ฐ๋˜์—ˆ๋‹ค.

โ— ๋ฆฌ์•กํŠธ๊ฐ€ ํ•ด๊ฒฐํ•˜๊ณ  ์‹ถ์—ˆ๋˜ ๋ฌธ์ œ

์ด์ „์— CSR๊ณผ SSR ๊ธ€๊ณผ Critical Rendering path์— ๋Œ€ํ•ด ๊ธ€์„ ์“ฐ๋ฉด์„œ ์ •๋ฆฌํ–ˆ์ง€๋งŒ SPA์€ MPA(Multi Page Application)์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‚˜์˜ค๊ฒŒ ๋œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด๋‹ค. MPA์˜ ๋ฌธ์ œ์ ์€ ํŽ˜์ด์ง€ ์ด๋™์— ๋”ฐ๋ผ HTML ์ „์ฒด๋ฅผ ์ƒˆ๋กญ๊ฒŒ ๊ฐ€์ ธ์™€์•ผ ํ•˜๋Š” ๋ถˆํ•„์š”ํ•œ ๋น„์šฉ์ด ๋ฐœ์ƒํ•œ๋‹ค๋Š” ์ ์ด์—ˆ๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํ•˜๋‚˜์˜ html์— javascript์„ ์ด์šฉํ•ด ๋™์ ์œผ๋กœ DOM์š”์†Œ๋ฅผ ๋ณ€ํ˜•ํ•˜๋Š”SPA (Single Page Application) ๋ฐฉ์‹์ด ์ œ์•ˆ๋˜์—ˆ๊ณ  ์—ฌ๊ธฐ์— ๋Œ€ํ‘œ์ ์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋ฐ”๋กœ ๋ฆฌ์•กํŠธ์ด๋‹ค.

ํ•˜์ง€๋งŒ SPA๋Š” DOM์š”์†Œ๋ฅผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ง์ ‘ ๊ฑด๋“œ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— Critical Rendering Path์—์„œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊ทธ๋ ค์ค˜์•ผํ•˜๋Š”layout -paint- composite๊ณผ์ •์ด ๋‹ค์‹œ ์ผ์–ด๋‚˜์•ผ ํ•ด์„œ ์„ฑ๋Šฅ์ด ํฐ ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฆฌ์•กํŠธ๋Š” ์ž์ฒด์ ์ธ V-DOM์„ ์ด์šฉํ•œ Reconcilation์œผ๋กœ ํ•ด๊ฒฐํ•œ๋‹ค. ๋‘๊ฐ€์ง€์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

๐ŸŽˆ V-DOM๊ณผ Reconcilation

V-DOM์€ ๋ฆฌ์•กํŠธ ์ž์ฒด์˜ ๊ฐ€์ƒ์˜ DOM์ด๋‹ค. ๋ฆฌ์•กํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ UI๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๊ธฐ ์œ„ํ•ด, DOM์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ์ƒํƒœ์— ๋”ฐ๋ผ ๋งค๋ฒˆ DOM์ž์ฒด๊ฐ€ ๋ฐ”๋€Œ๊ฒŒ ๋œ๋‹ค๋ฉด ์„ฑ๋Šฅ์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ์•กํŠธ๋Š” ์ž์ฒด์ ์œผ๋กœ V-DOM์— ์—…๋ฐ์ดํŠธ ํ•ด์•ผํ•  ๋ถ€๋ถ„์„ ๋จผ์ € ๋ฐ˜์˜ํ•œ๋‹ค. ์ด๋•Œ V-DOM์„ DOM์— ๋ฐ˜์˜ํ•  ํƒ€์ด๋ฐ์„ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์žˆ์–ด, ์ ์ ˆํ•œ ํƒ€์ด๋ฐ์— V-DOM๊ณผ ์‹ค์ œ DOM์„ ๋น„๊ตํ•ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ๋ฐ˜์˜ํ•˜๋Š”๋ฐ ์ด๊ฒƒ์„ Reconcilation์ด๋ผ๊ณ  ํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ V-DOM์ž์ฒด๋กœ ๋žœ๋”๋ง์„ ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋น„์šฉ์ด ์ ๊ฒŒ ๋“ค๋ฉด์„œ ๋งค๋ฒˆ DOM์„ ์—…๋ฐ์ดํŠธํ•˜์ง€ ์•Š๊ณ  ํ•„์š”ํ•œ DOM๋ณ€ํ™”๋ฅผ ๋ชจ์•„์„œ ํ•œ๋ฒˆ์— ์ฒ˜๋ฆฌํ•ด ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ๊ณผ์ •์ด ์ด์ „์— ๋งŽ์ด ์“ฐ์ด๋˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ JQuery์™€ ์ฐจ์ด๊ฐ€ ๋‚˜๋Š” ๋ถ€๋ถ„์œผ๋กœ DOM์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” JQuery์™€ ๋‹ฌ๋ฆฌ ํ•„์š”ํ•œ ๋ณ€ํ™”๋ฅผ ๋น„๊ตํ•˜๊ณ  ๊ทธ๋ถ€๋ถ„๋งŒ ์—…๋ฐ์ดํŠธํ•ด ํ›จ์”ฌ ์„ฑ๋Šฅ์ด ์ข‹๋‹ค.

vdom
vdom

Reconcilation์€ V-DOM์„ ์ด์šฉํ•ด ์‹ค์ œ DOM๊ณผ ๋น„๊ตํ•ด ๋ฐ˜์˜ํ•˜๋Š” ๊ณผ์ •์ด๋ผ๊ณ  ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ ์ค‘์š”ํ•œ ์ ์€ ๋น„๊ตํ•˜๋Š” ๊ฒƒ ์ž์ฒด์—๋„ ์„ฑ๋Šฅ์ด ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ๋ฆฌ์•กํŠธ ํ™ˆํŽ˜์ด์ง€์— ๋น„๊ต ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ state of art algorithm์„ ์ด์šฉํ•œ๋‹ค๋ฉด O(n^3)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ์— ํฐ ๋ฌธ์ œ๊ฐ€ ๋œ๋‹ค๊ณ  ํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ์•กํŠธ๋Š” ์„ฑ๋Šฅ์„ ๊ณ ๋ คํ•œ ๋น„๊ต๋ฅผ ์œ„ํ•ด ๋‘๊ฐ€์ง€ ๊ฐ€์ •์„ ํ•œ๋‹ค.

์ฒซ๋ฒˆ์งธ๋Š” element์˜ type์ด ๋‹ฌ๋ผ์ง€๋ฉด ๋‹ค๋ฅธ ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ ๋‹ค๋Š” ๊ฒƒ์ด๊ณ , ๋‘๋ฒˆ์งธ๋กœ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ child element์— key๋ฅผ ์ด์šฉํ•ด ๋ฐ”๋€Œ์ง€ ์•Š์„ ๊ณณ์„ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ์ด ๋‘๊ฐ€์ง€ ๊ฐ€์ •์„ ํ†ตํ•ด์„œ reconcilation์€ O(n)์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ–๊ฒŒ ๋œ๋‹ค.

๊ฐ๊ฐ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์ •๋ฆฌํ•ด๋ณด์ž

Elements Of Different Types

๋จผ์ € element์˜ tag ์ž์ฒด๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค๋ฉด, ์˜ˆ๋ฅผ ๋“ค๋ฉด <a> ์—์„œ <button>์œผ๋กœ ๋ฐ”๋€Œ์—ˆ๋‹ค๊ณ  ํ•˜๋ฉด ์ž์‹์„ ๋” ์ด์ƒ ๋น„๊ตํ•˜์ง€ ์•Š๊ณ  ๊ฑฐ๊ธฐ์„œ ๋ฐ”๋กœ ์ƒˆ๋กœ์šด DOM ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์•„๋ž˜ ์ž์‹ ์š”์†Œ๋“ค์ด ์—…๋ฐ์ดํŠธ๋œ๋‹ค. ์ด๋•Œ tag๋Š” ๊ฐ™์ง€๋งŒ className๊ณผ ๊ฐ™์€ attribute๊ฐ€ ๋‹ฌ๋ผ์งˆ ๊ฒฝ์šฐ์—๋Š” DOM์š”์†Œ๋Š” ๊ทธ๋Œ€๋กœ ๋‘๊ณ  attribute๋งŒ ๋ฐ”๊ฟ” ๋ฐ˜์˜ํ•œ๋‹ค.

Key

key๋ฅผ ์ •ํ•ด์ฃผ์–ด์•ผ ํ• ๋•Œ๋Š” ๋ณดํ†ต ๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ mappingํ•ด์ค„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ์ด๋•Œ key๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฆฌ์•กํŠธ๋Š” error๋ฅผ ๋˜์ง„๋‹ค. ๊ทธ ์ด์œ ๋Š” ๊ฐ™์€ tag๊ฐ€ ๋ฐ˜๋ณต๋˜๋Š” ์ƒํ™ฉ์—์„œ ์ˆœ์„œ๋งŒ์„ ์ด์šฉํ•˜๊ฒŒ ๋˜๋ฉด DOM์š”์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ ์ „์ฒด๋ฅผ ๋‹ค ๋ณ€๊ฒฝํ•ด์•ผํ•˜๋Š” ๋ถˆํ•„์š”ํ•œ ๋น„์šฉ์ด ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

// DOM
<ul>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

// VDOM
<ul>
  <li>Connecticut</li>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

์œ„ ์ฝ”๋“œ์™€ ๊ฐ™์€ ๊ฒฝ์šฐ react๋Š” ์ˆœ์„œ๋งŒ์œผ๋กœ ๋น„๊ตํ•ด ๋ชจ๋“  ์š”์†Œ๊ฐ€ ๋‹ค ๋ฐ”๋€Œ์—ˆ๋‹ค๊ณ  ์ดํ•ดํ•˜๊ณ  ์ „์ฒด๋ฅผ ๋‹ค ์ƒˆ๋กญ๊ฒŒ DOM์š”์†Œ๋ฅผ ๋งŒ๋“ ๋‹ค. ์ด์ ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ key๋ฅผ ์ด์šฉํ•œ๋‹ค๋ฉด ๋‚ด๋ถ€ ์ˆœ์„œ์™€๋Š” ์ƒ๊ด€์—†์ด key๊ฐ’์ด ๋ฐ”๋€ ์š”์†Œ๋งŒ ์ฐพ์•„์„œ DOM์„ ์—…๋ฐ์ดํŠธํ•ด ์ตœ์ ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๊ณ ์œ ํ•œ ๊ฐ’์œผ๋กœ key๋ฅผ ์ •ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋ฉฐ key๋กœ index๋ฅผ ์ง์ ‘ ๋„˜๊ธฐ๋ฉด ์•ˆ๋œ๋‹ค๋Š” ๊ฒƒ์ด ์ดํ•ด๊ฐ€ ๋˜์—ˆ๋‹ค.

<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

๐Ÿ˜ฒ Reconcilation ํ”ผํ•˜๊ธฐ

๋ฆฌ์•กํŠธ์˜ ๊ธฐ๋ณธ์›๋ฆฌ๋Š” ์ƒํƒœ์™€ props๊ฐ€ ๋ฐ”๋€Œ๋ฉด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ๋žœ๋”๋งํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์•ž์„œ ์ •๋ฆฌํ•œ ๋‚ด์šฉ๋“ค์€ ์ด๋Ÿฌํ•œ ๋ณ€ํ™”๋กœ V-DOM๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ V-DOM๊ณผ ์‹ค์ œ DOM์„ ์–ด๋–ป๊ฒŒ ๋น„๊ตํ•ด์„œ ๋ฐ˜์˜ํ•˜๋ƒ์— ๊ด€ํ•œ ๊ฒƒ์ด์—ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ์ตœ์ ํ™”ํ•ด์„œ ๋ฆฌ๋žœ๋”๋ง์„ ํ•œ๋‹คํ•ด๋„ ๋ฆฌ๋žœ๋”๋ง ์ž์ฒด๋Š” ๋น„์šฉ์ด ๋“œ๋Š” ์ž‘์—…์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด์˜ UI์ž์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•ด, ๋ฆฌ๋žœ๋”๋ง ์ž์ฒด๋ฅผ ์ค„์—ฌ์ค„ ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ๋œ๋‹ค.

๊ธฐ์กด์˜ UI๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ง€๋ฅผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์„ฑ๋Šฅ์„ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฆฌ์•กํŠธ๋Š” React.Memo์™€ useCallback,useMemo API๋ฅผ ์ง€์›ํ•œ๋‹ค.

React.Memo

๋ฆฌ์•กํŠธ์˜ ๊ธฐ๋ณธ ์›๋ฆฌ์— ๋”ฐ๋ผ์„œ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์™€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ชจ๋‘ ๋ฆฌ๋žœ๋”๋ง์„ ํ•ด์•ผ ํ•˜์ง€๋งŒ, ์ž์‹ ์š”์†Œ ์ค‘์—์„œ ์ „๋‹ฌ๋ฐ›์€ props๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š์•„์„œ UI๋ฅผ ๋ณ€ํ™”ํ•˜์ง€ ์•Š์•„๋„ ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์กด์žฌํ•œ๋‹ค. ์ด๋Ÿด ๋•Œ๋Š” ์ด์ „ UI๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ธ๋ฐ ์ด๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด React.Memo์ด๋‹ค.

import { memo } from "react"

function SomeComponent(props) {
  // ...
}

const MemoizedComponent = memo(SomeComponent)

React.memo๋Š” ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ๋Š” HOC (Higher Order Component)๋กœ ์ปดํฌ๋„ŒํŠธ์˜ ์ด์ „ props์™€ state ๋ณ€ํ™”๋กœ ์‚ฌ์šฉ๋  props ๋น„๊ตํ•ด์„œ ์ฐจ์ด๊ฐ€ ์žˆ์„ ๋•Œ์—๋งŒ ๋ฆฌ๋žœ๋”๋ง์„ ํ•˜๊ฒŒํ•œ๋‹ค.์ด๋•Œ ์ค‘์š”ํ•œ ๊ฒƒ์€ props๋ฅผ ๋น„๊ตํ•˜๋Š” ๋ฐฉ์‹์ธ๋ฐ ์–•์€ ๋น„๊ต๋ฅผ ํ†ตํ•ด ๋น„๊ตํ•œ๋‹ค.

์–•์€ ๋น„๊ต์™€ ๋ถˆ๋ณ€์„ฑ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋น„๊ต๋Š” ๋ฐ์ดํ„ฐ์˜ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์ด์šฉํ•ด ์ผ์น˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•œ๋‹ค. ์›์‹œํ˜•์˜ ๊ฒฝ์šฐ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์ƒˆ๋กœ์šด ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ์— ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ ์ž์ฒด๋กœ ๋น„๊ตํ•ด๋„ ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ๊ฐ์ฒด ํƒ€์ž…์€ ํ•ด๋‹น ๊ฐ์ฒด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ํ•˜๊ณ  ์žˆ๋Š” ์ฐธ์กฐ๊ฐ’์„ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ์— ํ• ๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋€Œ์–ด๋„ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๊ฐ€ ๋™์ผํ•ด, ์ฃผ์†Œ๊ฐ’๋งŒ์„ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‚ด๋ถ€ ๊ฐ’์ด ๋ณ€ํ–ˆ๋Š”์ง€ ์ผ์ผ์ด ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ์•กํŠธ์—์„œ๋Š” ๋น„๊ต์˜ ํŽธ์˜๋ฅผ ์œ„ํ•ด์„œ ๊ฐ์ฒด์˜ ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค๋Š” ๋ฐฉ์‹์„ ์ด์šฉํ•œ๋‹ค. ๊ฐ์ฒด์˜ ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค๊ฒŒ ๋˜๋ฉด ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋€Œ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋กœ ๋ฐ”๊พธ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์›์‹œํ˜• ํƒ€์ž…๊ณผ ๊ฐ™์ด ์ฃผ์†Œ๊ฐ’๋งŒ์œผ๋กœ๋„ ๋น„๊ต๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ž˜์„œ ๋ฆฌ์•กํŠธ์—์„œ ๊ฐ์ฒด์ƒํƒœ๋ฅผ ๋ณ€ํ™” ์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ๋Š” state๋ฅผ ์ง์ ‘ mutateํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, setState๋ฅผ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์„ ์ด์šฉํ•œ ๋ฐฉ์‹์œผ๋กœ ์ƒํƒœ๋ณ€ํ™”๋ฅผ ํ•œ๋‹ค. ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์€ key๋กœ ์ „๋‹ฌ๋œ ๊ฐ’์€ ๊ฐ™์ง€๋งŒ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ๊ฐ์ฒด๋Š” ์ƒˆ๋กญ๊ฒŒ ํ• ๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ์•กํŠธ์—๊ฒŒ ์ƒํƒœ๋ณ€ํ™”๋ฅผ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๊ณ , ์ž์‹์œผ๋กœ ๊ฐ’์„ ์ „๋‹ฌํ–ˆ์„ ๋•Œ ๋ฐ”๋€ ๋ถ€๋ถ„๋งŒ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

props ์ž์ฒด๋Š” ๋งค๋ฒˆ ๋žœ๋”๋ง์— ๋”ฐ๋ผ ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค์–ด์ ธ ๋น„๊ต๊ฐ€ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค. ๋น„๊ต๋ฅผ ์œ„ํ•ด์„œ๋Š” props ๋‚ด๋ถ€์˜ key๋ฅผ ๋Œ๋ฉด์„œ ๋น„๊ต๋ฅผ ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ๊ฐ’๋“ค ์ค‘์—์„œ ํ•˜๋‚˜๋ผ๋„ false๊ฐ€ ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค๋ฉด ๋ฆฌ๋žœ๋”๋ง์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ํŒ๋‹จํ•˜๊ณ  ๋ฆฌ๋žœ๋”๋ง์„ ํ•œ๋‹ค.

compare
compare

useCallback๊ณผ useMemo

React.Memo๋Š” ์ปดํฌ๋„ŒํŠธ ์ž์ฒด์˜ props๋ฅผ ์ด์šฉํ•ด์„œ ๋ฆฌ๋žœ๋”๋ง์„ ํ•ด์•ผํ•  ์ง€๋ฅผ ๊ณ ๋ฏผํ•œ๋‹ค๋ฉด, ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด๋‘๊ณ  ๋ถˆํ•„์š”ํ•œ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ง‰์•„ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ, useCallback๊ณผ useMemo๊ฐ€ ์žˆ๋‹ค.

ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋Š” ๋งค ๋ฆฌ๋žœ๋”๋ง๋•Œ๋งˆ๋‹ค ์ƒˆ๋กญ๊ฒŒ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ทธ๋•Œ๋งˆ๋‹ค ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜๊ฐ€ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑ๋˜๋Š” ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค. ๋งŒ์•ฝ์— ์ด ๋ณ€์ˆ˜๋“ค๊ณผ ํ•จ์ˆ˜๊ฐ€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌ๋œ๋‹ค๋ฉด React.Memo๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ๋”๋ผ๋„ ์ „๋‹ฌ๋˜๋Š” ๊ฐ’์ด ๊ณ„์†ํ•ด์„œ ์ƒˆ๋กœ์šด ๊ฐ’์œผ๋กœ ์ „๋‹ฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐ๊ตญ React.Memo๋กœ ๊ฐ์‹ธ์ง„ ์ปดํฌ๋„ŒํŠธ๋„ ๋ฆฌ๋žœ๋”๋ง์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

useMemo(callbackFunction, deps)

useMemo๋Š” ๊ฐ’์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์„ ์ €์žฅํ•˜๊ฒŒ ๋˜๊ณ , deps๋กœ ์ „๋‹ฌ๋œ ๊ฐ’์ด ๋ณ€ํ•  ๋•Œ๋งŒ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑํ•œ๋‹ค.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])

useCallback(callbackFunction, deps)

useCallback์€ useMemo๋กœ ์ €์žฅํ•˜๋˜ ํ•จ์ˆ˜๋ฅผ ์ข€ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” api๋กœ, useMemo์™€ ๋™์ผํ•˜๊ฒŒ deps๋กœ ์ „๋‹ฌ๋œ ๊ฐ’์ด ๋ณ€ํ•  ๋•Œ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑ๋œ๋‹ค.

const memorizedFunction = useMemo(() => () => console.log("Hello World"), [])

const memorizedFunction = useCallback(() => console.log("Hello World"), [])
@choi2021
๋งค์ผ์˜ ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ๊ธฐ๋กํ•˜๋Š” ๊ฐœ๋ฐœ์ผ์ง€์ž…๋‹ˆ๋‹ค.