all is well!!

1. React ๋™์ž‘๋ฐฉ์‹๊ณผ ๋‹ค์–‘ํ•œ hook ๋ณธ๋ฌธ

Javascript ๊ณต๋ถ€

1. React ๋™์ž‘๋ฐฉ์‹๊ณผ ๋‹ค์–‘ํ•œ hook

tnqlscho 95 2024. 7. 7. 20:52

๐Ÿ‘€  ๋ชฉํ‘œ

1. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ์ œ ๋ฆฌ๋ Œ๋”๋ง ๋˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ธฐ

2. ๋‹ค์–‘ํ•œ ํ›…์„ ์ดํ•ดํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ

 

๐Ÿ‘€  React์˜ ๋ Œ๋”๋ง ๋ผ์ดํ”„ ์‚ฌ์ดํด

๐ŸŸฃ 1. Trigger

๋‹จ์–ด ๊ทธ๋Œ€๋กœ ๋ Œ๋”๋ง์„ ์‹œ์ž‘ํ•˜๊ฒŒ๋” ๋ฐฉ์•„์‡ ๋ฅผ ๋‹น๊ธฐ๋Š” ๊ณผ์ •.

 

์–ธ์ œ Trigger๊ฐ€ ๋ฐœ๋™๋˜๋‚˜์š”?

1. ์ฒซ๋ฒˆ์งธ ๋ Œ๋”๋ง์ด ์ˆ˜ํ–‰๋ ๋•Œ

a. ReactDOM.createRoot(..).render()

2. ์ปดํฌ๋„ŒํŠธ์˜ state๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ

a. ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ setState ๋ฉ”์„œ๋“œ

b. useState, useReducer๋“ฑ ์ƒํƒœ๋ณ€๊ฒฝ ํ›…์˜ setter ํ•จ์ˆ˜ ํ˜ธ์ถœ.

 

1. ๋ Œ๋”๋ง Batch ์ฒ˜๋ฆฌ

Trigger ๊ณผ์ •์—์„œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ž‘์—…์„ ํ•œ๋ฒˆ์— ๋ฌถ์–ด์„œ ์ˆ˜ํ–‰ํ•˜๋Š” Batch ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค.

function Component() {
	const [count, setCount] = useState(0);
	const increase = () => {
		// trigger ํ•จ์ˆ˜๊ฐ€ ๋‘๋ฒˆ ํ˜ธ์ถœ๋˜์—ˆ์„๋•Œ
		setCount(count + 1);
		setCount(count + 2);
	};

	// ๋‘๋ฒˆ ํ˜ธ์ถœ ๋ ๊นŒ์š”?
	console.log('rendered');

	return (
		<>
			<div>{count}</div>
			<button onClick={increase}>Increase</button>
		</>
	)
}

์ •๋‹ต์€ ์•„๋‹ˆ์˜ค!

์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด์„œ ๋ Œ๋”๋ง์€ ๋งˆ์ง€๋ง‰์— ์ง€์ •๋œ true ๊ฐ’์ด ๋œฐ๋•Œ๊นŒ์ง€ ๋ชจ๋“  ์ƒํƒœ๋ณ€ํ™”๋ฅผ ์ง€์—ฐ์‹คํ–‰์‹œ์ผœ ํ•œ๋ฒˆ์— ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

๊ทธ๋ž˜์„œ ์ฝ˜์†”๋„ ํ•œ๋ฒˆ๋งŒ ์ฐํžŒ๋‹ค.

 

๋น„๋™๊ธฐ ๋ Œ๋”๋ง๋„ ์˜ˆ์ „์—๋Š” Batch ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์ง€ ์•Š์•˜์ง€๋งŒ Fiber Architecture๊ฐ€ ๋„์ž…๋˜๋ฉด์„œ ๋น„๋™๊ธฐ ์ฝœ๋ฐฑ์—์„œ๋„ Batch ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์กŒ๋‹ค.


 

