๋ฉ”๋ชจ์ด์ œ์ด์…˜(์ˆ˜๋™ ๋˜๋Š” ์ž๋™)๊ณผ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ์— ๋Œ€ํ•ด ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.

์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค!

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

๊ทœ์น™ ์„ธ๋ถ€ ์‚ฌํ•ญ

์ผ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” React์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ํŒจํ„ด์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฆฐํ„ฐ๊ฐ€ ์•Œ๋ ค์ง„ ๋ชฉ๋ก์—์„œ ์ด๋Ÿฌํ•œ API์˜ ์‚ฌ์šฉ์„ ๊ฐ์ง€ํ•˜๋ฉด ์ด ๊ทœ์น™์— ๋”ฐ๋ผ ํ”Œ๋ž˜๊ทธ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” React ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์•ฑ์„ ์†์ƒ์‹œํ‚ค์ง€ ์•Š๊ธฐ ์œ„ํ•ด ์ด๋Ÿฌํ•œ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž๋™์œผ๋กœ ๊ฑด๋„ˆ๋›ธ ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

// ์ด๋Ÿฌํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋ฉ”๋ชจ์ด์ œ์ด์…˜์ด ๊นจ์ง€๋Š” ์˜ˆ์‹œ
function Form() {
const { watch } = useForm();

// โŒ 'name' ํ•„๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด๋„ ์ด ๊ฐ’์€ ์ ˆ๋Œ€ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
const name = useMemo(() => watch('name'), [watch]);

return <div>Name: {name}</div>; // UI๊ฐ€ "์–ผ์–ด๋ถ™์€" ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค
}

React ์ปดํŒŒ์ผ๋Ÿฌ๋Š” React ๊ทœ์น™์„ ๋”ฐ๋ผ ๊ฐ’์„ ์ž๋™์œผ๋กœ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜๋™ useMemo๋กœ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ์˜ ์ž๋™ ์ตœ์ ํ™”๋„ ๊นจ์ง‘๋‹ˆ๋‹ค. ์ด ๊ทœ์น™์€ ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ํŒจํ„ด์„ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ธฐ

React ๊ทœ์น™์„ ๋”ฐ๋ฅด๋Š” API ์„ค๊ณ„ํ•˜๊ธฐ

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ API๋‚˜ Hook์„ ์„ค๊ณ„ํ•  ๋•Œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์งˆ๋ฌธ ์ค‘ ํ•˜๋‚˜๋Š” API ํ˜ธ์ถœ์„ useMemo๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์ˆ˜๋™ ๋ฉ”๋ชจ์ด์ œ์ด์…˜๊ณผ React ์ปดํŒŒ์ผ๋Ÿฌ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ๋ชจ๋‘ ์‚ฌ์šฉ์ž์˜ ์ฝ”๋“œ๋ฅผ ์†์ƒ์‹œํ‚ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋Ÿฌํ•œ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ํŒจํ„ด ์ค‘ ํ•˜๋‚˜๋Š” โ€œ๋‚ด๋ถ€ ๊ฐ€๋ณ€์„ฑโ€์ž…๋‹ˆ๋‹ค. ๋‚ด๋ถ€ ๊ฐ€๋ณ€์„ฑ์€ ๊ฐ์ฒด๋‚˜ ํ•จ์ˆ˜๊ฐ€ ์ฐธ์กฐ๋Š” ๋™์ผํ•˜๊ฒŒ ์œ ์ง€๋˜์ง€๋งŒ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋˜๋Š” ์ž์ฒด ์ˆจ๊ฒจ์ง„ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€์—์„œ๋Š” ๋™์ผํ•ด ๋ณด์ด์ง€๋งŒ ๋‚ด์šฉ๋ฌผ์„ ์€๋ฐ€ํ•˜๊ฒŒ ์žฌ๋ฐฐ์น˜ํ•˜๋Š” ์ƒ์ž๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. React๋Š” ๋‹ค๋ฅธ ์ƒ์ž๋ฅผ ๋ฐ›์•˜๋Š”์ง€๋งŒ ํ™•์ธํ•˜๊ณ  ์•ˆ์— ๋ฌด์—‡์ด ๋“ค์–ด ์žˆ๋Š”์ง€๋Š” ํ™•์ธํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ฉ”๋ชจ์ด์ œ์ด์…˜์„ ๊นจ๋œจ๋ฆฌ๋Š”๋ฐ, React๋Š” ๊ฐ’์˜ ์ผ๋ถ€๊ฐ€ ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ ์™ธ๋ถ€ ๊ฐ์ฒด(๋˜๋Š” ํ•จ์ˆ˜)๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ์— ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

