[๐Ÿ•น๏ธ ํฌ์ผ“๋ชฌ ๋„๊ฐ] React.memo ์‚ฌ์šฉํ•ด ์ค‘๋ณต ์ปดํฌ๋„ŒํŠธ ์ตœ์ ํ™”

JiEunยท2024๋…„ 4์›” 6์ผ
0

๐Ÿ“์‹œ์ž‘

Loading ๊ด€๋ จ ์ฝ”๋“œ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด ๋””๋ฒ„๊น… ์ž‘์—… ์ค‘
๋ฌดํ•œ ์Šคํฌ๋กค ์‹œ ์ด์ „ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ์˜ ์นด๋“œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜๋Š”๊ฑธ ํ™•์ธํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•™์Šตํ–ˆ๋˜ ๋ฉ”๋ชจ์ด์ œ์ด์…˜์— ๋Œ€ํ•ด ์ ์šฉํ•ด ๋ณด๋ ค๊ณ  ํ•œ๋‹ค.


React.memo?

๋ฉ”๋ชจ์ด์ œ์ด์…˜ ํ•˜๊ธฐ ์ „์— React.memo๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๊ฐ„๋žตํ•˜๊ฒŒ ์•Œ๊ณ ๊ฐ€์ž.

  • React.memo๋Š” ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ, ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ ๋‘˜ ๋‹ค ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    -> (useMemo, useCallback์€ hook์œผ๋กœ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.)
  • ์ปดํฌ๋„ŒํŠธ ์ž์ฒด๋ฅผ ๋ฉ”์ด๋ชจ์ด์ œ์ด์…˜ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ๊ฒฝ์šฐ ์ด๋ฅผ ๊ธฐ์–ตํ•˜๊ณ  ์ด์ „ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๊ณต๋ถ€ํ–ˆ๋˜ ๋‚ด์šฉ์œผ๋กœ ํ˜น์‹œ ํ‹€๋ฆฐ ๊ฐœ๋…์ด ์žˆ๋‹ค๋ฉด ๋ง์”€ํ•ด์ฃผ์„ธ์š”!

๐Ÿค” ์–ด๋–ค ๋ฌธ์ œ์ ์ด ๋ฐœ์ƒํ–ˆ๋Š”์ง€?

๋ฌดํ•œ ์Šคํฌ๋กค ์‹œ ์ด์ „์— ์žˆ๋˜ ์นด๋“œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋œ ์ดํ›„์— ๋ถˆ๋Ÿฌ์˜จ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ถˆ๋Ÿฌ์™€์ง„๋‹ค.

React Query๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์žˆ๊ธฐ์— ์บ์‹ฑ๋˜๋Š” ์ค„ ์•Œ์•˜์œผ๋‚˜,
์•„๋ฌด๋ž˜๋„ ๋ฌดํ•œ ์Šคํฌ๋กค์€ React Query์—์„œ ์ œ๊ณตํ•˜๋Š” hook์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ 
๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•ด์„œ ๊ทธ๋Ÿฐ๋“ฏ ์‹ถ๋‹ค.

์ด์ ์— ๋Œ€ํ•ด์„  React Query๋กœ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ • ํ›„ ๋‹ค์‹œ ํ™•์ธํ•ด ๋ด์•ผ๊ฒ ๋‹ค.

๋˜ํ•œ, state๋Š” ๋™์ผ ํ•œ ๊ฐ’์„ ํ˜ธ์ถœํ•ด๋„ ๋ฆฌ๋ Œ๋”๋ง ๋˜๋Š” ๋ฌธ์ œ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด,
๋ฉ”๋ชจ์ด์ œ์ด์…˜ ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค.

React.memo ์ถ”๊ฐ€ํ•˜๊ธฐ

// memo importํ•˜๊ธฐ
import { memo } from 'react';
.
.
.
const PokeInfoCard = ({ name }: { name: string }) => {
.
.
.
  return (
    <>
      <PokemonDetail name={name} />
      <PokeCardContainer id={name} onClick={() => handlerModal(name)}>
        <TextWrap>
          <NumText>no. {pokeData?.id}</NumText>
          <NameText>{pokeName}</NameText>
          <TypeBox>
            {pokeData?.types.map((el: TypesT, idx: number) => <TypeText key={idx} typename={el.type.name} />)}
          </TypeBox>
        </TextWrap>
        <Img src={pokeData?.sprites.front_default} loading="lazy" alt={pokeData?.name} />
        <BgImg>
          <Pokeball color="#f5f5f5" />
        </BgImg>
      </PokeCardContainer>
    </>
  );
};

// ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•  ์ปดํฌ๋„Œ๋ฅผ memo์˜ ์ธ์ž๋กœ ์ถ”๊ฐ€ํ•˜๊ธฐ
export default memo(PokeInfoCard);

๋™์ผํ•œ ์นด๋“œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ๋ Œ๋”๋ง ํ•˜๊ณ  ์žˆ๊ธฐ์— ์ด๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•ด
React.memo๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ตœํ•˜๋‹จ์— memo(์ปดํฌ๋„ŒํŠธ) ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹๋„ ์žˆ์œผ๋ฉฐ,
ํ•จ์ˆ˜์ปดํฌ๋„ŒํŠธ์— useMemo ๋“ฑ์˜ ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹๋„ ์žˆ๋‹ค.


์ดํ›„ ํ™•์ธํ–ˆ์„ ๋•Œ ๋™์ผํ•œ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฆฌ๋ Œ๋”๋ง ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ‘€ ์ฃผ์˜ํ•  ์ 

๋‹จ, ๋ฉ”๋ชจ์ด์ œ์ด์…˜์€ ์ด์ „์˜ ๊ฐ’์„ ๋ฏธ๋ฆฌ ์ €์žฅํ•ด ๋‘๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋งŒํผ ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋ชจ๊ฐ€ ๋œ๋‹ค.

๊ฐœ๋ฐœ์ž๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ๋•Œ ํ•ด๋‹น ์š”์†Œ๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ฆฌ๋ Œ๋”๋ง๋˜๊ณ ,
์ด๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์— ํฌ๊ฒŒ ๋ถ€ํ•˜๋ฅผ ์ฃผ๋Š” ์š”์†Œ์ธ์ง€ ์ฒดํฌํ•˜์—ฌ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•ด์•ผํ•œ๋‹ค.


โœ๏ธ ๋งˆ์น˜๋ฉฐ

์‚ฌ์‹ค ๋‹ค๋ฅธ๊ฑฐ ์ˆ˜์ •ํ•˜๋ ค๋‹ค ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜๊ณ  ์žˆ์–ด, React.memo๋ฅผ ์ ์šฉํ•ด ๋ณด์•˜๋‹ค.

ํฌ์ผ“๋ชฌAPI๋ฅผ ๋ฌด๋ฃŒ๋กœ ์ œ๊ณตํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๋ˆ„๊ตฐ๊ฐ€ ์ถ”๊ฐ€ ๋ฐ ์‚ญ์ œํ•  ์ˆ˜ ์—†๋Š” ๋ฐ์ดํ„ฐ์ด๋‹ค.
๊ทธ๋Ÿฐ์ ์—์„œ ๋ฉ”๋ชจ์ด์ œ์ด์…˜์„ ํ•ด๋„ ๊ดœ์ฐฎ๋‹ค ์ƒ๊ฐํ•˜์—ฌ ์ ์šฉํ•ด ๋ดค๋‹ค.

์•„๋งˆ React Query์—์„œ ์ œ๊ณตํ•˜๋Š” hook์„ ์‚ฌ์šฉํ•ด
๋ฌดํ•œ ์Šคํฌ๋กค ๋กœ์ง์„ ์ˆ˜์ •ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๊ตณ์ด ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ํ•  ํ•„์š”๊ฐ€ ์—†์ง€ ์•Š์„๊นŒ ์‹ถ๋‹ค.

์ด ์ ์— ๋Œ€ํ•ด์„  ์ถ”ํ›„ ๋ฆฌํŒฉํ† ๋ง ํ›„ ํฌ์ŠคํŒ…ํ•ด์•ผ๊ฒ ๋‹ค.

profile
๐Ÿ’ป ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๋ชฉํ‘œ๋กœ ์„ฑ์žฅ ์ค‘! (์•Œ์•„๋ดค๋˜ ๋‚ด์šฉ ๋“ฑ์„ ์ •๋ฆฌํ•˜๊ธฐ)

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