useMemo vs useCallback vs React.memo

0

React

๋ชฉ๋ก ๋ณด๊ธฐ
4/4
post-thumbnail
post-custom-banner

๋ฆฌ์•กํŠธ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค๋ณด๋ฉด ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐ˜๋ณต๋˜๋Š” ๋“ฑ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„ฑ๋Šฅ ์ด์Šˆ๋ฅผ ๋งˆ์ฃผํ•˜๊ฒŒ ๋œ๋‹ค.

  1. ๊ตณ์ด ๋ Œ๋”๋ง๋  ํ•„์š” ์—†๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ โ€˜๋ฐ˜๋ณตโ€™์ ์œผ๋กœ ๋ฆฌ๋ Œ๋”๋ง ๋˜๋Š” ๊ฒฝ์šฐ
  2. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ๋งˆ๋‹ค ์“ธ๋ฐ์—†์ด ๋‚ด๋ถ€ ๋กœ์ง์ด ๋‹ค์‹œ ๋งŒ๋“ค์–ด์ง€๊ฑฐ๋‚˜ ๋ณต์žกํ•œ ๊ณ„์‚ฐ์ด โ€˜๋ฐ˜๋ณตโ€™๋˜๋Š” ๊ฒฝ์šฐ

์ด๋Ÿฌํ•œ ๋ถˆํ•„์š”ํ•œ ๋ฐ˜๋ณต๋“ค์„ ์ค„์ด๊ธฐ ์œ„ํ•ด์„œ โ€˜๊ฒฐ๊ณผ๋ฅผ ๊ธฐ์–ตโ€™ํ•ด๋‘๊ณ  ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ธ ๋ฉ”๋ชจ์ด์ œ์ด์…˜(Memoization)์„ ํ†ตํ•ด ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿค”ย ๋ฉ”๋ชจ์ด์ œ์ด์…˜(Memoization)์ด ๋ฌด์—‡์ธ๊ฐ€์š”?

๋ฉ”๋ชจ์ด์ œ์ด์…˜(Memoization)์ด๋ž€ ๋™์ผํ•œ ๊ณ„์‚ฐ์„ ๋ฐ˜๋ณตํ•ด์•ผ ํ•  ๋•Œ, ์ด์ „์— ๊ณ„์‚ฐํ•œ ๊ฐ’์„ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•ด ๋‘์—ˆ๋‹ค๊ฐ€ ๊บผ๋‚ด ์”€์œผ๋กœ์จ ์ค‘๋ณต ๊ณ„์‚ฐ์„ ์ œ๊ฑฐํ•˜์—ฌ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์†๋„๋ฅผ ๋น ๋ฅด๊ฒŒ ํ•˜๋Š” ๊ธฐ๋ฒ•์ด๋‹ค. ์บ์‹ฑ(caching)์ด๋ผ๋Š” ๋‹จ์–ด์™€ ๋น„์Šทํ•˜๋‹ค.

๋ฆฌ์•กํŠธ์—์„œ ๋ฉ”๋ชจ์ด์ œ์ด์…˜์„ ํ™œ์šฉํ•˜๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ React.memo, useMemo, useCallback ๋“ฑ์ด ์žˆ๋‹ค.

๐Ÿค”ย useMemo์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.

uesMemo๋Š” memoized๋œ โ€˜๊ฐ’โ€™์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ›… ํ•จ์ˆ˜๋กœ, fn ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ dependencies๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์บ์‹ฑํ•œ๋‹ค.

const cachedValue = useMemo(fn, dependencies)

๐Ÿค”ย useCallback์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.

useCallback์€ memoized๋œ โ€˜ํ•จ์ˆ˜โ€™๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ›… ํ•จ์ˆ˜๋กœ, ์ „๋‹ฌ๋œ fn ํ•จ์ˆ˜๋ฅผ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•˜์—ฌ ์บ์‹ฑํ•œ๋‹ค. dependencies์— ํฌํ•จ๋œ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์บ์‹ฑํ•ด๋‘” fn ํ•จ์ˆ˜์˜ ์ฐธ์กฐ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

const cachedFn = useCallback(fn, dependencies)

๐Ÿค”ย React.memo์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”.

React.memo๋Š” ์ปดํฌ๋„ŒํŠธ ์ž์ฒด๋ฅผ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•˜๋Š” ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ(HOC)๋‹ค.