๐ŸŸฃ 2. Render

์–ด๋–ค ๋ถ€๋ถ„์„ ์–ด๋–ป๊ฒŒ ์—…๋ฐ์ดํŠธ ํ•ด์•ผํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋‹จ๊ณ„

 

1. Virtual DOM

๋ณดํ†ต JS ์—ฐ์‚ฐ๋ณด๋‹ค DOM์—ฐ์‚ฐ ๋น„์šฉ์ด ๋” ํฌ๊ธฐ๋•Œ๋ฌธ์— ์‹ค์ œ DOM์„ ๊ฑด๋“œ๋Š”๊ฒŒ ์•„๋‹Œ Virtual DOM(DOM์„ ๋ชจ๋ฐฉํ•œ JS ๊ฐ์ฒด)์œผ๋กœ ์—ฐ์‚ฐ์„ ๋งˆ์น˜๊ณ  DOM์—๋Š” ๊ฒฐ๊ณผ๋งŒ ๋ฐ˜์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค.

React์—๋Š” Virtual DOM์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ React Element, Fiber, VDOM ๊ฐœ๋…์„ ์‚ฌ์šฉํ•œ๋‹ค.

 

 

2. React Element

HTML ๊ตฌ์กฐ์ฒด๋กœ Virtual DOM์„ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์„ ์ข€ ๋” ํŽธํ•œ ๋ฌธ๋ฒ•์œผ๋กœ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ JSX ๋ฌธ๋ฒ•๊ณผ ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

return (
	<div>
		<div>{count}</div>
		<button onClick={increase}>Increase</button>
	</div>
)

์ด๋ ‡๊ฒŒ ์ž‘์„ฑ๋œ JSX ๋ฌธ๋ฒ•์€

return React.createElement(
	'div',
	null,
	React.createElement('div', null, count),
	React.createElement('button', { ... }, 'Increase'),
);

์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ํ†ตํ•ด ์ด๋Ÿฐ ์ฝ”๋“œ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

์ด๋Ÿฐ React Element ๊ฐ์ฒด๋Š” ๋ถˆ๋ณ€(Immutable)ํ•˜๋‹ค.

 

 

3. Fiber

๋ Œ๋”๋ง์„ ์—ฌ๋Ÿฌ ์กฐ๊ฐ์œผ๋กœ ์ชผ๊ฐœ์„œ DOM ๋ณ€๊ฒฝ ์š”์†Œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜.

Fiber๋กœ ์ธํ•ด ๋น„๋™๊ธฐ ๋ Œ๋”๋ง์˜ ํ•ต์‹ฌ์ธ ๋ Œ๋”๋ง ์ž‘์—…์„ ์ค‘์ง€ํ•˜๊ณ  ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค.

๋ Œ๋”๋ง ๋‹จ์œ„๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

child์™€ sibling์„ ์ฐธ์กฐ๊ฐ’์œผ๋กœ ๋‹ค์Œ์œผ๋กœ ํ•ด์•ผํ•  ๋ Œ๋”๋ง ์ž‘์—…์ธ ๋‹ค์Œ Fiber์„ ๊ฐ€๋ฅดํ‚ค๋Š” ๊ทธ๋ž˜ํ”„ ๊ตฌ์กฐ๋กœ ๋˜์–ด์žˆ๋‹ค.

function Component() {
	const [count, setCount] = useState(0);
	const increase = () => setCount(count => count + 1);

	return (
		<div>
			<div>{count}</div>
			<button onClick={increase}>Increase</button>
		</div>
	)
}

 

scheduleWork(fiber, expireTime)

