๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Frontend/TroubleShooting

[Trouble Shooting] useEffect๋„ useMemo๋„ ๋‹ต์ด ์•„๋‹ˆ์—ˆ๋‹ค — ํ•œ ๋ฐ•์ž ๋Šฆ๋Š” state

by YWTechIT 2026. 6. 24.
728x90

๐Ÿ“ useEffect๋„ useMemo๋„ ๋‹ต์ด ์•„๋‹ˆ์—ˆ๋‹ค — ํ•œ ๋ฐ•์ž ๋Šฆ๋Š” state

๋“ค์–ด๊ฐ€๋ฉฐ

ํ•ด์™ธ T&A ์ƒํ’ˆ ์ƒ์„ธ(PDP) ํŽ˜์ด์ง€์—๋Š” ๋‘ ๊ฐœ์˜ ์˜ˆ์•ฝ ๋ฒ„ํŠผ์ด ์žˆ๋‹ค. ํ•˜๋‚˜๋Š” ์˜ต์…˜ ์˜์—ญ ์•ˆ์˜ ์˜ˆ์•ฝ ๋ฒ„ํŠผ์ด๊ณ , ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์Šคํฌ๋กค์„ ๋‚ด๋ฆฌ๋ฉด ๋”ฐ๋ผ๋‹ค๋‹ˆ๋Š” CTA ํ”Œ๋กœํŒ… ๋ฒ„ํŠผ์ด๋‹ค.

 

๋งก๋˜ ์—…๋ฌด๊ฐ€ ์˜ˆ์ƒ๋ณด๋‹ค ๋น ๋ฅด๊ฒŒ ๋งˆ๋ฌด๋ฆฌ ๋˜์–ด ๋ฆฌ์†Œ์Šค๊ฐ€ ์กฐ๊ธˆ ๋‚จ์•„ ๋ฐฑ๋กœ๊ทธ๋ฅผ ์‚ดํŽด๋ณด๋‹ค ๋ˆˆ์— ๋„๋Š” ํ‹ฐ์ผ“์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค.

ํ•„์ˆ˜ ์˜ต์…˜์„ ์„ ํƒํ•˜์ง€ ์•Š์•˜๋Š”๋ฐ๋„ CTA ํ”Œ๋กœํŒ… "์˜ˆ์•ฝํ•˜๊ธฐ"๋ฅผ ๋ˆ„๋ฅด๋ฉด ๊ฒฐ์ œ ํŽ˜์ด์ง€๋กœ ๋„˜์–ด๊ฐ„๋‹ค.

 

์˜ต์…˜ ์˜์—ญ ๋ฒ„ํŠผ์€ ๊ฒ€์ฆ์„ ํ†ต๊ณผํ•˜์ง€ ๋ชป ํ•˜๋ฉด ๋ฒ„ํŠผ์ด disabled ์ฒ˜๋ฆฌ๊ฐ€ ๋˜๋Š”๋ฐ, CTA ํ”Œ๋กœํŒ… ๋ฒ„ํŠผ์€ ํด๋ฆญ์ด ๊ฐ€๋Šฅํ•œ ์ƒํƒœ์˜€๋‹ค. ๋‘ ๋ฒ„ํŠผ์ด ๊ฐ™์€ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜์ง€ ๋ชปํ•˜๊ณ  ์žˆ๋˜ ๊ฒƒ์ด๋‹ค.

๋ฌธ์ œ ๋ฐœ๊ฒฌ

๋ฒ„ํŠผ disabled ์ฒ˜๋ฆฌ๋Š” ์˜ต์…˜ ์ปดํฌ๋„ŒํŠธ(/item/index.tsx)์—์„œ ๊ณ„์‚ฐํ•œ๋‹ค. ์œ ์ €๊ฐ€ ์„ ํƒํ•œ ์ˆ˜๋Ÿ‰ (finalAmounts), ํƒ€์ž„์Šฌ๋กฏ (selectedTimeslot), ์ƒํ’ˆ์ƒ์„ธ ๋ฐ์ดํ„ฐ๋กœ๋ถ€ํ„ฐ ํ•„์ˆ˜ ์˜ต์…˜, ๋‹จ๋… ๊ตฌ๋งค, ์ตœ์†Œ ์ธ์› ์กฐ๊ฑด์„ ๊ณ ๋ คํ•˜์—ฌ ๋งŒ๋“  ๊ฐ’์ด๋‹ค.

 

