ย
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 React.memo์ useCallback์ ์ฌ์ฉํ์ง ์์์ ๋7.4.2 React.memo์ useCallback์ ์ฌ์ฉํ ๋7.4.3 ์ต์ข
์ฝ๋
ย
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๋ props๊ฐ ์
๋ฐ์ดํธ๋๋ฉด ์ปดํฌ๋ํธ๋ ๋ฆฌ๋ ๋๋ง ๋๋๋ฐ, ๋ง์ฝ ์๋ ์ฝ๋์ฒ๋ผ ์ฌ์ฉ์๋ก๋ถํฐ ์
๋ ฅ๋ฐ๋ 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 ์ฌ์ฉ์ ์ฃผ์ํ ์ 

๊ทธ๋ฆผ 7-3
ย

ย
์คํํ๋ฉด์์ ๋ณผ ์ ์๋ฏ์ด 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์ ์ฌ์ฉํ์ฌ ์ฑ๋ฅ ์ต์ ํ ๋ฐ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ์ค์ด๋ ๊ฒ์ ๋ชฉ์ ์ ๋์์ผ๋ฉฐ, ์ฝ๋์ ๊ฐ๋
์ฑ์ ์ํด ์คํ์ผ๋ง ์ฝ๋๋ ์ ์ธํ๊ณ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
* 7.4.3 ์ต์ข
์ฝ๋์ ์คํ์ผ๋ง ์ฝ๋๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
* ์ด๋ฏธ์ง ์ถ์ฒ - WeNiv
ย

ย
2๋ฐฐ ์ฑ์ฅ!๐ช
ย ๋ฒํผ์ ๋๋ฅด๋ฉด, RealLicat
์ 2๋ฐฐ๋ก ํฌ๊ธฐ๊ฐ ์ปค์ง๊ณ <h2> ์์์ ํ์ฌ ์ํ ๊ฐ์ธ licatSize
๊ฐ ํ๋ฉด์ ๋ํ๋ฉ๋๋ค. ๐ฆ์ ์ธ์ฌ
๋๋ย ๐จ์ ์ธ์ฌ
๋ฒํผ์ ๋๋ฅด๋ฉด,ย Boolean ๊ฐ์ด true์ผ ๋ โ์๋
!โ ๋ฌธ๊ตฌ๊ฐ ๋ํ๋ฉ๋๋ค. React.memo์ useCallback์ ์ฌ์ฉํ์ง ์์์ ๋, ๋ฒํผ์ ๋๋ฅด๋ฉด ์ฝ์ ์ฐฝ์์ ์ด๋ค ์ผ๋ค์ด ๋ฒ์ด์ง๋์ง ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.ย
7.4.1 React.memo์ useCallback์ ์ฌ์ฉํ์ง ์์์ ๋
ย
import React, { useState, useEffect } 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 ( <> {say ? <div className="message">์๋ !</div> : null} <button onClick={toggle}>{who}์ ์ธ์ฌ</button> </> ); } // --- โ export default function App() { const [blue, setBlue] = useState(false); const [yellow, setYellow] = useState(false); const [licatSize, setLicatSize] = useState(50); const toggleBlue = () => setBlue(!blue); // --- โก const toggleYellow = () => setYellow(!yellow); const doubleLicat = () => setLicatSize(licatSize * 2); const RealLicat = () => { return ( <img src={licat} alt="๋ผ์ด์บฃ ์ด๋ฏธ์ง" style={{ width: `${licatSize}px`, height: `${licatSize}px` }} /> ); }; useEffect(() => { console.log("๋ผ์ด์บฃ์ด 2๋ฐฐ๋ก ์ปค์ก๋ค!"); }, [licatSize]); return ( <> <h2>๐ ํ์ฌ, ๋ผ์ด์บฃ์ ํค๋ {licatSize}px</h2> <button onClick={doubleLicat}>2๋ฐฐ ์ฑ์ฅ!๐ช</button> <div className="background"> <img src={building} alt="๋น๋ฉ" /> <RealLicat /> <div className="python-friends"> <div className="message-wrapper"> <Message who="๐ฆ" say={blue} toggle={toggleBlue} /> <Message who="๐จ" say={yellow} toggle={toggleYellow} /> </div> <img className="friends" src={friends} alt="ํ์ด์ฌ ์น๊ตฌ๋ค ์ด๋ฏธ์ง" /> </div> </div> </> ); }
ย