{
// ์ž‘์—… ์ค‘์ธ props (props๊ฐ€ ์—†์Œ)
  pendingProps: null,
// Render Phase ๋๋‚œ ๋’ค์˜ Props (props๊ฐ€ ์—†์Œ)
	memoizedProps: null,
// count 0 ์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊น๋‹ˆ๋‹ค. 
// ์‹ค์ œ DOM์— ์ปค๋ฐ‹๋˜์–ด์•ผ ํ•˜๋Š”๋ฐ WORK๋“ค์ด ์Šค์ผ€์ค„๋ง๋˜๋Š” update์— ๋Œ€ํ•œ ์ •๋ณด๋„ ํ๋กœ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  memoizedState: {
		baseState: { count: 0 },
		next: null, // hook ์ด ์ถ”๊ฐ€์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉด LinkedIn ๋ฐฉ์‹์œผ๋กœ hook ์ •๋ณด๊ฐ€ ๋‹ด๊น๋‹ˆ๋‹ค.
	},
	...
}

์ƒ์„ฑ๋œ Fiber์€ DOM์— ๋ฐ˜์˜๋˜๊ธฐ ์œ„ํ•ด์„œ ์Šค์ผ€์ค„๋ง ๋œ๋‹ค.

 

 

4. React Virtual DOM

๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ Fiber ๋…ธ๋“œ์˜ ํŠธ๋ฆฌ ์ž๋ฃŒ๊ตฌ์กฐ.

virtual dom์—๋Š” ํ˜„์žฌ ์ƒํƒœ์™€ ๋‹ค์Œ ์ƒํƒœ๋ฅผ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‘๊ฐœ์˜ ํŠธ๋ฆฌ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.

current tree๋Š” ํ˜„์žฌ ์ƒํƒœ์˜ ํŠธ๋ฆฌ, workInProgress๋Š” ํ˜„์žฌ ์ž‘์—…์œผ๋กœ ์ธํ•ด ๋ฐ”๋€Œ๋Š” ํŠธ๋ฆฌ๋‹ค.

(์‰ฝ๊ฒŒ current tree์˜ ์ฐธ์กฐ์ฃผ์†Œ๋ฅผ working tree์— ๋ฎ์–ด์”Œ์›Œ์„œ ์—…๋ฐ์ดํŠธ ํ•˜๋Š”๊ฒƒ์œผ๋กœ ์ดํ•ดํ–ˆ๋‹ค.)

 

๋‚˜๋Š” ์ด๋•Œ๊นŒ์ง€ virtual dom์œผ๋กœ ์ธํ•ด ๋กœ๋”ฉ ์†๋„๊ฐ€ ๋น ๋ฅด๋‹ค๊ณ  ์•Œ๊ณ ์žˆ๋Š” ์ƒํƒœ์˜€๋‹ค.

๊ทธ๋ž˜์„œ virtual dom์ด react์˜ ์†์— ๊ผฝ๋Š” ์žฅ์ ์ด๋ผ๊ณ ๋งŒ ์•Œ๊ณ ์žˆ์—ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ๋‹จ์ ๋„ ์กด์žฌํ–ˆ๋‹ค.

์—ฐ์‚ฐ ๋น„์šฉ์ด ํฐ DOM์„ ์ง์ ‘ ์กฐ์ž‘ํ•˜์ง€ ์•Š์•„์„œ ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•˜๋Š” ์šฉ๋„๋กœ ์“ฐ์˜€์ง€๋งŒ

์• ์ดˆ์— virtual dom์„ ๊ด€๋ฆฌํ•˜๋Š”๊ฒŒ ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ์™€ CPU ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

(์ด๋ฒˆ์— ๊ณต๋ถ€ํ•˜๋ฉด์„œ react ๊ณต์‹ ๋ฌธ์„œ์—์„œ virtual dom์ด๋ผ๋Š” ์šฉ์–ด๊ฐ€ ์ œ๊ฑฐ๋˜์—ˆ๋‹ค๋Š” ์†Œ์‹์„ ๋“ค์—ˆ๋‹ค.)

 

 

5. ์žฌ์กฐ์ •(Reconciliation)๊ณผ diff(Diffing) ์•Œ๊ณ ๋ฆฌ์ฆ˜