๋ฌธ์ œ๋Š” CTA ํ”Œ๋กœํŒ… ๋ฒ„ํŠผ์ด ๋ณ„๋„ ์ปดํฌ๋„ŒํŠธ(/cta/desktop.tsx)๋ผ๋Š” ๊ฒƒ์ธ๋ฐ, ์ด ๊ณ„์‚ฐ ๋กœ์ง์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ๊ฐ€๋ฉด CTA ๋ฒ„ํŠผ์ด ์ƒํ’ˆ ๋ฐ์ดํ„ฐ์™€ ๊ฒ€์ฆ ๋กœ์ง ์ „์ฒด๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋˜์–ด ๊ฒฐํ•ฉ๋„๊ฐ€ ๋„ˆ๋ฌด ๋†’์•„์ง„๋‹ค. ๊ทธ๋ž˜์„œ ๊ณ„์‚ฐ์€ ์˜ต์…˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ง„ํ–‰ํ•˜๊ณ , ๊ฒฐ๊ณผ ๊ฐ’๋งŒ ์ „์—ญ store์— ์‹ค์–ด์„œ CTA๊ฐ€ ์ฝ๋„๋ก ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

// floatingOptionsAtom ์— buttonDisabled ํ•„๋“œ ์ถ”๊ฐ€
  export const floatingOptionsAtom = atom<{
    // ...
    buttonDisabled?: boolean
  } | undefined>(undefined)

  // cta/desktop.tsx — ์ฝ์–ด์„œ disabled ์— ๋ฐ˜์˜
  const floatingOptionButtonDisabled = floatingOptions && floatingOptions.buttonDisabled

  return (<CtaButton disabled={!isSaleable || floatingOptionButtonDisabled} ... />)

 

์—ฌ๊ธฐ๊นŒ์ง€๋Š” ๋‹จ์ˆœํ•ด ๋ณด์˜€๋‹ค. ๋ฌธ์ œ๋Š” ์˜ต์…˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ atom์— buttonDisabled๋ฅผ ์–ธ์ œ, ์–ด๋–ค ๊ฐ’์œผ๋กœ ๋„ฃ๋А๋ƒ์˜€๋‹ค.

๐Ÿ“ ์‹œ๋„ 1 — useEffect๋กœ atom์— ๋™๊ธฐํ™”

๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•. buttonDisabled๊ฐ€ ๋ณ€๊ฒฝ๋ ๋•Œ๋งˆ๋‹ค useEffect๋กœ atom์— ๋”ฐ๋ผ ์“ฐ๊ฒŒ ํ–ˆ๋‹ค.

const buttonDisabled = useMemo(() => compute(finalAmounts, selectedTimeslot), [finalAmounts, selectedTimeslot])

useEffect(() => {
  setFloatingOptions((prev) => (prev && { ...prev, buttonDisabled }))
}, [buttonDisabled])

 

๊ฒฐ๊ณผ๋Š” ํ•œ ๋ฐ•์ž (1๋ Œ๋”) ๋Šฆ๊ฒŒ ๋ฐ˜์˜๋จ. ์˜ต์…˜์„ ์„ ํƒํ•œ ์งํ›„ CTA๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋น„ํ™œ์„ฑํ™”๋ผ์•ผ ํ•  ๋ฒ„ํŠผ์ด ๊ทธ๋Œ€๋กœ ๋ˆŒ๋ ธ๋‹ค.

์›์ธ์€ useEffect์˜ ์‹คํ–‰ ์‹œ์ ์ด๋‹ค. useEffect๋Š” ๋ Œ๋”๊ฐ€ ํ™”๋ฉด์— ์ปค๋ฐ‹๋œ ์ดํ›„์— ์‹คํ–‰๋œ๋‹ค.

  1. ์˜ต์…˜ ๋ณ€๊ฒฝ → setFinalAmounts(์ƒˆ ๊ฐ’)
  2. ๋ฆฌ๋ Œ๋” → useMemo๊ฐ€ buttonDisabled ์žฌ๊ณ„์‚ฐ
  3. DOM ์ปค๋ฐ‹
  4. ๊ทธ์ œ์„œ์•ผ useEffect ์‹คํ–‰ → setFloatingOptions(buttonDisabled ๋ฎ์–ด์“ฐ๊ธฐ)
  5. 4๋ฒˆ ๋•Œ๋ฌธ์— ๋‹ค์‹œ ํ•œ ๋ฒˆ ๋” ๋ Œ๋”