ย
๊ฐ๊ฐ์ ๋ฒํผ์ ํ ๋ฒ์ฉ ๋๋ ์ ๋, ํด๋น ๋ฒํผ๊ณผ ๊ด๋ จ์ด ์๋ ํจ์๋ ํจ๊ป ๋ฆฌ๋ ๋๋ง์ด ์ผ์ด๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
ย
7.4.2 React.memo์ useCallback์ ์ฌ์ฉํ ๋
ย
function Message({ who, say, toggle }) { console.log({ who, say }); return ( <> {say ? <div className="message">์๋ !</div> : null} <button onClick={toggle}>{who}์ ์ธ์ฌ</button> </> ); } const MemorizedMessage = React.memo(Message); // --- โ ... <div className="message-wrapper"> <MemorizedMessage who="๐ฆ" say={blue} toggle={toggleBlue} /> <MemorizedMessage who="๐จ" say={yellow} toggle={toggleYellow} /> </div>
ย
์ ์ฝ๋๋
who
, say
, toggle
์ props๋ก ๋ด๋ ค์ฃผ๋ Message
์ปดํฌ๋ํธ์ React.memo๋ก ๊ฐ์ธ์ฃผ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ์์ต๋๋ค. ๊ทธ ๊ฒฐ๊ณผ๋ก, props๊ฐ ๋ณ๊ฒฝ๋ ๋์๋ง ํจ์ ํธ์ถ์ด ์ด๋ฃจ์ด์ง๊ฒ ๋ฉ๋๋ค.ย
์ค์ต2์์๋
yellow
, blue
, licatSize
3๊ฐ์ state๋ฅผ ๋ค๋ฃน๋๋ค. ๋จผ์ , blue
์ ํจ์์๋ง useCallback์ ์ถ๊ฐํ์ฌ ๋ณํ๋ฅผ ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.ย
import React, { useState, useEffect, useCallback } from "react"; ... const toggleBlue = useCallback(() => setBlue(!blue), [blue]); // --- โก const toggleYellow = () => setYellow(!yellow);
ย
%25E1%2584%2589%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25AD%25E1%2586%25BC%25E1%2584%2592%25E1%2585%25A1%25E1%2586%25AF%25E1%2584%2584%25E1%2585%25A2.png?table=block&id=1ae76d4c-7df8-431b-8fe6-dda2f36c3ceb&cache=v2)
ย
2๋ฐฐ ์ฑ์ฅ!๐ช
ย ๋ฒํผ๊ณผ ๐ฆ์ ์ธ์ฌ
๋ฒํผ์ ๋๋ฅด๋ฉดย useCallback์ ์ฌ์ฉํ์ง ์์ ํจ์๋ ํจ๊ป ๋ฆฌ๋ ๋๋ง ๋๋ ๋ฐ๋ฉด, ๐จ์ ์ธ์ฌ
๋ฒํผ์ ๋๋ฅด๋ฉด useCallback์ ์ฌ์ฉํ ํจ์๋ ๋ฆฌ๋ ๋๋ง ๋์ง ์์ต๋๋ค.ย
useCallback์ ์ฌ์ฉํ์ง๋ง, React.memo๋ก ๊ฐ์ธ์ง ์์์ ๋

%25E1%2584%2589%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25AD%25E1%2586%25BC%25E1%2584%2592%25E1%2585%25A1%25E1%2586%25AF%25E1%2584%2584%25E1%2585%25A2%25E1%2584%258B%25E1%2585%25AAReact.memo%25E1%2584%2589%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25AD%25E1%2586%25BC%25E1%2584%2592%25E1%2585%25A1%25E1%2584%258C%25E1%2585%25B5%25E1%2584%258B%25E1%2585%25A1%25E1%2586%25AD%25E1%2584%258B%25E1%2585%25A1%25E1%2586%25BB%25E1%2584%258B%25E1%2585%25B3%25E1%2586%25AF%25E1%2584%2584%25E1%2585%25A2.png?table=block&id=b53482cc-58ee-4e5e-8d65-b9eed834f2d6&cache=v2)
๊ทธ๋ฆผ 7-9
%25E1%2584%2589%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25AD%25E1%2586%25BC%25E1%2584%2592%25E1%2585%25A1%25E1%2586%25AF%25E1%2584%2584%25E1%2585%25A2%25E1%2584%258B%25E1%2585%25AAReact.memo%25E1%2584%2589%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25AD%25E1%2586%25BC%25E1%2584%2592%25E1%2585%25A1%25E1%2584%258C%25E1%2585%25B5%25E1%2584%258B%25E1%2585%25A1%25E1%2586%25AD%25E1%2584%258B%25E1%2585%25A1%25E1%2586%25BB%25E1%2584%258B%25E1%2585%25B3%25E1%2586%25AF%25E1%2584%2584%25E1%2585%25A2.png?table=block&id=b53482cc-58ee-4e5e-8d65-b9eed834f2d6&cache=v2)
ย
๋ง์ง๋ง์ผ๋ก
yellow
์ licatSize
์ ํจ์์๋ useCallback์ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.ย
const toggleBlue = useCallback(() => setBlue(!blue), [blue]); const toggleYellow = useCallback(() => setYellow(!yellow), [yellow]); const doubleLicat = useCallback(() => setLicatSize(licatSize * 2), [licatSize]);
ย