์žฌ์กฐ์ • : DOM ํŠธ๋ฆฌ์— ์—…๋ฐ์ดํŠธ ํ•ด์•ผํ•˜๋Š” ๋‚ด์šฉ์„ ์ด์ „ ํŠธ๋ฆฌ์™€ ๋น„๊ตํ•ด ๊ณ„์‚ฐํ•˜๊ณ  ํŒŒ์•…ํ•˜๋Š” ๊ณผ์ •

 

๋ณดํ†ต ๋‘๊ฐœ์˜ ํŠธ๋ฆฌ๋ฅผ ๋น„๊ตํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ตœ์†Œ O(n^3)์˜ ์ˆœํšŒ๋น„์šฉ์ด ๋ฐœ์ƒํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

React์—์„œ๋Š” ์œ„์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด key ๊ฐ’์„ ์ด์šฉํ•œ Heuristics ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•ด์„œ O(n)๊นŒ์ง€ ์ค„์ด๋Š”๋ฐ ์„ฑ๊ณตํ–ˆ๋‹ค.


 

๐ŸŸฃ 3. Commit

์žฌ์กฐ์ •(Reconciliation) ํ”„๋กœ์„ธ์Šค์˜ ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„๋กœ ๋ณ€ํ™”๋œ ๋ถ€๋ถ„์„ DOM์— ๋ฐ˜์˜ํ•œ๋‹ค.

์ด ๋‹จ๊ณ„์—์„œ๋Š” ๋ณดํ†ต ์•„๋ž˜์˜ ์ž‘์—…๋“ค์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

1. pre-commit phase

๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํ™•์ •ํ•˜๊ธฐ ์ „ ์ž‘์—… ์ค€๋น„.

์ฃผ๋กœ ๋ ˆ์ด์•„์›ƒ ํšจ๊ณผ(useLayoutEffect)๊ฐ€ ์˜ˆ์•ฝ๋œ๋‹ค.

 

2. commit phase

DOM ์—…๋ฐ์ดํŠธ 

DOM ์†์„ฑ ๋ฐ ์Šคํƒ€์ผ ์—…๋ฐ์ดํŠธ

Ref ์—…๋ฐ์ดํŠธ : DOM ์š”์†Œ์— ์ง์ ‘ ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ด ๋‹จ๊ณ„์—์„œ ์—…๋ฐ์ดํŠธ ๋œ๋‹ค.

๋ ˆ์ด์•„์›ƒ ํšจ๊ณผ(useLayoutEffect) ์‹คํ–‰

 

3. post-commit phase

Effects ์—…๋ฐ์ดํŠธ : ์‚ฌ์ด๋“œ์ดํŽ™ํŠธ ํ›…์ด ์‹คํ–‰๋œ๋‹ค.

๋น„๋™๊ธฐ ์ž‘์—… ์‹คํ–‰

 


 

๐Ÿ‘€  React์˜ ์—ฌ๋Ÿฌ๊ฐ€์ง€ hook

๐ŸŸฃ useState

export default function UseStateTest() {
  const [state, setState] = useState({ bar: { count: 1 } });
  const increment = () => {

    setState((prev)=>({
      ...prev, // useState๋Š” ๋ถˆ๋ณ€ํ•จ์„ ์ง€์ผœ์ฃผ๋Š” ํ˜•ํƒœ๋กœ ๊ฐ’์„ ๋ฐ”๊ฟ”์•ผ ๋ Œ๋”๋ง trigger์˜ ์กฐ๊ฑด์ด ์ง€์ผœ์ง„๋‹ค.
      bar:{
        ...prev.bar,
        count: prev.bar.count+1
      }
    }))
  }

  return (
    <div>
      count: {state.bar.count}
      <button onClick={increment}>์ฆ๊ฐ€</button>
    </div>
  );
}

 