buttonDisabled๊ฐ€ atom์— ๋„๋‹ฌํ•˜๋Š”๊ฑด 4๋ฒˆ ์‹œ์ ์ธ๋ฐ, ๊ทธ ์ „ (2 ~ 3๋ฒˆ ์‚ฌ์ด)์— ํด๋ฆญ์ด ๋“ค์–ด์˜ค๋ฉด ์ด์ „ ์‚ฌ์ดํด ๊ฐ’์ด ์žกํžŒ๋‹ค.

๐Ÿ“ ์‹œ๋„ 2 — useEffect ๋Œ€์‹  setFloatingOptions์— ์ง์ ‘ ๋ฎ์–ด์“ฐ๊ธฐ

๊ทธ๋Ÿฌ๋ฉด, useEffect๋ฅผ ๋นผ๊ณ , ์˜ต์…˜์„ ๋ฐ”๊พธ๋Š” ํ•ธ๋“ค๋Ÿฌ์—์„œ setFloatingOptions์— buttonDisabled๋ฅผ ๋ฐ”๋กœ ๋„ฃ์œผ๋ฉด ๋˜์ง€ ์•Š์„๊นŒ?

 onChange={(value) => {
    const amounts = amountToSnapshotOptions({ value, ... })
    setFinalAmounts(amounts)
    setFloatingOptions({ ...floatingOptions, amounts, buttonDisabled })
    //                                                 ^^^^^^^^^^^^^^ useMemo ๊ฐ’
  }}

 

๊ทธ๋Ÿฐ๋ฐ ์—ฌ์ „ํžˆ ํ•œ ๋ฐ•์ž๊ฐ€ ๋Šฆ์—ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ํ—ค๋งธ๋Š”๋ฐ, ํ•ต์‹ฌ ์ธ์‚ฌ์ดํŠธ๋Š” ์ด๊ฑฐ์˜€๋‹ค.

๋ Œ๋” ์ค‘ ๊ณ„์‚ฐ๋œ ๊ฐ’ (useMemo๋“  ์•„๋‹ˆ๋“ ) ์ง์ „์— ์ปค๋ฐ‹๋œ state ๊ธฐ์ค€์ด๋‹ค.

 

์ด ํ•ธ๋“ค๋Ÿฌ ์•ˆ์—์„œ ์ฐธ์กฐํ•˜๋Š” buttonDisabled๋Š” ์ด๋ฒˆ ๋ Œ๋”์˜ useMemo์˜ ๊ฒฐ๊ณผ = ์ง์ „ finalAmounts ๊ธฐ์ค€ ๊ฐ’์ด๋‹ค. ๋ฐฉ๊ธˆ setFinalAmounts(amounts)๋ฅผ ํ˜ธ์ถœํ–ˆ์–ด๋„ ๊ทธ๊ฑด ๋‹ค์Œ ๋ Œ๋”๋ฅผ ์˜ˆ์•ฝํ•œ ๊ฒƒ์ผ ๋ฟ, ์ง€๊ธˆ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ณด๋Š” buttonDisabled๋Š” ์ƒˆ amounts๋ฅผ ๋ชจ๋ฅธ๋‹ค.

 

useMemo๋Š” ๋‹ค์Œ ๋ Œ๋”์—์„œ์•ผ ์žฌ๊ณ„์‚ฐ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ฆ‰ useEffect๋ฅผ ์—†์• ๋„, staleํ•œ useMemo๋ฅผ ๊ทธ๋Œ€๋กœ ๋„ฃ๋Š” ํ•œ ๋ฌด์กฐ๊ฑด ๋Šฆ๋Š”๋‹ค. useMemo๋ฅผ ๋นผ๋„ ๋˜‘๊ฐ™๋‹ค. "useMemo๊ฐ€ ์บ์‹ฑํ•ด์„œ ๋Šฆ๋Š” ๊ฑด๊ฐ€?" ์‹ถ์–ด์„œ useMemo๋ฅผ ๋นผ๊ณ  ๋ Œ๋” ๋ณธ๋ฌธ์—์„œ ๊ทธ๋ƒฅ ๊ณ„์‚ฐํ•ด๋ดค๋‹ค.

 

// useMemo ์ œ๊ฑฐ — ๋ Œ๋”ํ•  ๋•Œ๋งˆ๋‹ค ์ง์ ‘ ๊ณ„์‚ฐ
const buttonDisabled = getItemButtonDisabled({ detailData, finalAmounts, selectedTimeslot })