ย
๊ฐ๊ฐ์ ๋ฒํผ์ ๋๋ ์ ๋, useCallback์ ์์กด์ฑ ๋ฐฐ์ด์ ๋ฃ์ ํด๋น state๊ฐ ๋ณํ์ ๋๋ง ๋ฆฌ๋ ๋๋ง ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. ์ฝ์ ์ฐฝ์์ ๋ณด์ด์ง๋ ์์ง๋ง,
setLicatSize
ํจ์์ useCallback์ ์ฌ์ฉํจ์ผ๋ก์จ ๊ด๋ จ ์๋ ๋ฒํผ์ ๋๋ ์ ๋ ์ด๋ฏธ์ง๊ฐ ํจ๊ป ๋ฆฌ๋ ๋๋ง ๋์ง ์์ต๋๋ค.ย
useCallback ์ฑํฐ๋ฅผ ๋๋ง์น๋ฉฐ, ์ฑ๋ฅ ์ต์ ํ์๋ ์ฝ๋์ ๋ณต์ก์ฑ, ์ ์ง๋ณด์์ ์ด๋ ค์, ๋ฉ๋ชจ๋ฆฌ ์ฆ๊ฐ ๋ฑ์ ๋จ์ ์ด ์์ ์ ์๊ธฐ ๋๋ฌธ์ ์ฅ๋จ์ ์ ๋น๊ตํ์ฌ useCallback์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
ย
7.4.3 ์ต์ข ์ฝ๋
ย
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 ( <> {say ? <div className="message">์๋ !</div> : null} <button onClick={toggle}>{who}์ ์ธ์ฌ</button> </> ); } const MemorizedMessage = React.memo(Message); export default function App() { const [blue, setBlue] = useState(false); const [yellow, setYellow] = useState(false); const [licatSize, setLicatSize] = useState(50); const toggleBlue = useCallback(() => setBlue(!blue), [blue]); const toggleYellow = useCallback(() => setYellow(!yellow), [yellow]); const doubleLicat = useCallback( () => setLicatSize(licatSize * 2), [licatSize] ); const RealLicat = () => { return ( <img src={licat} alt="๋ผ์ด์บฃ ์ด๋ฏธ์ง" style={{ width: `${licatSize}px`, height: `${licatSize}px` }} /> ); }; useEffect(() => { console.log("๋ผ์ด์บฃ์ด 2๋ฐฐ๋ก ์ปค์ก๋ค!"); }, [licatSize]); return ( <> <h2>๐ ํ์ฌ, ๋ผ์ด์บฃ์ ํค๋ {licatSize}px</h2> <button onClick={doubleLicat}>2๋ฐฐ ์ฑ์ฅ!๐ช</button> <div className="background"> <img src={building} alt="๋น๋ฉ" /> <RealLicat /> <div className="python-friends"> <div className="message-wrapper"> <MemorizedMessage who="๐ฆ" say={blue} toggle={toggleBlue} /> <MemorizedMessage who="๐จ" say={yellow} toggle={toggleYellow} /> </div> <img className="friends" src={friends} alt="ํ์ด์ฌ ์น๊ตฌ๋ค ์ด๋ฏธ์ง" /> </div> </div> </> ); }
h2, .python-friends, .message { display: inline-block; } h2 { margin-right: 10px; } .background { background-color : rgb(203, 228, 250); padding: 5px; } .friends { width: 280px; } .message { background-color: white; padding: 5px; border-radius: 5px; margin: 0 3px 0 10px; } .message-wrapper { text-align: center; }
ย