๐ŸŸฃ useMemo

import { useMemo, useState } from "react";
import { repeatBarked, repeatMeow } from "./UseMemoTest.utils.ts";

export default function UseMemoTest() {
  const [meowCount, setMeowCount] = useState(1);
  const [barkedCount, setBarkedCount] = useState(1);

  // useMemo๋Š” ์˜์กด์„ฑ ๋ฐฐ์—ด์˜ ๊ฐ’์ด ์—…๋ฐ์ดํŠธ ๋ ๋•Œ๊นŒ์ง€ ์ด๋ฏธ ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ์บ์‹ฑํ•œ๋‹ค.
  const meow = useMemo(()=>repeatMeow(meowCount),[meowCount]) 
  const bark = useMemo(()=>repeatBarked(barkedCount),[barkedCount])

  return (
    <div>
      <p data-testid="cat">๊ณ ์–‘์ด "{meow}"</p>
      <p data-testid="dog">๊ฐ•์•„์ง€ "{bark}"</p>
      <button data-testid="meow" onClick={() => setMeowCount(n => n + 1)}>์•ผ์˜น</button>
      <button data-testid="bark" onClick={() => setBarkedCount(n => n + 1)}>๋ฉ๋ฉ</button>
    </div>
  );
}

 

๐ŸŸฃ pureComponent

import { memo, useState } from "react";
import { Cat, Dog } from "./PureComponentTest.components.tsx";

// memo๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์บ์‹ฑํ•ด์„œ ๋™์ผํ•œ props๋กœ ์—ฌ๋Ÿฌ๋ฒˆ ๋ Œ๋”๋ง ๋˜๋Š”๊ฒƒ์„ ๋ฐฉ์ง€ํ•œ๋‹ค.
// memo๋ฅผ ๊ฑธ์ง€์•Š์œผ๋ฉด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋˜๋ฉด ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋„ ์ „๋ถ€ ๋ Œ๋”๋ง๋˜๊ธฐ ๋•Œ๋ฌธ์—
// memo๋ฅผ ๊ฑธ์–ด์„œ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋˜์–ด๋„ ๋™์ผํ•œ props์ธ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ Œ๋”๋ง๋˜์ง€ ์•Š๊ฒŒ ๋ง‰๋Š”๋‹ค.
const MemoCat = memo(Cat);
const MemoDog = memo(Dog);

export default function PureComponentTest() {
  const [meowCount, setMeowCount] = useState(1);
  const [barkedCount, setBarkedCount] = useState(1);

  return (
    <div>
      props์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ๋ Œ๋”๋ง์ด ๋ฐœ์ƒ
      <MemoCat crying={meowCount}/>
      <MemoDog crying={barkedCount}/>
      <button data-testid="meow" onClick={() => setMeowCount(n => n + 1)}>์•ผ์˜น</button>
      <button data-testid="bark" onClick={() => setBarkedCount(n => n + 1)}>๋ฉ๋ฉ</button>
    </div>
  );
}

 

๐ŸŸฃ useCallback

import { ComponentProps, PropsWithChildren, memo, useCallback, useMemo, useState } from "react";
import { BarkButton, MeowButton } from "./UseCallbackTest.components.tsx";

// pureComponent์™€ useCallback์„ ์‚ฌ์šฉํ•ด์„œ ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ๋ง‰๋Š”๋‹ค.
const PureComponent = memo(({ children, ...props }: PropsWithChildren<ComponentProps<'p'>>) => {
  return <p {...props}>{children}</p>
})

export default function UseCallbackTest() {
  const [meowCount, setMeowCount] = useState(0);
  const [barkedCount, setBarkedCount] = useState(0);

  const callbackMeowCount = useCallback(
    ()=>{setMeowCount(n => n + 1)},[setMeowCount]
  )
    
  const callbackBarkCount = useCallback(
    ()=>{setBarkedCount(n => n + 1)},[setBarkedCount]
  )

  return (
    <div>
      <PureComponent data-testid='cat'>meowCount {meowCount}</PureComponent>
      <PureComponent data-testid='dog'>barkedCount {barkedCount}</PureComponent>
      <MeowButton onClick={callbackMeowCount}/>
      <BarkButton onClick={callbackBarkCount}/>
    </div>
  );
}

 