onChange={(value) => {
  const amounts = amountToSnapshotOptions({ value, ... })
  setFinalAmounts(amounts)
  setFloatingOptions({ ...floatingOptions, amounts, buttonDisabled })
//                                                 ^^^^^^^^^^^^^^ ์—ฌ์ „ํžˆ ์˜› ๊ฐ’
}}

 

๊ทธ๋ž˜๋„ ํ•œ ๋ฐ•์ž ๋Šฆ์—ˆ๋‹ค. ์ด์œ ๋Š” ํด๋กœ์ €์— ์žˆ๋‹ค. onChange ํ•ธ๋“ค๋Ÿฌ๋Š” ์ด๋ฒˆ ๋ Œ๋”์—์„œ ๋งŒ๋“ค์–ด์ง„ ํ•จ์ˆ˜๋ผ, ๊ทธ ์•ˆ์˜ buttonDisabled๋Š” ์ด๋ฒˆ ๋ Œ๋” ์‹œ์ ์˜ finalAmounts(์˜› ๊ฐ’)๋กœ ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ์บก์ฒ˜ํ•œ๋‹ค.

 

ํ•ธ๋“ค๋Ÿฌ ์•ˆ์—์„œ setFinalAmounts(amounts)๋ฅผ ๋ถˆ๋Ÿฌ๋„ ๊ทธ๊ฑด ๋‹ค์Œ ๋ Œ๋”๋ฅผ ์˜ˆ์•ฝํ•  ๋ฟ, ์ด๋ฏธ ์บก์ฒ˜๋œ buttonDisabled๋Š” ๋ฐ”๋€Œ์ง€ ์•Š๋Š”๋‹ค.
์ฆ‰ ๋Šฆ๋Š” ์›์ธ์€ useMemo์˜ ์บ์‹ฑ์ด ์•„๋‹ˆ๋ผ, "๋ Œ๋” ์‹œ์ ์— ๋งŒ๋“ค์–ด์ง„ ๊ฐ’์„, ๊ทธ ๋ Œ๋”์—์„œ ์ƒ์„ฑ๋œ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๊ทธ๋Œ€๋กœ ๋“ค๊ณ  ์žˆ๋‹ค"๋Š” ๊ตฌ์กฐ ์ž์ฒด์˜€๋‹ค. memoize๋Š” ๊ฑฐ๋“ค ๋ฟ, ๋นผ๋„ ๊ฒฐ๊ณผ๋Š” ๊ฐ™๋‹ค.

 

๊ทธ๋ž˜์„œ ๋‹ต์€ ํ•˜๋‚˜๋กœ ๋ชจ์ธ๋‹ค — ๋ Œ๋”๊ฐ€ ๋งŒ๋“ค์–ด ์ค€ ๊ฐ’์„ ์žฌ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ , ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋ฐฉ๊ธˆ ๋งŒ๋“  amounts๋กœ ๊ทธ ์ž๋ฆฌ์—์„œ ๋‹ค์‹œ ๊ณ„์‚ฐํ•  ๊ฒƒ.

๐Ÿ’ก react 18์— ์‚ฌ์šฉํ•˜๋Š” useTransition, flushSync๋Š”?

  • useTransition / useDeferredValue๋Š” ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฏธ๋ฃจ๋Š”(defer) API๋‹ค. "๊ฐ™์€ cycle ๋‚ด ์ฆ‰์‹œ ๋ฐ˜์˜"๊ณผ๋Š” ์ •๋ฐ˜๋Œ€๋ผ ๋„์›€์ด ์•ˆ ๋œ๋‹ค.
  • flushSync๋กœ ๊ฐ•์ œ ๋™๊ธฐ ๋ Œ๋”๋ฅผ ์‹œํ‚ค๋ฉด ์ฆ์ƒ์€ ๊ฐ€๋ ค์ง€์ง€๋งŒ ๊ทผ๋ณธ์ ์ธ ํ•ด๊ฒฐ๋ฐฉ์•ˆ์€ ์•„๋‹ˆ๋‹ค. React 18์˜ ์ž๋™ ๋ฐฐ์นญ์„ ๊นจ์„œ ์„ฑ๋Šฅ์„ ๋–จ์–ด๋œจ๋ฆฌ๊ณ , ๋Šฆ๋Š” ์›์ธ(๋ Œ๋” ํŒŒ์ƒ๊ฐ’์€ ์ง์ „ ์ปค๋ฐ‹ state ๊ธฐ์ค€)์€ ๊ทธ๋Œ€๋กœ๋ผ ์กฐ๊ฑด์ด ์ถ”๊ฐ€๋˜๊ธฐ๋ผ๋„ ํ•œ๋‹ค๋ฉด ์ƒํƒœ๊ฐ€ ๊นจ์ง€๊ธฐ๋„ ์‰ฝ๋‹ค.