React API๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ์˜ ๊ฒฝํ—˜ ๋ฒ•์น™์œผ๋กœ, useMemo๊ฐ€ ์ด๋ฅผ ๊นจ๋œจ๋ฆด์ง€ ์ƒ๊ฐํ•ด๋ณด์„ธ์š”.

function Component() {
const { someFunction } = useLibrary();
// ์ด์™€ ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•˜๋Š” ๊ฒƒ์€ ํ•ญ์ƒ ์•ˆ์ „ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค
const result = useMemo(() => someFunction(), [someFunction]);
}

๋Œ€์‹ , ๋ถˆ๋ณ€ ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋ช…์‹œ์ ์ธ ์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” API๋ฅผ ์„ค๊ณ„ํ•˜์„ธ์š”.

// โœ… ์ข‹์€ ์˜ˆ์‹œ: ์—…๋ฐ์ดํŠธ๋  ๋•Œ ์ฐธ์กฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š” ๋ถˆ๋ณ€ ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜
function Component() {
const { field, updateField } = useLibrary();
// ์ด๊ฒƒ์€ ํ•ญ์ƒ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•˜๊ธฐ์— ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค
const greeting = useMemo(() => `Hello, ${field.name}!`, [field.name]);

return (
<div>
<input
value={field.name}
onChange={(e) => updateField('name', e.target.value)}
/>
<p>{greeting}</p>
</div>
);
}

์ž˜๋ชป๋œ ์˜ˆ์‹œ

์ด ๊ทœ์น™์— ๋Œ€ํ•œ ์ž˜๋ชป๋œ ์ฝ”๋“œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

// โŒ react-hook-form `watch`
function Component() {
const {watch} = useForm();
const value = watch('field'); // ๋‚ด๋ถ€ ๊ฐ€๋ณ€์„ฑ
return <div>{value}</div>;
}

// โŒ TanStack Table `useReactTable`
function Component({data}) {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
});
// table ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‚ด๋ถ€ ๊ฐ€๋ณ€์„ฑ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค
return <Table table={table} />;
}

์ฃผ์˜ํ•˜์„ธ์š”!

MobX

observer์™€ ๊ฐ™์€ MobX ํŒจํ„ด๋„ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ๊ฐ€์ •์„ ๊นจ๋œจ๋ฆฌ์ง€๋งŒ, ๋ฆฐํ„ฐ๋Š” ์•„์ง ์ด๋ฅผ ๊ฐ์ง€ํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. MobX์— ์˜์กดํ•˜๊ณ  ์žˆ๊ณ  React ์ปดํŒŒ์ผ๋Ÿฌ์—์„œ ์•ฑ์ด ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด "use no memo" ์ง€์‹œ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// โŒ MobX `observer`
const Component = observer(() => {
const [timer] = useState(() => new Timer());
return <span>๊ฒฝ๊ณผ๋œ ์‹œ๊ฐ„: {timer.secondsPassed}</span>;
});

์˜ฌ๋ฐ”๋ฅธ ์˜ˆ์‹œ

์ด ๊ทœ์น™์— ๋Œ€ํ•œ ์˜ฌ๋ฐ”๋ฅธ ์ฝ”๋“œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

// โœ… react-hook-form์˜ ๊ฒฝ์šฐ `useWatch`๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”
function Component() {
const {register, control} = useForm();
const watchedValue = useWatch({
control,
name: 'field'
});

return (
<>
<input {...register('field')} />
<div>ํ˜„์žฌ ๊ฐ’: {watchedValue}</div>
</>
);
}

์ผ๋ถ€ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์•„์ง React์˜ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ๋ชจ๋ธ๊ณผ ํ˜ธํ™˜๋˜๋Š” ๋Œ€์ฒด API๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฆฐํ„ฐ๊ฐ€ ์ด๋Ÿฌํ•œ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋‚˜ Hook์„ ์ž๋™์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ด์Šˆ๋ฅผ ์ œ์ถœํ•˜์—ฌ ๋ฆฐํ„ฐ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ์„ธ์š”.