๐ŸŸฃ RequireRefactoring

// useMemo, useCallback ๋“ฑ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

import { ComponentProps, memo, PropsWithChildren } from "react";

type Props = {
  countRendering?: () => void;
}

// React๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ์–•์€ ๋น„๊ต๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด์˜ ์ฐธ์กฐ ์ฃผ์†Œ๋ฅผ ๋น„๊ตํ•œ๋‹ค.
// ๊ทธ ์ค‘ memo๋Š” props๊ฐ€ ๋ณ€๊ฒฝ๋ ๋•Œ๋งˆ๋‹ค ์–•์€ ๋น„๊ต๋ฅผ ํ•œ๋‹ค.
// ๊ทธ๋ž˜์„œ ์ฐธ์กฐ ํƒ€์ž…์˜ ๊ฒฝ์šฐ ์ฃผ์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด props๊ฐ€ ๋ณ€๊ฒฝ๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ.
// ๊ทธ๋ž˜์„œ PureComponent๊ฐ€ memo๋ฅผ ์ผ์ง€๋งŒ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ฐ์ฒด์™€ ํ•จ์ˆ˜๋กœ props๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด ๊ฐ’์ด ๊ฐ™์•„๋„ ๋ฆฌ๋ Œ๋”๋ง์ด ๋œ๋‹ค.
const PureComponent = memo(({ children, countRendering, ...props }: PropsWithChildren<ComponentProps<'div'> & Props>) => {
  countRendering?.();
  return <div {...props}>{children}</div>
})

// eslint-disable-next-line @typescript-eslint/no-unused-vars
let outerCount = 1

// ์ปดํฌ๋„ŒํŠธ ๋ฐ–์— ์ •์˜ํ•œ ๊ฐ์ฒด๋‚˜ ํ•จ์ˆ˜๊ฐ™์€ ์ฐธ์กฐํƒ€์ž…์€ ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋ ๋•Œ ํ•œ๋ฒˆ ์ƒ์„ฑ๋˜์–ด์„œ
// ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ๋ฐ–์— ์ •์˜๋œ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด๋„ ์ฃผ์†Œ๊ฐ’์€ ๊ฐ™์€๊ณณ์„ ๋ฐ”๋ผ๋ณด๊ณ  ์žˆ๊ธฐ๋•Œ๋ฌธ์— ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
const style = { width: '100px', height: '100px' }
const onClick = () => {
  outerCount += 1;
}

export default function RequireRefactoring({ countRendering }: Props) {

  return (
    <PureComponent
      // ์ฒซ๋ฒˆ์งธ ๋ฌธ์ œ์ . ๊ฐ์ฒด๋กœ props๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ์•ˆ์˜ ๊ฐ์ฒด๋Š” ํ•ญ์ƒ ๊ฐ’์€ ๊ฐ™์•„๋„ ์ƒˆ๋กœ ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ์ฃผ์†Œ๊ฐ’์„ ๊ฐ€์ ธ์„œ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋กœ ๊ฐ„์ฃผํ•ด์„œ ๋ฆฌ๋ Œ๋”๋ง๋จ.
      style={style}
      // ๋‘๋ฒˆ์งธ ๋ฌธ์ œ์ . onClick์— ์ „๋‹ฌ๋œ ํ•จ์ˆ˜๋„ ์ฐธ์กฐํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด์šฉ์ด ๊ฐ™๋”๋ผ๋„ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋กœ ๊ฐ„์ฃผํ•ด์„œ ๋ฆฌ๋ Œ๋”๋ง๋จ.
      onClick={onClick}
      countRendering={countRendering}
    >
      test component
    </PureComponent>
  );
}

