๐ค ์ ๋ด useEffect๋ ๋ฉ์ถ์ง ์์๊น?
React ๊ฐ๋ฐ์ ํ๋ค ๋ณด๋ฉด, ๋ถ๋ช
ํ ์ฝ๋๋ฅผ ๋ง๊ฒ ์งฐ๋๋ฐ๋
useEffect๊ฐ ๋ฌดํํ ์คํ๋๊ฑฐ๋, ์์ ์ปดํฌ๋ํธ๊ฐ ์ด์ ์์ด
๋ฆฌ๋ ๋๋ง ๋๋ ๊ฒฝํ์ ํด๋ณด์
จ์ ๊ฒ๋๋ค.
๋๋ถ๋ถ์ ๊ฒฝ์ฐ, ๋ฒ์ธ์ ๋ก์ง์ ์ค๋ฅ๊ฐ ์๋๋ผ ์๋ฐ์คํฌ๋ฆฝํธ์
์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ(Referential Integrity)์ด ๊นจ์ก๊ธฐ
๋๋ฌธ์
๋๋ค.
React์์ ๊ฐ์ฒด๋ ํจ์๋ ๋งค ๋ ๋๋ง๋ง๋ค
์๋ก์ด ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ํ ๋น๋ฐ๋๋ฐ, React๋ ์ด๋ฅผ '๋ฐ์ดํฐ๊ฐ
๋ณ๊ฒฝ๋์๋ค'๊ณ ์ธ์ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
์ค๋์ React ์ฑ๋ฅ ์ต์ ํ์ ์๋ ์ ๊ฒ์ธ useMemo์
useCallback์ ํตํด ์ด ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ์ ์ด๋ป๊ฒ ์ง์ผ๋ด๋์ง, ๊ทธ๋ฆฌ๊ณ
์์กด์ฑ ๋ฐฐ์ด(Dependency Array)์ ์ด๋ป๊ฒ ๊ด๋ฆฌํด์ผ ๋ฒ๊ทธ๋ฅผ ๋ง์ ์ ์๋์ง ๊น์ด
ํํค์ณ ๋ณด๊ฒ ์ต๋๋ค.
{} === {}๋
false์
๋๋ค. ๋ชจ์์ด ๊ฐ์๋ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊ฐ ๋ค๋ฅด๊ธฐ
๋๋ฌธ์
๋๋ค. ์ด๊ฒ์ด React ์ต์ ํ์ ์์์ ์
๋๋ค.๐ 1. ์ฐธ์กฐ ๋๋ฑ์ฑ(Referential Equality) ์ดํดํ๊ธฐ
Hook์ ๋ฐฐ์ฐ๊ธฐ ์ ์, React๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋น๊ตํ๋ ๋ฐฉ์์ ๋จผ์ ์ดํดํด์ผ
ํฉ๋๋ค.
React๋ ๋ ๋๋ง ์ ํ์ Props๋ State๋ฅผ ๋น๊ตํ ๋
์์ ๋น๊ต(Shallow Compare)๋ฅผ ์ํํฉ๋๋ค.
| ๋ฐ์ดํฐ ํ์ | ๋น๊ต ๋ฐฉ์ | ๊ฒฐ๊ณผ ์์ |
|---|---|---|
| ์์ ํ์ (Primitive) | ๊ฐ(Value) ์์ฒด๋ฅผ ๋น๊ต |
1 === 1 (True)
|
| ์ฐธ์กฐ ํ์ (Object, Array, Function) | ๋ฉ๋ชจ๋ฆฌ ์ฃผ์(Reference)๋ฅผ ๋น๊ต |
[] === [] (False)
|
๋ฌธ์ ๋ ์ปดํฌ๋ํธ ํจ์๊ฐ ์ฌ์คํ๋ ๋๋ง๋ค, ํจ์ ๋ด๋ถ์ ์ ์ธ๋
๊ฐ์ฒด์ ํจ์๋ค๋ ๋งค๋ฒ ์๋ก ์์ฑ๋๋ค๋ ์ ์
๋๋ค.
์ด๋ก ์ธํด ์์ ์ปดํฌ๋ํธ์ธ React.memo๊ฐ ์ ์ฉ๋์ด ์์ด๋,
Props๋ก ์ ๋ฌ๋๋ ๊ฐ์ฒด๋ ํจ์์ ์ฃผ์๊ฐ ๋ฐ๋์ด
๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํฉ๋๋ค.
๐ ️ 2. useMemo์ useCallback์ ์ ํํ ์ฌ์ฉ๋ฒ
A. useMemo: ๊ฐ(Value)๊ณผ ๊ฐ์ฒด์ ์ฃผ์ ์ ์ฅ
useMemo๋ ๊ณ์ฐ ๋น์ฉ์ด ๋ง์ด ๋๋ ํจ์์ ๋ฆฌํด๊ฐ์ ์บ์ฑํ๊ฑฐ๋,
๊ฐ์ฒด/๋ฐฐ์ด์ ์ฐธ์กฐ๋ฅผ ๊ณ ์ ํ ๋ ์ฌ์ฉํฉ๋๋ค.
✅ ์ฌ๋ฐ๋ฅธ ์ฌ์ฉ ์์:
const heavyValue = useMemo(() => calculateHugeData(data),
[data]);
const stableObject = useMemo(() => ({ id: 1, text: 'Hello' }),
[]);
์ด์ฒ๋ผ ๊ฐ์ฒด๋ฅผ ๊ฐ์ธ์ฃผ๋ฉด ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋์ด๋
stableObject๋ ๋์ผํ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ
์ ์งํฉ๋๋ค.
B. useCallback: ํจ์(Function)์ ์ฃผ์ ์ ์ฅ
์๋ฐ์คํฌ๋ฆฝํธ์์ ํจ์๋ ๊ฐ์ฒด์
๋๋ค. ์ปดํฌ๋ํธ ๋ด๋ถ์ ํจ์๋ ๋ ๋๋ง๋ง๋ค ์๋ก
๋ง๋ค์ด์ง๋๋ค.
useCallback์
ํจ์ ์ธ์คํด์ค ์์ฒด๋ฅผ ๋ฉ๋ชจ์ด์ ์ด์
ํ์ฌ, ์์ ์ปดํฌ๋ํธ์
Props๋ก ์ ๋ฌํ ๋ ์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํฉ๋๋ค.
⚠️ ์ธ์ ์ฌ์ฉํด์ผ ํ ๊น์?
-
1. ์์ ์ปดํฌ๋ํธ๊ฐ
React.memo๋ก ์ต์ ํ๋์ด ์์ ๋. - 2. ํจ์๋ ๊ฐ์ฒด๊ฐ ๋ค๋ฅธ Hook(useEffect ๋ฑ)์ ์์กด์ฑ ๋ฐฐ์ด(Dependency Array)์ ํฌํจ๋ ๋.
๐ก️ 3. ๋ํ๋์(Dependency) ๊ด๋ฆฌ์ Stale Closure
useMemo์ useCallback ์ฌ์ฉ ์ ๊ฐ์ฅ ์ฃผ์ํด์ผ ํ
์ ์ ์์กด์ฑ ๋ฐฐ์ด(deps) ๊ด๋ฆฌ์
๋๋ค.
์์กด์ฑ ๋ฐฐ์ด์ ์๋ชป ์ค์ ํ๋ฉด ์ต์ ์ํ๋ฅผ ์ฐธ์กฐํ์ง ๋ชปํ๋
Stale Closure(์ค๋๋ ํด๋ก์ ) ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ฑฐ๋,
๋ฉ๋ชจ์ด์ ์ด์
์ด ๋ฌด์ฉ์ง๋ฌผ์ด ๋ฉ๋๋ค.
๐จ ํํ ์ค์: ์์กด์ฑ ์๋ต
"ํจ์๊ฐ ๋๋ฌด ์์ฃผ ๋ฐ๋์ด์ ๋ฌดํ ๋ฃจํ๊ฐ ๋์์"๋ผ๋ฉฐ ์์กด์ฑ ๋ฐฐ์ด์์ ํน์
๋ณ์๋ฅผ ๊ณ ์๋ก ๋นผ๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
์ด๋ React์๊ฒ ๊ฑฐ์ง๋ง์ ํ๋ ํ์์ด๋ฉฐ, ์ฌ๊ฐํ ๋ฒ๊ทธ๋ฅผ
์ ๋ฐํฉ๋๋ค.
❌ ์๋ชป๋ ์ฝ๋ (Stale Closure ๋ฐ์):
const handleClick = useCallback(() => {
console.log(count); // count๊ฐ ๋ฐ๋์ด๋ ํญ์ 0๋ง ์ถ๋ ฅ๋
์ ์์
}, []); // count๋ฅผ ์์กด์ฑ์ ๋ฃ์ง ์์
✅ ํด๊ฒฐ ๋ฐฉ๋ฒ (ํจ์ํ ์
๋ฐ์ดํธ):
const handleClick = useCallback(() => {
setCount(prev => prev + 1); // ์ต์ ์ํ๋ฅผ ๋ณด์ฅ๋ฐ์
}, []); // ์์กด์ฑ ์์ด๋ ์์ ํจ
์ํ ๊ฐ์ ์ง์ ์ฐธ์กฐํ๋ ๋์ ํจ์ํ ์ ๋ฐ์ดํธ(Functional Update)๋ฅผ ์ฌ์ฉํ๋ฉด, ์์กด์ฑ ๋ฐฐ์ด์ ๋น์ฐ๋ฉด์๋ ํญ์ ์ต์ ๊ฐ์ ์์ ํ๊ฒ ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค.
✅ ๊ณผ๋ํ ์ต์ ํ๋ ๊ธ๋ฌผ
์ฐธ์กฐ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๋ ๊ฒ์ ์ค์ํ์ง๋ง, ๋ชจ๋ ํจ์์ ๊ฐ์ฒด์
useMemo์ useCallback์ ๊ฐ์ธ๋ ๊ฒ์ ์คํ๋ ค
์ฑ๋ฅ ์ค๋ฒํค๋๋ฅผ ๋ฐ์์ํฌ ์ ์์ต๋๋ค.
๋ฉ๋ชจ์ด์ ์ด์
์์ฒด๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ณ ๋น๊ต ์ฐ์ฐ์ ์ํํ๋ ๋น์ฉ์ด ๋ค๊ธฐ
๋๋ฌธ์
๋๋ค.
๐ ์์ฝ ๋ฐ ์ค์ฒ ๊ฐ์ด๋
- 1. ์๋ฆฌ ํ์ : ๊ฐ์ฒด์ ํจ์๋ ๋ ๋๋ง๋ง๋ค ์ฐธ์กฐ ์ฃผ์๊ฐ ๋ฐ๋๋๋ค.
- 2. ์ ์ ํ ์ฌ์ฉ: ์์ ์ปดํฌ๋ํธ์ Props๋ก ๋๊ธฐ๊ฑฐ๋, ์์กด์ฑ ๋ฐฐ์ด์ ๋ค์ด๊ฐ ๋๋ง ๋ฉ๋ชจ์ด์ ์ด์ ํ์ญ์์ค.
- 3. ์ ์งํ ๋ฐฐ์ด: ์์กด์ฑ ๋ฐฐ์ด์๋ ์ฌ์ฉํ๋ ๋ชจ๋ ์ธ๋ถ ๋ณ์๋ฅผ ๋ฃ์ด์ผ ํฉ๋๋ค. (ESLint ๊ท์น ์ค์ ์ถ์ฒ)
React Hooks์ ์ฐธ์กฐ ๊ด๋ฆฌ ๋ฅ๋ ฅ์ ๋ง์คํฐํ๋ค๋ฉด, ์ฑ๋ฅ ๋ฌธ์ ์์ด ๋ณต์กํ๊ณ ๊ฑฐ๋ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ์ ์ผ๋ก ์ ์ดํ ์ ์๋ ์ง์ ํ React ์ ๋ฌธ๊ฐ๋ก ๊ฑฐ๋ญ๋ ๊ฒ์ ๋๋ค.

๋๊ธ ์ฐ๊ธฐ