๐ฅ [React] React.memo(), useCallback(), useMemo() ๋ฅผ ํ์ฉํ ์ต์ ํ๋ฅผ ํด๋ณด์
๊ฐ์
์ฝ๋๋ฅผ ์ง๋ ๊ฒ์ ๋ํ ์ฅ๋ฒฝ์ด ๋ฎ์์ง๊ณ ์๋ ์์ฆ,
์ฌ๋๋ค์ด ์๊ธฐ ์ฝ๋๋ฅผ ๊ฐ์ ํ๊ณ ์ต์ ํ ํ๋ ์ผ์๋ ์ํํํ๋ ๊ฒฝํฅ์ด ์๋ค.
๊ฐ๋จํ ์์ ๋ฅผ ๋ฐํ์ผ๋ก ์ฝ๋๋ฅผ ํ๋ฒ ๊ฐ์ ํด๋ณด์
๊ท์ฐฎ์ง๋ง ํด๋ณด์
React Profiler ์ค์น
์ผ๋จ ๋จผ์ ๊ตฌ๊ธ์์ ์ค์น๊ฐ ๊ฐ๋ฅํ React Profiler
๋ฅผ ํ์ฉํ ์์ ์ด๋ค.
์ค์น๋ฅผ ํ๋ ค๋ฉด ๋งํฌ ์ฐธ๊ณ
React.memo()
๋จผ์ React.memo()
๋ฅผ ํ์ฉํด๋ณด๊ธฐ ์ ์
React.memo()
๋ ๋ญ๊น?
๊ทธ๊ฑธ ์๋ ค๋ฉด ์ผ๋จ React
์ ๊ธฐ๋ณธ ๋์์ ๋์ง์ด๋ณด์์ผ ํ๋๋ฐ
React
๋ ๋จผ์ ์ปดํฌ๋ํธ๋ฅผ rendering
ํ ํ ์ด์ ์ rendering
๋ ๊ฒฐ๊ณผ๋ฅผ ๋น๊ตํด
DOM ์ ๋ฐ์ดํธ๋ฅผ ๊ฒฐ์ ํ๋ค (Virtual DOM). ๋ง์ฝ ์ด์ ๊ฒฐ๊ณผ๊ฐ ๋ค๋ฅด๋ฉด DOM ์ ์ ๋ฐ์ดํธ ํ๋ ์์ผ๋ก ๋์ํ๋ค.
์ด๋ React.memo()
๋ก ์์ฌ์์ผ๋ฉด React
๋ ์ปดํฌ๋ํธ๋ฅผ ์ฒ์ rendering
ํ ๋ ๋ฉ๋ชจ๋ฆฌ์ Memoizing
ํ๋ค.
๊ทธ ํ ๋ค์ rendering ๋ฐ์ ์ ์ปดํฌ๋ํธ์ props ๊ฐ ์ผ์นํ๋ค๋ฉด React ๋ Memoizing ํ ๊ฐ์
์ฌ์ฌ์ฉํ๋ค.
React ๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ๊ธฐ์ตํด ๋๋ค๊ฐ ๋ค์ ์ฌํ์ฉํ๋ ๊ฒ
์ ์ด์ ํจ์์ ๋ํด ์์๋ณด์์ผ๋ ์์๋ฅผ ๋ณด์
์์์ฝ๋
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export default function A({ message, posts }) {
return (
<div>
<h1>A Component</h1>
<p>{message}</p>
<ul>
{posts.map((post) => (
<li key={post.id}>
<p>{post.title}</p>
</li>
))}
</ul>
</div>
);
}
๋ชจ๋ ๊ฐ์ ํ๋ฒ์ ๋๋๋ง ํ๋ A-component
๊ฐ ์๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import React from "react";
export default function B({ message, posts }) {
return (
<div>
<h1>B Component</h1>
<Message message={message} />
<List posts={posts} />
</div>
);
}
const Message = ({ message }) => {
return <p>{message}</p>;
};
const ListItem = ({ post }) => {
return (
<li key={post.id}>
<p>{post.title}</p>
</li>
);
};
const List = ({ posts }) => {
return (
<ul>
{posts.map((post) => (
<ListItem key={post.id} post={post} />
))}
</ul>
);
};
์ด๋ฒ์ ๊ฐ๊ฐ ๋์์ ๋ถ๋ฆฌํ B-components
๊ฐ ์๋ค.
React Profiler
๋ฅผ ํตํด ๋๋๋ง ์๋๋ฅผ ๋น๊ตํด ๋ณด์
(์ ์ด๋ ๊ฒ ์ฐจ์ด๊ฐ ๋ ๊น?)
๋ฌธ์ ํ์
๋๋์ฒด ์ ์ด๋ฐ ์ฐจ์ด๊ฐ ๋ฐ์ํ์๊น?
์ค๋ น ์ฐจ์ด๊ฐ ๋๋๋ผ๋ B๊ฐ ๋ ๋นจ๋ผ์ผ ํ๋ ๊ฒ ์๋๊น?
์ถ์ง๋ง B ๊ฐ ๋ ๋๋ฆฐ ์ด์ ๋ props ๋ก ์ด๋ฏธ ๋ฐ์์จ ๊ฐ์ ํ์ ์ปดํฌ๋ํธ์
๋ฟ๋ฆฌ๊ณ ์๊ธฐ ๋๋ฌธ์ ๋๋๋ง ์ ์๋๊ฐ ๋ ์ง์ฐ๋๋ ์ํฉ์ด๋ค.
๊ทธ๋ ๊ธฐ์ ํด๊ฒฐ๋ฐฉ์์ ๊ฐ๋จํ๋ค.
์์ ์ปดํฌ๋ํธ์์ props ๋ก ์ฃผ๊ณ ์๋ ๊ฐ์ react ์์ ๊ธฐ์ต ํ๊ณ ์๋ค๊ฐ
๋์ผํ ๊ฐ์ด๋ฉด ๋๋๋ง์ ํ์ง ์์ผ๋ฉด ๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
์ด๋ฐ ์ํฉ์์ React.memo()
๋ฅผ ํ์ฉํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// React.memo() ๋ฅผ ์ ์ฉํ ๋ชจ์ต
import React from "react";
export default function B({ message, posts }) {
return (
<div>
<h1>B Component</h1>
<Message message={message} />
<List posts={posts} />
</div>
);
}
const Message = React.memo(({ message }) => {
return <p>{message}</p>;
});
const ListItem = React.memo(({ post }) => {
return (
<li key={post.id}>
<p>{post.title}</p>
</li>
);
});
const List = React.memo(({ posts }) => {
return (
<ul>
{posts.map((post) => (
<ListItem key={post.id} post={post} />
))}
</ul>
);
});
(๋๋๋ง ์๋๊ฐ ํ์ฐํ ์ค์ด๋ ๊ฒ์ด ๋ณด์ธ๋ค)
๊ทธ๋ ๋ค๊ณ ํด์ React.memo() ๋ฅผ ๋จ์ฉํด์๋ ์ ๋๋ค !
์ง์ํด์ผ ํ๋ ์ํฉ
๋๋๋ง ๋ ๋ props
๊ฐ ๋ค๋ฅธ ๊ฒฝ์ฐ๊ฐ ๋๋ถ๋ถ์ผ ๊ฒฝ์ฐ์๋ React.memo() ๋ ๋ณ
๋์์ด ๋์ง ๋ชปํ๋ค. ๊ทธ๋ ๋ค๊ณ ๋ชจ๋ ํจ์์ React.memo() ๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ
์๋ฌ๊ฐ ๋ฐ์ํ ์ ์๋ค๋ ๊ฒฝ๊ณ ๊ฐ ์์ผ๋ ์ ์ฌ ์ ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ค์ํ๋ค.
๋ฐ๋ผ์
React.memo() ๋ ์ฑ๋ฅ ๊ฐ์ ์ ์ํ ํ๋์ ๋๊ตฌ๋ก ์๊ฐํด์ผํ๋ค.
useCallback()
์๋ ์ปดํฌ๋ํธ๊ฐ ๋๋๋ง ๋ ๋๋ ๊ทธ ์์ ์๋ ํจ์๋ ๋ค์ ๋ง๋ค๊ฒ ๋๋๋ฐ,
๊ณ์ ๊ฐ์ ์ปดํฌ๋ํธ๊ฐ ๋๋๋ง ๋ ๋ ๋ง๋ค ๊ณ์ ๋ค์ ๋ง๋๋ ๊ฒ์ ์ข์ ํ์์ ์๋๋ค.
์ค๋ น ํด๋น ํจ์๊ฐ ํ์ ์ปดํฌ๋ํธ๋ก props
๋ฅผ ์ ๋ฌํ๋ ์ํฉ์ด๋ผ๋ฉด ํ์ ์ปดํฌ๋ํธ๋
๊ณ์ํด์ re-rendering
๋๋ ํ์์ด ๋ฐ์ํ๋ค.
๊ทธ๋ด ๋๋ useCallback()
์ผ๋ก ๊ฐ์ ํ ์ ์๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import React, { useCallback } from "react";
export default function B({ message, posts }) {
/**
* ํ์ ์ปดํฌ๋ํธ List ์ props ๋ก ๋ค์ด๊ฐ๋ ํจ์
*/
const tsetFunction = useCallback(() => {
console.log("TEST");
}, []);
// useEffect() ์ ์ฌ์ฉ๋ฐฉ๋ฒ์ด ๋น์ทํ๋ค.
return (
<div>
<h1>B Component</h1>
<Message message={message} />
<List posts={posts} tsetFunction={tsetFunction} />
</div>
);
}
const List = React.memo(({ posts, tsetFunction }) => {
return (
<ul>
{posts.map((post) => (
<ListItem key={post.id} post={post} />
))}
</ul>
);
});
์ฌ์ฉ ๋ฐฉ๋ฒ์ ๊ฐ๋จํ๋ฐ, useEffect()
์ฒ๋ผ ์ฌ์ฉํ๋ฉด ๋๋ค.
์ค๋ฅธ์ชฝ์ ์๋ ๋ฐฐ์ด์ ์์กด์ฑ์ด๋ฏ๋ก ํด๋น ํจ์๋ฅผ ๋ค์ ๋๋๋ง ํ ๋์ ์กฐ๊ฑด์ ์ถ๊ฐ ํด์ฃผ๋ฉด ๋๋ค.
useMemo()
useMemo()
๋ ๋ฐ์ง๊ณ ๋ณด๋ฉด Memoization
์ ๊ด๋ จ๋์ด ์๋๋ฐ,
๊ฐ๋จํ๊ฒ ์ค๋ช ํ์๋ฉด
์ด๋ฏธ ๋ถํ์ํ ๋๋๋ง์ด ๊ณ์ ์งํ ๋ ๋ ๋ณต์กํ ์ฐ์ฐ์์ด ์๋ค๋ฉด ๊ทธ ๊ฐ์ memoization
ํ๋ ๊ฒ์ด๋ค.
์์์ฝ๋
1
2
3
4
5
function Component({a, b}) {
const result = calculate(a, b);
return <div>{result}</div>;
}
๋ผ๋ ๊ฐ๋จํ ํจ์๊ฐ ์์ ๋ calculate
๋ผ๋ ์ฐ์ฐ ๊ฐ์ด
๋ณํ์ง ์์๋๋ฐ ๊ณ์ํด์ rendering
์ด ๋ฐ์ํด ๊ฐ์ ์ฐ์ฐ์ ๋ฐ๋ณตํ๋ค๋ฉด ์ข์ง ๋ชปํ๋ค.
๋ฐ๋ผ์ ์ด๋ด ๋ useMemo()
๋ฅผ ํ์ฉํด ์ธ๋ฐ ์๋ ์ฐ์ฐ์ ์ค์ผ ์ ์๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
1
2
3
4
5
function Component({a, b}) {
const result = useMemo(() => calculate(a, b), [a, b]);
return <div>{result}</div>;
}
์์ ์ค๋ช
ํ useCallback()
๊ณผ ์ผ๋งฅ์ํตํ๋ค.
useEffect()
์ฒ๋ผ ์ฌ์ฉํ๋ค๊ณ ์๊ฐํ๋ฉด ํธํ๋ค. ์ฐ์ธก์ ๋ฐฐ์ด์ ์์กด์ฑ์ ์ถ๊ฐ ํ๋ ๊ฒ์ด๋ค.
๋ง์น๋ฉฐ
React
์ ๋์๋ฐฉ์์ ์ํด ๋ถํ์ํ ๋๋๋ง์ด ๋ง์์ง์ ์ด์ ๋ฐ๋ฅธ ์ฑ๋ฅ ๊ฐ์ ์ ์ํด
์ฌ์ฉํ๋ ๊ฒ์ด Memoization
์ ํ์ฉํ๋๋ฐ
useMemo() | useCallback() |
---|---|
์ฐ์ฐ์ ๊ธฐ๋กํ ๋ | props ๋ ๋ถํ์ํ ํจ์๋ฅผ ์ค์ผ ๋ |
๋ก ํ์ฉํ๋ค๊ณ ์๊ฐํ๋ฉด ํธํ ๊ฒ ๊ฐ๋ค.
๋ค์์ ์์ ํ๋ก์ ํธ์์
ํด๋น ํ์ด์ง์์ ๋ฐฐ์ด Memoization
์ ํ์ฉํด ์ฑ๋ฅ ๊ฐ์ ์ ํด๋ณผ ์์ ์ด๋ค.
์ผ๋ง๋ ๊ฐ์ ์ด ๋๋์ง ์์ง์ ๊ฐ๋จํ ์ฝ๋์์๋ง ํ ์คํธ ํด๋ดค๋๋ฐ
์ถํ ์์ ํฐ ํ๋ก์ ํธ์์ ํ์ฉ์ ํ๋ค๋ฉด ์ผ๋ง๋ ๋ง์ ์๊ฐ ๋จ์ถ์ด ๋ ์ง ํฅ๋ฏธ๋กญ๋ค.
์์ง๊น์ง ์ฝ๋ ๊ฐ์ ๊ฒฝํ์ด ๋ชจ์๋ฅธ ์ง๊ธ ์ค์ํ ํ์ต ์ค ํ๋์๋ค๊ณ ์๊ฐํ๋ค.
์๊ฐ๋ณด๋ค ๊ฐ๋จํ๋๋ฐ ์ ์ํ์ง