์ฆ‰, ํƒ€์ด๋ฐ API๋กœ ํ’€ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ, ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๊ณ ์ณ์•ผ ํ•˜๋Š” ๋ฌธ์ œ์˜€๋‹ค.

๐Ÿ“ ์ตœ์ข… ์†”๋ฃจ์…˜ — ์“ฐ๋Š” ์‹œ์ ์— fresh ๊ฐ’์œผ๋กœ ์ง์ ‘ ๊ณ„์‚ฐ

ํ•ด๊ฒฐ์€ ์˜์™ธ๋กœ ๋‹จ์ˆœํ–ˆ๋‹ค. useMemo๊ฐ€ ๋‹ค์Œ ๋ Œ๋”์— ๊ณ„์‚ฐํ•ด ์ค„ ๊ฐ’์„, ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ด๋ฏธ ์†์— ์ฅ” fresh ๊ฐ’(amounts)๋กœ ๋ฏธ๋ฆฌ ๋‹น๊ฒจ์„œ ์ง์ ‘ ๊ณ„์‚ฐํ•ด ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜์— ํ•จ๊ป˜ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค.
๋จผ์ € ๊ณ„์‚ฐ ๋กœ์ง์„ ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋กœ ์ถ”์ถœํ•ด useMemo์™€ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๊ฐ™์€ ๊ณต์‹์„ ๊ณต์œ ํ•˜๊ฒŒ ํ–ˆ๋‹ค.

// helpers.ts
export function getItemButtonDisabled({ detailData, finalAmounts, selectedTimeslot }): boolean {
  if (!detailData) return true
  // ... ํ•„์ˆ˜ ์˜ต์…˜ / ๋‹จ๋…๊ตฌ๋งค / ์ตœ์†Œ ์ธ์› / ํšŒ์ฐจ ์กฐ๊ฑด ๊ณ„์‚ฐ
  return hasTimeslots ? !(!!selectedTimeslot && isCommonConditions) : !isCommonConditions
}

 

๊ทธ๋ฆฌ๊ณ  atom์— ์“ฐ๋Š” ์‹œ์ ์— fresh ๊ฐ’์œผ๋กœ ํ˜ธ์ถœํ•œ๋‹ค.

onChange={(value) => {
  const amounts = amountToSnapshotOptions({ value, ... })

  const buttonDisabled = getItemButtonDisabled({
    detailData,
    finalAmounts: amounts,   // โœ… state๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฐฉ๊ธˆ ๋งŒ๋“  fresh ๊ฐ’
    selectedTimeslot,
  })

  setFinalAmounts(amounts)
  setFloatingOptions({ ...floatingOptions, amounts, buttonDisabled })
}}

 

ํšŒ์ฐจ ์„ ํƒ(onTimeslotClick)์—์„œ๋„ ๋˜‘๊ฐ™์ด ๊ทธ ์ˆœ๊ฐ„์˜ fresh ๊ฐ’์œผ๋กœ ๊ณ„์‚ฐํ•ด์„œ ๋„ฃ์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  useEffect๋Š” ์‚ญ์ œํ–ˆ๋‹ค.

ํ•ต์‹ฌ์€ amounts์™€ buttonDisabled๊ฐ€ ํ•œ ํŠธ๋žœ์žญ์…˜์— ์ผ๊ด€๋˜๊ฒŒ atom์œผ๋กœ ๋“ค์–ด๊ฐ„๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋ Œ๋” ์‚ฌ์ดํด์„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š์œผ๋‹ˆ ์–ด๊ธ‹๋‚  ํ‹ˆ์ด ์—†๋‹ค.