/** ๋‚ด๊ฐ€ ์ž˜๋ชป ์ƒ๊ฐํ•œ๊ฒƒ : ์™œ ์ปดํฌ๋„ŒํŠธ ์•ˆ์˜ ๊ฐ์ฒด๋Š” ๋‹ค๋ฅธ ์ฃผ์†Œ๊ฐ’์„ ๊ฐ€์ง€์ง€?? react์—์„œ ์ผ๋ถ€๋Ÿฌ ๋‹ค๋ฅธ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ ํ•ด์„œ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์˜ ๋ฆฌ๋ Œ๋”๋ง์„ ์ผ์œผํ‚ค๊ธฐ ์œ„ํ•œ๊ฑด๊ฐ€??
 * ์ปดํฌ๋„ŒํŠธ๋„ ๊ฒฐ๊ตญ ํ•˜๋‚˜์˜ ํ•จ์ˆ˜๋ผ๋Š”๊ฒƒ์„ ๊นœ๋นกํ•จ..ใ… 
 * ์ปดํฌ๋„ŒํŠธ๋Š” ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ํ˜ธ์ถœ๋ ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์‹คํ–‰์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
 * ๊ทธ๋ž˜์„œ ๋‚ด๋ถ€์˜ ๋ณ€์ˆ˜๋‚˜ ๊ฐ์ฒด๋„ ์ƒˆ๋กœ์šด ์‹คํ–‰์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ ์ƒˆ๋กœ ์ƒ์„ฑ๋œ๋‹ค.
 * ๊ทธ๋ž˜์„œ ๋™์ผํ•œ ์ฝ”๋“œ๋ผ๋„ ๋ฆฌ๋ Œ๋”๋งํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ์•ˆ์˜ ์ฐธ์กฐํƒ€์ž…๋“ค(๊ฐ์ฒด, ๋ฐฐ์—ด, ํ•จ์ˆ˜ ๋“ฑ)์€ ์ƒˆ๋กœ์šด ์ฃผ์†Œ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.
 */

 

๐ŸŸฃ useMyRef

import { useMemo } from "react"

export function useMyRef<T>(initValue: T | null) {

  const ref = useMemo(()=>{
    return { current: initValue };
  },[])

  return ref;
}

// ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ์˜ ์ฐธ์กฐํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š”๋‹ค.
// ๊ทธ๋Ÿผ ์ง€๊ธˆ ๋ฌธ์ œ๋Š” ๋ฆฌ๋ Œ๋”๋ง ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ๋•Œ๋งˆ๋‹ค ๊ณ„์† ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฑด๋ฐ,
// useMyRef๋Š” ํ•จ์ˆ˜. ํ•จ์ˆ˜๋Š” ์‹คํ–‰๋ ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์‹คํ–‰์ปจํ…์ŠคํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์—
// ๊ทธ ์•ˆ์˜ ๊ฐ์ฒด๋„ ๊ฐ™์€ ๊ฐ’์ด์—ฌ๋„ ์ƒˆ๋กœ์šด ์ฃผ์†Œ์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
// ๋ฆฌ๋ Œ๋”๋ง ๋ ๋•Œ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ํ›…๋“ค๋กœ ๋‹ค๋ฅธ ๋ฉ”๋ชจ๋ฆฌ๋กœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰์•„์•ผ ํ•˜๋‚˜..?

