ย
7.1 useCallback์ด๋?7.1.1 ๊ธฐ๋ณธ ๊ตฌ์กฐ7.1.2 useMemo์์ ๋น๊ต7.2 useCallback์ ์ฌ์ฉํ๋ ์ด์ 7.2.1 useCallback์ผ๋ก ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์ ์ฌ์ฌ์ฉํ๊ธฐ 7.2.2 useCallback์ผ๋ก ์ฐธ์กฐ ๋์ผ์ฑ ๋ฌธ์ ํด๊ฒฐํ๊ธฐ7.3. (์ค์ต1) useCallback ์ฌ์ฉํด๋ณด๊ธฐ7.3.1 useCallback์ ์ฌ์ฉํ์ง ์์์ ๋7.3.2 useCallback์ ์ฌ์ฉํ ๋7.4. (์ค์ต2) useCallback ์ฌ์ฉํด๋ณด๊ธฐ7.4.1 ์ต์ข
์ฝ๋
ย
7.1 useCallback์ด๋?
ย
useCallback
์ useMemo
์ ๊ฐ์ด ์ปดํฌ๋ํธ์ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ํ์ฌ ์ฌ์ฉ๋๋ Hook์
๋๋ค. useCallback
์ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ๋ฐฉ์งํ๊ธฐ ์ํด ํน์ ํจ์๋ฅผ ์๋ก ๋ง๋ค์ง ์๊ณ ์ฌ์ฌ์ฉํ๊ณ ์ถ์ ๋ ์ฌ์ฉํฉ๋๋ค.ย
7.1.1 ๊ธฐ๋ณธ ๊ตฌ์กฐ
ย
const memoizedCallback = useCallback(() => {doSomething(a, b)},[a, b]);
ย
useCallback
์ ์์ ๊ฐ์ด ๋ ๊ฐ์ ์ธ์๋ฅผ ๋ฐ์ต๋๋ค. ์ฒซ๋ฒ์งธ ์ธ์๋ ๋ฉ๋ชจ์ด์ ์ด์
ํ ์ฝ๋ฐฑํจ์๋ฅผ, ๋๋ฒ์งธ ์ธ์๋ useEffect
, useMemo
์ ๊ฐ์ด ์์กด์ฑ ๋ฐฐ์ด์ด ์ ๋ฌ๋ฉ๋๋ค. useCallback
์ ๋ฉ๋ชจ์ด์ ์ด์
๋ ์ฝ๋ฐฑํจ์๋ฅผ ๋ฐํํ๋ฉฐ, ์ด ์ฝ๋ฐฑํจ์๋ ์์กด์ฑ ๋ฐฐ์ด์ ๊ฐ์ด ๋ณ๊ฒฝ๋์์ ๊ฒฝ์ฐ์๋ง ๊ฐฑ์ ๋ฉ๋๋ค. ๋ง์ฝ ์์กด์ฑ ๋ฐฐ์ด์ ๊ฐ์ด ๋์ผํ๋ค๋ฉด, ํด๋น ํจ์๋ฅผ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋๋๋ผ๋ ์๋ก์ด ํจ์๊ฐ ์์ฑ๋์ง ์๊ณ ๊ธฐ์กด ํจ์๊ฐ ๋ฐํ๋ฉ๋๋ค.ย
7.1.2 useMemo์์ ๋น๊ต
ย
useCallback
์ useMemo
๋ฅผ ์ฌ์ฉํด์ ํํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ย
const memoizedCallback = useCallback(function, deps); const memoizedValue = useMemo(() => function, deps);
ย
์์ ๋ ์ฝ๋๋ ๋์ผํฉ๋๋ค.
useCallback
์ useMemo
๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด์ก๊ธฐ ๋๋ฌธ์
๋๋ค. useCallback
์ useMemo
์์ ๊ฐ์ด ์๋ ํจ์๋ฅผ ์ฌ์ฉํ ๋์ ํธ์์ฑ์ ์ฆ์ง์ํจ Hook์
๋๋ค. ๋ Hook์ ์ฑ๋ฅ ์ต์ ํ๋ผ๋ ๋ชฉ์ ์์๋ ๊ณตํต์ ์ ๊ฐ์ง๋ง, ํน์ ๊ฐ์ ์ฌ์ฌ์ฉํ ๊ฒ์ธ์ง ํน์ ํน์ ํจ์๋ฅผ ์ฌ์ฌ์ฉํ ๊ฒ์ธ์ง์ ๋ฐ๋ผ ์ ํ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. useMemo
๋ ๊ฐ์ ์ฌ์ฌ์ฉ์ ์ํด ์ ๋ฌ๋ ํจ์๋ฅผ ์คํํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ๋ชจ์ด์ ์ด์
ํ์ง๋ง, useCallback
์ ํจ์์ ์ฌ์ฌ์ฉ์ ์ํด ์ ๋ฌ๋ ํจ์ ์์ฒด๋ฅผ ๋ฉ๋ชจ์ด์ ์ด์
ํฉ๋๋ค. ย
ย
7.2 useCallback์ ์ฌ์ฉํ๋ ์ด์
ย
useCallback
์ ์ฌ์ฉํ๋ฉด ๋งค๋ฒ ํจ์๋ฅผ ์์ฑํ์ง ์๊ณ ๊ธฐ์ตํ๊ฒ ํด๋์๋ค๊ฐ ํ์ํ ๋๋ง๋ค ํจ์๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค. ํจ์๋ฅผ ์์ฑํ๋ ๊ฒ๋ง์ผ๋ก๋ ๋ฉ๋ชจ๋ฆฌ๋ CPU์ ๋ฆฌ์์ค๋ฅผ ๋ง์ด ์ฐจ์งํ๋ ์์
์ด๋ผ๊ณ ํ ์ ์์ต๋๋ค. ํ์ง๋ง props๊ฐ ๋ฐ๋์ง ์์์ ๋, React์ ๊ฐ์ ๋(Virtual DOM)์ ๋ฆฌ๋ ๋๋ง์ ํ์ง ์๊ณ ์ด์ ๊ฒฐ๊ณผ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ๋๋ง ์๊ฐ์ ์ค์ผ ์ ์์ต๋๋ค.ย
useCallback
์ด ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ๋ ๋ํ์ ์ผ๋ก ๋ ๊ฐ์ง๊ฐ ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์๋ฅผ ์ฌ์ฌ์ฉํ ๋, ๋ ๋ฒ์งธ๋ ์ฐธ์กฐ ๋์ผ์ฑ์ด ์ ์ง๋์ง ์์ ์๊ธฐ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๋์
๋๋ค. ย
7.2.1 useCallback์ผ๋ก ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์ ์ฌ์ฌ์ฉํ๊ธฐ
ย
๊ธฐ๋ณธ์ ์ผ๋ก ์ปดํฌ๋ํธ ์์์ state๋ proprs๊ฐ ์
๋ฐ์ดํธ๋๋ฉด ์ปดํฌ๋ํธ๋ ๋ฆฌ๋ ๋๋ง ๋๋๋ฐ, ๋ง์ฝ ์๋ ์ฝ๋์ฒ๋ผ ์ฌ์ฉ์๋ก๋ถํฐ ์
๋ ฅ๋ฐ๋ input ํ๊ทธ๊ฐ์ด ์
๋ฐ์ดํธ๊ฐ ์ฆ์ state๊ฐ ์๋ ์ปดํฌ๋ํธ๋ผ๋ฉด ๋งค๋ฒ ์๋กญ๊ฒ ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์๊ฐ ์์ฑ๋ฉ๋๋ค.
ย
import React, { useState } from "react"; function InputId() { const [id, setId] = useState(""); const onChangeId = (e) => { setId(e.target.value); }; return <input onChange={onChangeId} />; } export default InputId;
์ด๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํด ๋ฐ๋ณตํด์ ์์ฑ๋๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์๋ฅผ
useCallback
์ผ๋ก ๊ฐ์ธ์ฃผ๋ฉด ํจ์๋ฅผ ๋ฉ๋ชจ์ด์ ์ด์
ํ์ฌ, ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋๋๋ผ๋ ์์กดํ๋ ๊ฐ๋ค์ด ๋ฐ๋์ง ์๋ ํ ๊ธฐ์กด ํจ์๋ฅผ ๊ณ์ํด์ ๋ฐํํฉ๋๋ค. ย
import React, { useCallback, useState } from "react"; function InputId() { const [id, setId] = useState(""); // useCallback ์ฌ์ฉ const onChangeId = useCallback( e => { setId(e.target.value); }, []); return <input onChange={onChangeId} />; } export default InputId;
ย
7.2.2 useCallback์ผ๋ก ์ฐธ์กฐ ๋์ผ์ฑ ๋ฌธ์ ํด๊ฒฐํ๊ธฐ
ย
useEffect
์ ์์กด์ฑ ๋ฐฐ์ด์ ํจ์๊ฐ ๋ค์ด๊ฐ๋ฉด, ํจ์๋ ๊ฐ์ฒด ํ์
์ด๊ธฐ ๋๋ฌธ์ ์ฑํฐ6(์ค์ต2)์์ ๋ดค๋ ์ฐธ์กฐ ๋์ผ์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค. ์์์๋ ๊ฐ์ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด์ useMemo
๋ฅผ ํตํด ๋ฉ๋ชจ์ด์ ์ด์
ํ๋ค๋ฉด ์ด๋ฒ์๋ ํจ์๋ฅผ ์ฌ์ฌ์ฉํด์ผ ํ๋ฏ๋ก useCallback
์ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค. ย
import React, { useState, useEffect } from "react"; function UserProfile({ id }) { const [user, setUser] = useState(null); const fetchUserInfo = () => fetch(`https://user-api.com/users/${Id}`) .then((response) => response.json()) .then(({ user }) => user); useEffect(() => { fetchUserInfo().then((user) => setUser(user)); }, [fetchUserInfo]); ... }
ย
์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ,
useEffect
์ ์์กด์ฑ ๋ฐฐ์ด์ fetchUserInfo
ํจ์๊ฐ ๋ค์ด์์ผ๋ฏ๋ก fetchUserInfo
๊ฐ ๋ณ๊ฒฝ๋ ๋ API๋ฅผ ํธ์ถํฉ๋๋ค. ๊ทธ๋ฐ๋ฐ ๊ฐ์ฒด ํ์
์ธ fetchUserInfo
๋ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋๋ฉด ์๋ก์ด ์ฐธ์กฐ ๊ฐ์ผ๋ก ๋ณ๊ฒฝ๋ฉ๋๋ค. fetchUserInfo
์ ์ฐธ์กฐ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด useEffect
๊ฐ ๋ค์ ์คํ๋๊ณ , state์ธ user ๊ฐ์ด ์
๋ฐ์ดํธ๋์ด ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋ฉ๋๋ค. ์ด๋ก ์ธํด ๋ฐ์ํ๋ ๋ฌดํ ๋ฃจํ๋ฅผ useCallback
์ผ๋ก ํด๊ฒฐํด๋ณด๊ฒ ์ต๋๋ค. ย
import React, { useState, useEffect, useCallback } from "react"; function UserProfile({ id }) { const [user, setUser] = useState(null); // useCallback์ ์ฌ์ฉํ ์์ const fetchUserInfo = useCallback( () => fetch(`https://user-api.com/users/${id}`) .then((response) => response.json()) .then(({ user }) => user), [id] ); useEffect(() => { fetchUserInfo().then((user) => setUser(user)); }, [fetchUserInfo]); ... }
ย
useCallback
์ผ๋ก ํจ์๋ฅผ ๊ฐ์ธ์ฃผ๋ฉด ํด๋น ํจ์๋ ์ด๋ฏธ ๋ฉ๋ชจ์ด์ ์ด์
๋์๊ธฐ ๋๋ฌธ์ ์์กด์ฑ ๋ฐฐ์ด๋ก ๋ฃ์ด์ค id
๋ฅผ ๋ณ๊ฒฝํ์ง ์๋ ํ ์ปดํฌ๋ํธ๋ ๋ฆฌ๋ ๋๋ง๋์ง ์์ต๋๋ค.ย
ย
7.3. (์ค์ต1) useCallback ์ฌ์ฉํด๋ณด๊ธฐ
ย
useCallback
์ ์ฌ์ฉ๋ฒ๊ณผ ์ฌ์ฉ์๊ธฐ๋ฅผ ํ์ธํด๋ณด๊ณ ์ ๊ฐ๋จํ ์์ ๋ฅผ ํตํด useCallback
์ ์ฌ์ฉํ์ง ์์์ ๋์ ์ฌ์ฉํ์ ๋๋ฅผ ๋น๊ตํด๋ณด๊ฒ ์ต๋๋ค. ํด๋น ์์ ์์๋ ํ ๊ธ ๋ฒํผ์ ์ฌ์ฉํ์ฌ bool
๊ฐ์ ๋ฐ๋ผ ๋ผ์ด์บฃ์ ์ธ์ถ ์ํ๋ฅผ ๋ณ๊ฒฝ์ํค๋๋ฐ, ์ํ๊ฐ์ด true
์ผ ๊ฒฝ์ฐ โ์ง์์์ด์!โ, false
์ผ ๊ฒฝ์ฐ โ์ธ์ถํ์ด์!โ๋ผ๋ ๋ฌธ๊ตฌ์ ์ด๋ฏธ์ง๋ก ์ฝ๊ฒ ๋ผ์ด์บฃ์ ์ํ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.ย
7.3.1 useCallback์ ์ฌ์ฉํ์ง ์์์ ๋
ย
import { useState, useEffect, useCallback } from "react"; import goLicat from "./go.jpg"; import backLicat from "./back.jpg"; function App() { const [locationToggle, setLocationToggle] = useState(false); const licatLocation = () => { console.log( locationToggle ? "๐ ํ์ฌ getLocation๊ฐ์ true(์ง์์์ด์!)" : "๐ ํ์ฌ getLocation๊ฐ์ false(์ธ์ถํ์ด์!)" ); return; }; useEffect(() => { console.log("licatLocation ํจ์ ํธ์ถ!"); }, [licatLocation]); return ( <> <h2>๐ ๋ผ์ด์บฃ ์ง๊ธ ์ง์ ์๋์?</h2> <div> {locationToggle ? ( <img src={backLicat} alt="์ง์ ๋ค์ด๊ฐ ๋ผ์ด์บฃ" /> ) : ( <img src={goLicat} alt="์ธ์ถํ ๋ผ์ด์บฃ" /> )} </div> <h3> ๋ผ์ด์บฃ์ ์ง๊ธ {locationToggle ? " '์ง์์์ด์!'" : " '์ธ์ถํ์ด์!'"} </h3> <button onClick={() => setLocationToggle(!locationToggle)} style={{ margin: "-5px 10px 0 0", fontSize: "14px", }} > ๐ฆ ๋ผ์ด์บฃ ์ด๋! </button> <button onClick={licatLocation} style={{ fontSize: "14px" }}> ๐ ํ์ฌ getLocation๊ฐ </button> </> ); } export default App;
ย
์ ์์ ๋
๋ผ์ด์บฃ ์ด๋!
๋ฒํผ์ ๋๋ฌ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค locationToggle
๋ณ์์ ๋ณ๊ฒฝ๋ ๊ฐ์ ๋ฐ์ํด์ฃผ๊ณ , ํ์ฌ getLocation๊ฐ
๋ฒํผ์ ๋๋ ์ ๋ licatLocation
ํจ์๋ฅผ ํธ์ถํ์ฌ ์ฝ์์ ์ํ ๊ฐ์ ์ถ๋ ฅํด์ค๋๋ค. ๋ง์ฝ ์ํฉ์ ๋ฐ๋ผ licatLocation
ํจ์์ ๋ณํ๊ฐ ์์ ๋๋ง ์คํ๋๋ useEffect
๋ฅผ ์ถ๊ฐํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ธด๋ค๋ฉด, ์ด๋ค ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๊น์?ย
ย
์ฒ์ ํ์ด์ง๊ฐ ๋ ๋๋ง๋๋ฉด,
useEffect
๊ฐ ๋ง์ดํธ๋ฉ๋๋ค. ์ฝ์์ฐฝ์ ๋ณด์ด๋ ๋ฉ์ธ์ง๋ useEffect
๊ฐ ์คํ๋ ๋๋ง๋ค ์ถ๋ ฅ๋ฉ๋๋ค. ์ด์ ๋ผ์ด์บฃ์ ์ธ์ถ ์ํ๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ์ํด ๋ผ์ด์บฃ ์ด๋!
๋ฒํผ์ ๋๋ฌ๋ณด๊ฒ ์ต๋๋ค. ย
ย
๋ถ๋ช
๋ผ์ด์บฃ ์ด๋!
๋ฒํผ๋ง ํด๋ฆญํ๊ธฐ ๋๋ฌธ์ licatLocation
ํจ์์๋ ์ํฅ์ด ์์ด licatLocation
ํจ์๋ฅผ ์์กดํ๋ useEffect
๋ ์คํ๋์ง ์์ ๊ฑฐ๋ผ๊ณ ์์ํ๊ณ ์์์ ๊ฒ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ useEffect
๋ ๊ฐ์ด ์คํ๋๊ณ ์๋ ๊ฑธ๊น์?ย
๊ทธ ๋ต์ React ๋ฆฌ๋ ๋๋ง ์กฐ๊ฑด ์ค state ๊ฐ์ด ๋ณํ๋ฉด ์ปดํฌ๋ํธ ์ ์ฒด๊ฐ ๋ฆฌ๋ ๋๋ง๋๊ณ , ํจ์๊ฐ ๋ค์ ์์ฑ๋์ด ์๋ก์ด ์ฃผ์ ๊ฐ์ ์ฐธ์กฐํ๋ ์ฐธ์กฐ ๋์ผ์ฑ ๋ฌธ์ ๋ฅผ ํตํด ์ฐพ์ ์ ์์ต๋๋ค. ์ง๊ธ ์์ ์ฒ๋ผ ๊ฐ๋จํ ์ํฉ์์๋ ๋ฆฌ๋ ๋๋ง์ด ๊ณ์ ๋ฐ์ํด๋ ์ฑ๋ฅ์ ํฌ๊ฒ ์ํฅ์ด ์์ง๋ง, ๋ง์ฝ ํธ์ถํ๋ ํจ์๊ฐ ๋งค์ฐ ๋ฌด๊ฑฐ์ด ๋ก์ง์ ๊ฐ์ง๊ณ ์๋ค๋ฉด ์์์ด ๋ฐ๋ณต๋๋ ๋ฆฌ๋ ๋๋ง์ ๋งค์ฐ ๋นํจ์จ์ ์ผ ๊ฒ์
๋๋ค.
ย
์ด๋ด ๋
useCallback
์ ์ฌ์ฉํฉ๋๋ค. ์ฌ์ฌ์ฉํ ํจ์๋ฅผ useCallback
์ ์ฝ๋ฐฑํจ์๋ก ๋ฃ์ด ๋ฉ๋ชจ์ด์ ์ด์
ํด์ฃผ๋ฉด, ์ด์ state ๊ฐ์ด ๋ณํด๋ licatLocation
ํจ์์ ๋ณํ๊ฐ ์์ ๋ useEffect
๋ ์คํ๋์ง ์์ ๋ฆฌ๋ ๋๋ง์ด ์ผ์ด๋์ง ์๊ฒ ๋ฉ๋๋ค.ย
7.3.2 useCallback์ ์ฌ์ฉํ ๋
const licatLocation = useCallback(() => { console.log( locationToggle ? "๐ ํ์ฌ getLocation๊ฐ์ true(์ง์์์ด์!)" : "๐ ํ์ฌ getLocation๊ฐ์ false(์ธ์ถํ์ด์!)" ); return; }, []); // ๋น ๋ฐฐ์ด์ ๋ฃ์์ ๋
ย
useCallback ์ฌ์ฉ์ ์ฃผ์ํ ์
์คํํ๋ฉด์์ ๋ณผ ์ ์๋ฏ์ด
useCallback
์ผ๋ก licatLocation
ํจ์๋ฅผ ๊ฐ์ธ์ค ๊ฒฐ๊ณผ useEffect
๋ ๋ ์ด์ ์คํ๋์ง ์์ง๋ง, ํ์ฌ locationToggle
์ ์ ์ฅ๋ state ๊ฐ์ true
์์๋ ๋ถ๊ตฌํ๊ณ licatLocation
ํจ์๋ ๊ณ์ํด์ false
๊ฐ์ ๋ณด์ฌ์ฃผ๊ณ ์์ต๋๋ค.
์ด๋ฐ ์ํฉ์ ์์กด์ฑ ๋ฐฐ์ด์ ๋น ๋ฐฐ์ด๋ก ์ฃผ๊ฒ ๋ ๋ ๋ง๋ ์ ์์ต๋๋ค. ์์กด์ฑ ๋ฐฐ์ด์ ์๋ฌด ์กฐ๊ฑด๋ ์ฃผ์ง ์๋๋ค๋ฉด, ์ฒ์ ๋ ๋๋ง๋ ๋์ state ๊ฐ์ด ๊ทธ๋๋ก ๋ฉ๋ชจ์ด์ ์ด์
๋ฉ๋๋ค. ๋ฆฌ๋ ๋๋ง์ ํด์ค ์กฐ๊ฑด์ด ์์ด์ ๊ณ์์ฒ์ ์ ์ฅ๋ ์ํ ๊ทธ๋๋ก๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ๋๋ฌธ์
๋๋ค. ์์ ์ํฉ๋ ์ฝ๋ฐฑํจ์๊ฐ ๋ฉ๋ชจ์ด์ ์ด์
๋ ๋ locationToggle
๊ฐ์ด false
๋ก ์ ์ฅ๋ ์ํฉ์ด์์ต๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ useCallback
์ ์ฌ์ฉํ ๋๋ ์์กด์ฑ ๋ฐฐ์ด์ ๋ฆฌ๋ ๋๋ง์ ์ํ ์กฐ๊ฑด์ ๋ฐ๋์ ๋ฃ์ด์ค์ผ ํฉ๋๋ค.ย
๋ฆฌ๋ ๋๋ง์ ์ํ ์กฐ๊ฑด์ธ
locationToggle
๊น์ง ๋ฃ์ด์ฃผ๊ณ , ๋ค์ ์ฝ๋๋ฅผ ์คํ์์ผ ๋ด
์๋ค.ย
const licatLocation = useCallback(() => { console.log( locationToggle ? "๐ ํ์ฌ getLocation๊ฐ์ true(์ง์์์ด์!)" : "๐ ํ์ฌ getLocation๊ฐ์ false(์ธ์ถํ์ด์!)" ); return; }, [locationToggle]); // ๊ฐ์ ๋ฃ์์ ๋
ย
ย
์ฝ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํด๋ณด๋ฉด,
๋ผ์ด์บฃ ์ด๋!
๋ฒํผ์ ํด๋ฆญํ์ ๋๋ง๋ค 'licatLocation ํจ์ ํธ์ถ!' ๋ฉ์ธ์ง๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค. ๋ํ state ๊ฐ์ ๋ฐ๋ผ ์ผ์ชฝ ํ๋ฉด์ ์ถ๋ ฅ๋๋ state ๊ฐ๊ณผ licatLocation
ํจ์๊ฐ ๊ฐ์ง๊ณ ์๋ state ๊ฐ์ด ์ผ์นํ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. ย
ย
7.4. (์ค์ต2) useCallback ์ฌ์ฉํด๋ณด๊ธฐ
ย
์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง ๋ ๋ ์์ ์ปดํฌ๋ํธ๋ ๋ ๋๋ง ๋ฉ๋๋ค. ๋ง์ฝ props๊ฐ ๊ฐ์ ์ฃผ์์ผ ๊ฒฝ์ฐ, ์ฃผ์๋ฅผ ๋น๊ตํ๊ณ ๋ฆฌ๋ ๋๋งํ๋ React.memo๋ฅผ ๊ฐ์ธ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด๋ฒ ์ค์ต์์๋, React.memo์ useCallback Hook์ ์ฌ์ฉํ์ฌ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ์ค์ด๋ ๊ฒ์ ๋ชฉ์ ์ ๋์์ผ๋ฉฐ, ์ฝ๋์ ๊ฐ๋
์ฑ์ ์ํด ์คํ์ผ๋ง ์ฝ๋๋ ์ ์ธํ๊ณ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
* 7.4.1 ์ต์ข
์ฝ๋์ ์คํ์ผ๋ง ์ฝ๋๊ฐ ๋ชจ๋ ํฌํจ๋์ด ์์ต๋๋ค.
ย
// ----- (1) function App() { //useState const [yellowSay, setYellowSay] = useState(false); const [blueSay, setBlueSay] = useState(true); const [licatSize, setLicatSize] = useState(50); const toggleYellow = () => setYellowSay(!yellowSay); ----- (2) const toggleBlue = () => setBlueSay(!blueSay); const licatStyle = { width: `${licatSize}px`, height: `${licatSize}px`, }; // ๋ผ์ด์บฃ ์คํ์ผ, ์ด๋ฏธ์ง, useEffect๋ฅผ ๋ฐํํ๋ RealLicat ์ปดํฌ๋ํธ const RealLicat = ({ licatSize }) => { useEffect(() => { console.log("์ปค์ ธ๋ผ, ๋ผ์ด์บฃ!"); }, [licatSize]); return <img src={licat} alt="๋ผ์ด์บฃ์ด๋ฏธ์ง" style={licatStyle} />; }; return ( <> <h2>๐ ๋ผ์ด์บฃ์ ํ์ฌ ํค๋ {licatSize}px</h2> <img src={building} alt="๋น๋ฉ" /> <button onClick={() => setLicatSize(licatSize * 2)}>๐ช</button> <RealLicat /> <MemoMessage who="๐ฆ" say={blueSay} toggle={toggleBlue} /> <MemoMessage who="๐จ" say={yellowSay} toggle={toggleYellow} /> <img src={friends} alt="ํ์ด์ฌ ์น๊ตฌ๋ค" /> </> ); }
๐ช
ย ๋ฒํผ์ ๋๋ฅด๋ฉด, RealLicat์ 2๋ฐฐ๋ก ํฌ๊ธฐ๊ฐ ์ปค์ง๊ณ <h2>์์์ ํ์ฌ ์ํ๊ฐ์ด ๋ํ๋ฉ๋๋ค. ๐ฆ์ ์ธ์ฌ
๋๋ ๐จ์ ์ธ์ฌ
๋ฒํผ์ ๋๋ฅด๋ฉด, Boolean ๊ฐ์ ๋ฐ๋ผ โ์๋
~โ ๋๋ โ๋ผ์ด์บฃ!โ์ ๋ฌธ๊ตฌ๊ฐ ๋ํ๋๊ฒ ๋ฉ๋๋ค. React.memo์ useCallback์ ์ฌ์ฉํ์ง ์์์ ๋, ๋ฒํผ์ ๋๋ฅด๋ฉด ์ฝ์์ฐฝ์์ ์ด๋ค ์ผ๋ค์ด ๋ฒ์ด์ง๋์ง ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.ย
๊ฐ๊ฐ์ ๋ฒํผ์ ํ๋ฒ์ฉ ๋๋ ์ ๋ฟ์ธ๋ฐ, ํด๋น ๋ฒํผ๊ณผ ๊ด๋ จ์ด ์๋ ํจ์๋ ํจ๊ป ๋ฆฌ๋ ๋๋ง์ด ์ผ์ด๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
ย
function Message({ who, say, toggle }) { console.log({ who, say }); return ( <> <div className="message">{say ? "๋ผ์ด์บฃ!" : "์๋ ~"}</div> <button onClick={toggle}>{who}์ ์ธ์ฌ</button> </> ); } const MemoMessage = React.memo(Message);
์ ์ฝ๋๋
who
, say
, toggle
์ props๋ก ๋ด๋ ค ์ฃผ๋ Message ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ , React.memo๋ก ๊ฐ์ธ์ฃผ์์ต๋๋ค. ๊ฒฐ๊ณผ๋ก, props๊ฐ ๋ณ๊ฒฝ๋ ๋์๋ง ํจ์ ํธ์ถ์ด ์ด๋ฃจ์ด์ง๊ฒ ๋ฉ๋๋ค.ย
์ค์ต2์์๋
yellowSay
, blueSay
, licatSize
3๊ฐ์ state๋ฅผ ๋ค๋ฃน๋๋ค. ๋จผ์ , yellowSay
์ blueSay
state์๋ง useCallback Hook์ ์ถ๊ฐํ์ฌ ๋ณํ๋ฅผ ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.// ์ด์ ์ฝ๋ const toggleYellow = () => setYellowSay(!yellowSay); const toggleBlue = () => setBlueSay(!blueSay); // useCallback์ ์ถ๊ฐํ ์ฝ๋ const toggleYellow = useCallback(() => setYellowSay(!yellowSay), [yellowSay]); const toggleBlue = useCallback(() => setBlueSay(!blueSay), [blueSay]);
๐ช
ย ๋ฒํผ์ ๋๋ฅด๋ฉด, ์ฝ์์ฐฝ์๋ โ์ปค์ ธ๋ผ, ๋ผ์ด์บฃ!โ ๋ฌธ๊ตฌ๋ง ๋ํ๋ฉ๋๋ค. ๐ฆ์ ์ธ์ฌ
ย ๋ฒํผ๋ ๋๋ฌ๋ณด๊ฒ ์ต๋๋ค. useCallback์ ์ฌ์ฉํ์ง ์์ licatSize
๋ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ด ์ผ์ด๋ฌ์ง๋ง, ๋๋ฒ์งธ ์ธ์์ ๋ณ์๋ฅผ ์ง์ ํ useCallback์ ํด๋น ๋ฒํผ์ ํด๋ฆญํ ๊ฒ๋ง ๋ฆฌ๋ ๋๋ง ๋์์ต๋๋ค.ย
useCallback Hook ์ฑํฐ๋ฅผ ๋๋ง์น๋ฉฐ, ์ฑ๋ฅ ์ต์ ํ์๋ ์ฝ๋์ ๋ณต์ก์ฑ, ์ ์ง๋ณด์์ ์ด๋ ค์, ๋ฉ๋ชจ๋ฆฌ ์ฆ๊ฐ ๋ฑ์ ๋จ์ ์ด ์์ ์ ์๊ธฐ ๋๋ฌธ์ ๋จ์ ๊ณผ ์ฅ์ ์ ๋น๊ตํ์ฌ useCallback์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
7.4.1 ์ต์ข ์ฝ๋
import React, { useState, useEffect, useCallback } from "react"; import "./style.css"; import licat from "./licat.png"; import friends from "./friends.png"; import building from "./building.png"; function Message({ who, say, toggle }) { console.log({ who, say }); return ( <> <div className="message">{say ? "๋ผ์ด์บฃ!" : "์๋ ~"}</div> <button onClick={toggle}>{who}์ ์ธ์ฌ</button> </> ); } Message = React.memo(Message); export default function App() { const [yellowSay, setYellowSay] = useState(false); const [blueSay, setBlueSay] = useState(true); const [licatSize, setLicatSize] = useState(50); const toggleYellow = useCallback(() => setYellowSay(!yellowSay), [yellowSay]); const toggleBlue = useCallback(() => setBlueSay(!blueSay), [blueSay]); const licatStyle = { width: `${licatSize}px`, height: `${licatSize}px`, }; const RealLicat = ({ licatSize }) => { useEffect(() => { console.log("์ปค์ ธ๋ผ, ๋ผ์ด์บฃ!"); }, [licatSize]); return <img src={licat} alt="๋ผ์ด์บฃ์ด๋ฏธ์ง" style={licatStyle} />; }; return ( <> <h2>๐ ๋ผ์ด์บฃ์ ํ์ฌ ํค๋ {licatSize}px</h2> <div className="background"> <img src={building} alt="๋น๋ฉ" /> <div className="bigger-licat"> <button onClick={() => setLicatSize(licatSize * 2)}>๐ช</button> <RealLicat /> </div> <div className="python-friends"> <div> <Message who="๐ฆ" say={blueSay} toggle={toggleBlue} /> <Message who="๐จ" say={yellowSay} toggle={toggleYellow} /> </div> <img src={friends} alt="ํ์ด์ฌ ์น๊ตฌ๋ค" /> </div> </div> </> ); }
.background { background-color: rgb(203, 228, 250); display: flex; flex-direction: row; } .bigger-licat, .python-friends { display: flex; flex-direction: column; align-self: flex-end; } .message { background-color: white; display: inline-block; padding: 5px; border-radius: 5px; margin: 10px 3px 10px 65px; }
ย
ย
ย
ย
ย
ย
ย
ย
ย
ย
ย
ย
ย
ย
ย
ย
ย
ย
ย
[๋ชฉ์ฐจ]
- ์ ์(useMemo์ ์ฝ๋ ๋น๊ต) - ๋ฏผ์ ๋
- ์ฌ์ฉ ์ด์ (+์ฅ์ )/์ฌ์ฉํด์ผ ํ ๋ (์์ : ๊ฐ์ ํ๊ธฐ ์ ์ฝ๋ , useCallback์ผ๋ก ๊ฐ์ ํ ์ฝ๋) - ํ์ค๋
- useCallback ์ฌ์ฉํด๋ณด๊ธฐ - ์น๋ฏธ, ์งํด๋
3.1 useCallback ์ฌ์ฉ๋ฒ (์์ ๊ธฐ๋ณธ ๋ฌธ๋ฒ! ๋ฌธ๋ฒ์!)
3.2 useCallback ์์ (+์์กด์ฑ ๋ฐฐ์ด์ state๊ฐ์ด ๋ณํ์ง ์์์ ๋๋ฅผ ์์๋ก ์ฃผ์์ฌํญ ์ ์ด์ฃผ๊ธฐ) -> input ์์
3.3 useCallback ์์ 2 -> ๋ผ์ด์บฃ ์ปค์ง๊ธฐ
3.4 ๋ง๋ฌด๋ฆฌ(useCallback์ ์ฌ์ฉํ๋ฉด ์๋๋ ์ํฉ ๊ฐ๋จํ๊ฒ ๋งํด์ฃผ๊ธฐ)
ย
์น๋ฏธ๋ : useCallback ์ฌ์ฉ ์ ํ + ์ฝ์์(์์กด์ฑ๋ฐฐ์ด ๊ด๋ จ ์ฃผ์์ฌํญ)
์งํด๋ : useMemo์ ๊ฐ์ด ์ฌ์ฉํ๋ ๋ถ๋ถ ์ถ๊ฐ
ย
ย