๐Ÿ“ ๊ธฐ๋Œ€ ํšจ๊ณผ / ์„ฑ๋Šฅ

  • ํ•œ ๋ฐ•์ž ๋Šฆ๋Š” ์‚ฌ์ดํด ์ œ๊ฑฐ → ํƒ€์ด๋ฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์—†๋Š” ๊ตฌ์กฐ
  • flushSync ๊ฐ™์€ ๊ฐ•์ œ ๋™๊ธฐ ๋ Œ๋” ๋ถˆํ•„์š” → ์ž๋™ ๋ฐฐ์นญ ์œ ์ง€
  • CTA๋Š” ๊ธฐ์กด์—๋„ floatingOptions๋ฅผ ๊ตฌ๋…ํ•˜๊ณ  ์žˆ์—ˆ์œผ๋ฏ€๋กœ ์ถ”๊ฐ€ ๋ Œ๋”·์‹ ๊ทœ ๊ตฌ๋… ์—†๋‹ค. ๋™์ผ write์— ํ•„๋“œ ํ•˜๋‚˜๋งŒ ๋” ์‹ค๋ฆด ๋ฟ
  • ๋Š˜์–ด๋‚œ ๋น„์šฉ์€ ์‚ฌ์šฉ์ž ์ธํ„ฐ๋ž™์…˜๋‹น ์ˆœ์ˆ˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋ช‡ ๋ฒˆ(๋ Œ๋” ๊ฒฝ๋กœ ์•„๋‹˜)๋ฟ → ์‚ฌ์‹ค์ƒ ์˜ํ–ฅ ์—†์Œ

๐Ÿ“ ํšŒ๊ณ 

์ด๋ฒˆ ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ•˜๋ฉด์„œ ๊ฐ€์žฅ ํฌ๊ฒŒ ๋‚จ์€ ๊ฑด ๋‘ ๊ฐ€์ง€๋‹ค.

 

์ฒซ์งธ, ํŒŒ์ƒ ์ƒํƒœ(derived state)๋Š” store์— ๋ณต์ œํ•˜์ง€ ๋ง์ž. ๋ณต์ œํ•˜๋Š” ์ˆœ๊ฐ„ ์›๋ณธ๊ณผ ๋ณต์‚ฌ๋ณธ ๋‘ ๊ฐœ์˜ ์ง„์‹ค์ด ์ƒ๊ธฐ๊ณ , ๋‘˜์„ ๋งž์ถ”๋Š” ๋™๊ธฐํ™” ์ฑ…์ž„์ด ๋”ฐ๋ผ์˜จ๋‹ค. useEffect๋กœ ๋งž์ถ”๋ฉด ํ•œ ๋ฐ•์ž ๋Šฆ๊ณ , flushSync๋กœ ๋งž์ถ”๋ฉด ์„ฑ๋Šฅ์„ ๊นŽ๋Š”๋‹ค. ๋‘˜ ๋‹ค ์ฆ์ƒ์„ ๋‹ค๋ฃฐ ๋ฟ์ด๋‹ค.

 

๋‘˜์งธ, ๋ Œ๋” ์ค‘ ๊ณ„์‚ฐ๋œ ๊ฐ’์€ "์ง์ „ ์ปค๋ฐ‹ state" ๊ธฐ์ค€์ด๋‹ค. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ๋ฐฉ๊ธˆ setState๋กœ ๋ฐ”๊พผ ๊ฐ’์„ ๊ทธ ์ž๋ฆฌ์—์„œ ์“ฐ๊ณ  ์‹ถ๋‹ค๋ฉด, state๋ฅผ ๋‹ค์‹œ ์ฝ์ง€ ๋ง๊ณ  ๋‚ด๊ฐ€ ๋ฐฉ๊ธˆ ๋งŒ๋“  fresh ๊ฐ’์œผ๋กœ ์ง์ ‘ ๊ณ„์‚ฐํ•ด์•ผ ํ•œ๋‹ค. ๋„ˆ๋ฌด ๋‹น์—ฐํ•œ ์‚ฌ์‹ค์ธ๋ฐ, "๊ฐ’์ด ๋Šฆ๋Š”๋‹ค"๋Š” ์ฆ์ƒ์„ ๋งŒ๋‚˜๋ฉด ์ž๊พธ ํƒ€์ด๋ฐ API๋ถ€ํ„ฐ ์ฐพ๊ฒŒ ๋œ๋‹ค. ์ดํ›„ ๋™์ผํ•œ ์ด์Šˆ๊ฐ€ ์žˆ์–ด๋„ ๋‹นํ™ฉํ•˜๊ณ  ํ—ค๋งค์ง€ ๋ง์ž๋Š” ์ทจ์ง€์—์„œ ์ด ๊ธ€์„ ๋‚จ๊ธด๋‹ค.

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€