import { memo } from 'react';

const MemoizedComponent = memo(SomeComponent, arePropsEqual?)

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋ž€, ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„์„œ ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งํ•œ๋‹ค.

๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ์ธ React.memo๋Š” ์ธ์ž๋กœ ๋ฐ›์€ ์ปดํฌ๋„ŒํŠธ์˜ props์˜ ๋ณ€ํ™”๋ฅผ ์ฒดํฌํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ ์ตœ์ ํ™”๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.

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

React.memo์˜ ์ธ์ž๋กœ ๋ฐ›์€ ์ปดํฌ๋„ŒํŠธ์˜ props์— ๋ณ€ํ™”๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ Œ๋”๋ง์„ ํ•˜๊ณ , props์— ๋ณ€ํ™”๊ฐ€ ์—†๋‹ค๋ฉด ๋ Œ๋”๋ง ํ•˜์ง€ ์•Š๊ณ  ๊ธฐ์กด์— ๋ Œ๋”๋ง ๋œ ๊ฒฐ๊ณผ๋ฅผ ์žฌ์‚ฌ์šฉํ•œ๋‹ค.

const Profile = ({info}) => {
  return (
    <p>name: {info.name}</p>
    <p>age: {info.age}</p>
  )
}

export default React.memo(Profile);

๐Ÿค”ย ๊ฐ๊ฐ์˜ ๊ณตํ†ต์ ๊ณผ ์ฐจ์ด์ ์— ๋Œ€ํ•ด ๋งํ•ด์ฃผ์„ธ์š”.

๊ณตํ†ต์ 

๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง, ๋ณต์žกํ•œ ๊ณ„์‚ฐ์˜ ๋ฐ˜๋ณต ๋“ฑ์„ ์ค„์ด๊ธฐ ์œ„ํ•œ ์šฉ๋„๋กœ, ๋ฉ”๋ชจ์ด์ œ์ด์…˜์„ ํ†ตํ•ด ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ํ•˜๋Š” ๊ฒƒ์ด ๊ทธ ๋ชฉ์ ์ด๋‹ค.

์ฐจ์ด์ 

React.memo๋Š” ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋กœ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ useMemo์™€ useCallback์€ ํ›…์œผ๋กœ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

useMemo๋Š” ์ „๋‹ฌ๋œ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๊ณ  ๋ฐ˜ํ™˜๋œ ๊ฐ’์„ ์บ์‹ฑํ•˜์ง€๋งŒ useCallback์€ ์ „๋‹ฌ๋œ ํ•จ์ˆ˜ ๊ทธ ์ž์ฒด๋ฅผ ์บ์‹ฑํ•œ๋‹ค.

๐Ÿค”ย React.memo๋Š” ์–ธ์ œ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹๋‚˜์š”?

React.memo๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ ํ•ฉํ•œ ์ƒํ™ฉ์€

  1. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ™์€ props๋กœ ์ž์ฃผ ๋ Œ๋”๋ง๋  ๋•Œ
  2. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋  ๋•Œ๋งˆ๋‹ค ๋ณต์žกํ•œ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ

React.memo๋Š” ์˜ค์ง props ๋ณ€ํ™”์—๋งŒ ์˜์กดํ•˜๋Š” ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์ด๋‹ค.

๋งŒ์•ฝ์— ์ปดํฌ๋„ŒํŠธ๊ฐ€ useState, useReducer, useContext์™€ ๊ฐ™์€ ์ƒํƒœ ๊ด€๋ จ ํ›…์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, props์˜ ๋ณ€ํ™”๊ฐ€ ์—†๋”๋ผ๋„ ์—ฌ์ „ํžˆ state๋‚˜ context๊ฐ€ ๋ณ€ํ•  ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ๋ Œ๋”๋ง ๋  ๊ฒƒ์ด๋‹ค.

๐Ÿค”ย React.memo์˜ ๋‹จ์ ์€ ์—†๋‚˜์š”?

  1. ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋น„

React.memo๋ฅผ ์ž˜ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋ Œ๋”๋ง ํšŸ์ˆ˜ ๊ฐ์†Œ๋กœ ์ธํ•ด ์ด๋“์„ ๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฌด๋ถ„๋ณ„ํ•œ ์‚ฌ์šฉ์€ ์˜คํžˆ๋ ค ๋…์ด ๋  ์ˆ˜๋„ ์žˆ๋‹ค.