// useMemo๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ณ„์‚ฐ๋œ๊ฐ’์„ ์บ์‹ฑ์„ ํ•˜๊ธฐ๋•Œ๋ฌธ์— ์˜์กด์„ฑ ๋ฐฐ์—ด์˜ ๊ฐ’์ด ๋ฐ”๋€”๋•Œ๊นŒ์ง€ ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ์ฐธ์กฐ๋ฅผ ํ•œ๋‹ค.
// useRef๋Š” .current ๊ฐ’์„ ๋ฐ”๊ฟ”๋„ ํ•ญ์ƒ ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
// ์ด ์ปค์Šคํ…€ํ›…์—๋„ ๋™์ผํ•˜๊ฒŒ ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด์„œ ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ๋น„์šด๋‹ค.
// ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ๋น„์šฐ๋ฉด ๋‹ค์‹œ ๊ณ„์‚ฐํ•ด์•ผ๋  ๊ธฐ์ค€์ด ์—†๊ธฐ๋•Œ๋ฌธ์—
// ์ฒ˜์Œ ๋ Œ๋”๋ง ๋˜์—ˆ์„๋•Œ ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ์–ด๋–ค ๋ฉ”๋ชจ๋ฆฌ์— ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  ๊ทธ ๋’ค์—๋Š” ๋™์ผํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.
// ๊ทธ๋Ÿฌ๋ฉด ๊ฐ์ฒด๋‚ด๋ถ€์˜ ๊ฐ’์€ ๋ฐ”๋€Œ์–ด๋„ ๋™์ผํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฐธ์กฐํ•ด์„œ useRef์™€ ๋น„์Šทํ•˜์ง€ ์•Š์„๊นŒ...?

์ด๊ฑด ๋‚˜์˜ ํ’€์ด

import { useState } from "react";

export function useMyRef<T>(initValue: T | null) {
  // ์‚ฌ์‹ค ref๋„ state์˜ ํ•œ ์ข…๋ฅ˜์ž…๋‹ˆ๋‹ค. set์„ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ์–ธ์ œ๋‚˜ ๋™์ผํ•œ state๋กœ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
  const [ref] = useState<{ current: typeof initValue}>({ current: initValue });
  return ref
}

์ด๊ฑด ์ •๋‹ต..

 

๋‚˜๋Š” ๋™์ผํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฐธ์กฐํ•˜๋Š”๊ฒƒ์—๋งŒ ์ง‘์ค‘ํ–ˆ๋Š”๋ฐ ์ •๋‹ต์„ ๋ณด๊ณ  ์•„ํ•˜! ํ–ˆ๋‹คใ… 

ํ™”๋ฉด์— ๋ฐ”๋€ ๋‚ด์šฉ์„ ๋ณด์—ฌ์ฃผ๋ ค๋ฉด useState๋Š” ๋ฌด์กฐ๊ฑด ๋ถˆ๋ณ€์„ฑ์„ ์ง€์ผœ์•ผํ•œ๋‹ค!๋ฅผ ๋’ค์ง‘๋Š” ์ƒ๊ฐ์ด์—ˆ๋‹ค.

setter ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ƒํƒœ ๊ฐ์ฒด ์†์„ฑ์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•ด์„œ ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋™์ผํ•œ ์ฐธ์กฐ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

 


tmi...

3์ฃผ๋™์•ˆ ํ•œ๊ฑธ ์ •๋ฆฌํ•˜๋ฉด์„œ ๋ฉ˜ํ† ๋‹˜์˜ ํ”ผ๋“œ๋ฐฑ์„ ๋ณด๋Š”๋ฐ ๋‚˜์—๊ฒ ์•„์ง ํ—˜๋‚œํ•œ ๋‚œ์ด๋„(ใ… ใ… )๋กœ ์ธํ•ด

์ฒซ ์ฃผ๋งŒ ๋‚˜์˜ ์ƒ๊ฐ์„ ํ† ๋Œ€๋กœ ์ •๋ฆฌํ•ด์„œ ๊ณผ์ œ๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ์—ˆ๊ณ , ๊ทธ์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค..

ํ‘....ใ… ใ… ใ…  2,3์ฃผ์ฐจ ๋„ˆ๋ฌด ์–ด๋ ค์›Œ์š”๐Ÿ˜‡

 

 

Comments