์™œ๋ƒํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฉ”๋ชจ์ด์ง•ํ•  ๋•Œ ๋ Œ๋”๋ง ๋œ ๊ฒฐ๊ณผ๋ฅผ ์–ด๋”˜๊ฐ€์— ์ €์žฅํ•ด๋†“์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ์†Œ๋น„ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋งŒ์•ฝ props๊ฐ€ ๊ณ„์† ๋ณ€ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ React.memo๋กœ ๊ฐ์‹ผ๋‹ค๋ฉด ๋ถˆํ•„์š”ํ•œ ๋น„๊ต๊ณผ์ •๋งŒ ๊ฑฐ์น ๋ฟ ๋ Œ๋”๋ง์€ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋‹ค.

  1. props์— ์ฐธ์กฐ๊ฐ’์„ ์ „๋‹ฌํ•  ๊ฒฝ์šฐ ์›ํ•˜๋Š”๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์Œ

props์— ๊ฐ์ฒด, ๋ฐฐ์—ด, ํ•จ์ˆ˜ ๋“ฑ ์ฐธ์กฐ ํƒ€์ž…์˜ ๊ฐ’์„ ์ „๋‹ฌํ•  ๊ฒฝ์šฐ ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ๋งค๋ฒˆ ์ƒˆ๋กœ ์ƒ์„ฑ๋˜๋Š” ์ฐธ์กฐ๊ฐ’์€ ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ์ฃผ์†Œ๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค. ์–•์€ ๋น„๊ต๋ฅผ ํ†ตํ•ด React.memo์˜ ์ž…์žฅ์—์„œ๋Š” props์— ๋ณ€ํ™”๊ฐ€ ์žˆ๋‹ค๊ณ  ํŒ๋‹จํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ๋œ ๊ฐ’์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ Œ๋”๋ง์ด ๋‹ค์‹œ ๋ฐœ์ƒํ•œ๋‹ค.

import Profile from './Profile';

const App = () => {
  const info = {
    name: 'kim',
    age: 20,
  };

  return (
    <Profile info={info} /> // App์ด ๋ Œ๋”๋ง ๋  ๋•Œ๋งˆ๋‹ค props๊ฐ€ ๋‹ฌ๋ผ์ง
  )
};

๐Ÿค”ย useMemo, useCallback, React.memo.. ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„๊นŒ์š”?

๐Ÿ‘‰ย useMemo + React.memo

React.memo๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์ŒŒ์ง€๋งŒ props์— ์ฐธ์กฐ ํƒ€์ž…์˜ ๊ฐ’์ด ์ „๋‹ฌ๋œ ๊ฒฝ์šฐ ํ•ด๋‹น ์ฐธ์กฐ๊ฐ’์„ useMemo๋กœ ๊ฐ์‹ธ์„œ ๋™์ผํ•œ ์ฐธ์กฐ๋ฅผ ๋ณด์žฅํ•œ๋‹ค๋ฉด ์˜๋„ํ•œ ๋Œ€๋กœ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

import { useMemo } from 'react';
import Profile from './Profile';

const App = () => {
  const info = useMemo(() => {
    return { 
			name: 'kim',
	    age: 20,
		};
  }, []);

  return (
    <Profile info={info} />
  )
};

๐Ÿ‘‰ย useCallback + React.memo

React.memo๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์ŒŒ์ง€๋งŒ props์— ํ•จ์ˆ˜๊ฐ€ ์ „๋‹ฌ๋œ ๊ฒฝ์šฐ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ useCallback์œผ๋กœ ๊ฐ์‹ธ์„œ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งค๋ฒˆ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ํ•จ์ˆ˜์˜ ๋™์ผํ•œ ์ฐธ์กฐ๋ฅผ ๋ณด์žฅํ•œ๋‹ค๋ฉด ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

import { useCallback } from 'react';
import Profile from './Profile';

const App = () => {
  const sayHi = useCallback(() => {
    console.log('hi');
  }, []);

  return (
    <Profile sayHi={sayHi} />
  )
};

๐Ÿ”Žย ์ฐธ๊ณ 

https://www.youtube.com/watch?v=oqUgcxwrnSY&t=29s

post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€