๐จ 03. ๋ถ๋ณ์ฑ(Immutability)๊ณผ ๋ ๋ ํธ๋ฆฌ๊ฑฐ โ ํ๋ฉด์ด ์ ์ ๋ณํ์ฃ ?
๐ ๊ฐ์
๊ฐ์ฒด์ ๋ฐฐ์ด ์ํ๋ฅผ ๋ค๋ฃฐ ๋ ์ ์คํ๋ ๋ ๋ฌธ๋ฒ(...)์ด ํ์ํ์ง, ๋ถ๋ณ์ฑ์ ์งํค์ง ์์ผ๋ฉด ์ผ์ด๋๋ ์ฐธ์ฌ๋ฅผ ๋ฐฐ์๋๋ค.
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
- ๋ฆฌ์กํธ๊ฐ ๋ ๋๋ง์ ์์ํ ์ง ๋ง์ง ๊ฒฐ์ ํ๋ ๊ธฐ์ค(
Object.is๋๋ฑ์ฑ ๋น๊ต)์ ์ค๋ช ํ ์ ์๋ค.- ์ํ์ ๋ฐฐ์ด์ด๋ ๊ฐ์ฒด์ ์๋ณธ์ ํผ์(Mutate)ํ์ ๋ ๋ฒ์ด์ง๋ '์นจ๋ฌต์ ๋ฒ๊ทธ' ์์ธ์ ํ์ ํ ์ ์๋ค.
- ๊น์ด๊ฐ ๊น์ ๊ฐ์ฒด๋ฅผ ์์ ํ๊ฒ ์์ ๋ณต์ฌ(Shallow Copy)ํ์ฌ ์ ๋ฐ์ดํธํ๋ ๋ฒ์ ๊ฟฐ๋ซ๋๋ค.
๐ ๋ชฉ์ฐจ
- ๐ค ์ ์์์ผ ํ๋๊ฐ: ์นจ๋ฌตํ๋ ๋ฆฌ์กํธ์ ํจ์
- ๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
- ๐งฉ ๋ถ๋ณ์ฑ(Immutability)์ ์งํค๋ ์์ ๋ณต์ฌ์ ์ฐ์ํจ
- ๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 15๋ถ / ํต์ฌ ํํธ: 8๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ์์ฒ (์ ์
): "์ด๋ผ? ์ ์ ํ๋กํ ํ์ด์ง์์
user.nickname = '์์ด๋ฆ'์ผ๋ก ์ง์ ๋ฌธ์์ด์ ๋ฐ๊ฟจ๋๋ฐ ํ๋ฉด์ด ์ ๋ณํด์. ๋ก๊ทธ ์ฐ์ด๋ณด๋ฉด ๋ถ๋ช ํ ๊ฐ์ฒด ๊ฐ์ ์ ๋ค์ด๊ฐ ์๋๋ฐ ๋ง์ด์ฃ ! ๋ฆฌ์กํธ ๋ฒ๊ทธ ์๋๊ฐ์?" - ์ํธ(๋ฆฌ๋): "์์ฒ ๋... ๋ฆฌ์กํธ๋ ๋ฐ๋น ์ ๊ฐ์ฒด ์์ ๋ด์ฉ๋ฌผ์ ์ผ์ผ์ด ๊ฒ์ฌํ์ง ์์์. ๊ฐ์ฒด์ '๊ป๋ฐ๊ธฐ ์ฃผ์'๊ฐ ๊ทธ๋๋ก๋๊น ์ ๋ฐ๋ ์ค ์๊ณ ๋ ๋๋ง์ ์ฟจํ๊ฒ ๊ฑด๋๋ด ๊ฑฐ์์์!"
๐ค ์ ์์์ผ ํ๋๊ฐ: ์นจ๋ฌตํ๋ ๋ฆฌ์กํธ์ ํจ์
๋จ์ํ ์ซ์๋ ๋ฌธ์๋ ๊ฐ์ด ๋ฐ๋๋ฉด ์๋ง ๋ ๋๋ง๋๋ ๋ฆฌ์กํธ๊ฐ, ์ ๋ ๊ฐ์ฒด(Object)๋ ๋ฐฐ์ด(Array) ์ํ๋ฅผ ๋ค๋ฃฐ ๋๋ฉด ์๋ฌด๋ฐ ์๋ฌ ๋ฉ์์ง ํ๋ ์์ด "ํ๋ฉด๋ง" ์ ๋ฐ์ดํธ์ ์คํจํ๋ ๊ธฐ๊ดดํ ํ์์ ๊ฒช์ด๋ดค์ ๊ฑฐ์ผ.
๐ค ์ ๊น, ๋จผ์ ์๊ฐํด๋ด
์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ๋ ์ฝ๋์ผ. ๋ฒํผ์ ๋๋ฅด๋ฉด ํ๋ฉด์ ๋๋ค์์ด ๋ฐ๋๊น?
// โ ์์งํ ์ฝ๋ (Naive Approach)
function UserProfile() {
const [user, setUser] = useState({ id: 1, name: '์ด๋ณด์์ฒ ' });
const handleChangeName = () => {
user.name = '๋ง์คํฐ์์ฒ '; // ์๋ณธ ๊ฐ์ฒด ์ง์ ์์ (Mutation)
setUser(user); // ๋ณ๊ฒฝ๋ ์ํ ์ธํ
!
};
return (
<div>
<p>์ ์ ์ด๋ฆ: {user.name}</p>
<button onClick={handleChangeName}>์ด๋ฆ ๋ณ๊ฒฝ!</button>
</div>
);
}์์ฒ ์ด์ ์์๊ณผ ๋ค๋ฅด๊ฒ ํ๋ฉด์ ์ ๋ ๋ง์คํฐ์์ฒ ๋ก ์
๋ฐ์ดํธ๋์ง ์์. ๋ง์น ์ผ์ด๋ถ์ ๊ฒ์ฒ๋ผ.
๋์ฒด ๋ฆฌ์กํธ ์์์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋ ๊ฑธ๊น?
๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
๐ง 5์ด์๊ฒ ์ค๋ช ํ๋ค๋ฉด?
์๋ง(๋ฆฌ์กํธ)๊ฐ ์๋ฅ์ด ์๊ธฐ ๋ ๋ช ์ ๋๋ณด๊ณ ์์ด. ์๋ง๋ ๋๋ฌด ๋ฐ๋น ์ ์๊ธฐ ์ผ๊ตด์ ์์ธํ ๋ณด์ง ์๊ณ , ์ค์ง ์๊ธฐ๋ฐฉ ๋ฌธ ์์ ๋ถ์ ๋ช ํจ(๋ฉ๋ชจ๋ฆฌ ์ฃผ์) ๋ง ์ฌ์ฉ ๋ณด๊ณ ์ง๋๊ฐ๋ ๋ฒ๋ฆ์ด ์์ด.
๋ค๊ฐ ๋ฐฉ์ ๋ค์ด๊ฐ์ ์๊ธฐ ํ ๋ช ์ ๋นจ๊ฐ ๋ชจ์๋ฅผ ํ๋์์ผ๋ก ๋ชฐ๋ ๋ฐ๊ฟ์์ ์ด(user.name = '๋ง์คํฐ์์ฒ ').
๊ทธ๋ฆฌ๊ณ ์๋งํํ "์ ๊ธฐ ์ ์๊ธฐ ํ์ธํด๋ด์!"(setUser(user)) ๋ผ๊ณ ๋ถ๋ ์ง๋ง, ์๋ง๋ ๋ฌธํจ๋ง ๋ด ๋๋ค.
"์ด? ๋ฌธํจ ์ด๋ฆ์ด ๋๊ฐ๋ค? ์ ๋ฐ๋ ๊ฑฐ ๋ค ์๋๊น ๊ท์ฐฎ๊ฒ ํ์ง ๋ง." ํ๊ณ ๊ทธ๋ฅ ๊ฐ๋ฒ๋ฆฌ๋ ๊ฑฐ์ง. (์ ์ง์ผ๋ก ์ด์ฌ ๊ฐ์ง ์๋ ์ด์ ๋ฌด์ํจ)
โ
ํต์ฌ ์๋ฆฌ:
๋ฆฌ์กํธ๋ ์ฑ๋ฅ์ ์๋ผ๊ธฐ ์ํด ๊ทน๋จ์ ์ธ ํจ์จ์ ์ถ๊ตฌํด. ์ํ๊ฐ ๋ฐ๋์๋์ง ํ๋จํ ๋ ๊ฐ์ฒด ๋ด๋ถ์ ์์ฑ์ 1์ฐจ์๋ถํฐ ๋๊น์ง ์น ๋ค ๊น์ ๋น๊ตํ๋ ๋ฌด๊ฑฐ์ด ์ง(๊น์ ๋น๊ต)์ ํ์ง ์์.
์ค์ง ์๋ฐ์คํฌ๋ฆฝํธ์ Object.is() (์ฝ๊ฒ ๋งํด === ์ผ์น ์ฐ์ฐ์)๋ฅผ ํตํด ๊ป๋ฐ๊ธฐ์ ๋ฉ๋ชจ๋ฆฌ ์ฐธ์กฐ ์ฃผ์๊ฐ์ด ๋ณ๊ฒฝ๋์๋์ง๋ง 0.001์ด ๋ง์ ๋น๊ตํด ๋ฒ๋ฆฌ์ง. ๊ฐ์ฒด ๋ด๋ถ๋ฅผ ๋ฐฑ๋ ์ค์๊ณ ๋ฏ์ด ๊ณ ์ณ๋ดค์, ๊ป๋ฐ๊ธฐ ์ฃผ์๊ฐ ๊ฐ์ผ๋ฉด ๋ฆฌ์กํธ๋ ์ ๋ ํ๋ฉด์ ๋ค์ ๊ทธ๋ฆฌ์ง ์์. ์ด๋ฅผ ๋ถ๋ณ์ฑ(Immutability) ์ ์งํค์ง ์์ ๊ฒฝ์ฐ๋ผ๊ณ ๋ถ๋ฌ.
๐งฉ ๋ถ๋ณ์ฑ(Immutability)์ ์งํค๋ ์์ ๋ณต์ฌ์ ์ฐ์ํจ
โ ์์ฒ ์ด์ ๋ฐฐ์ด ํญํ ์ฌ๊ณ
๊ฒ์๊ธ์ ๋ฌ๋ฆฐ ๋๊ธ(๋ฐฐ์ด)๋ค์ ๋ค๋ฃฐ ๋๋ ๋๊ฐ์ ์ผ์ด ๋ฒ์ด์ ธ. ๋ฐฐ์ด์ ๋๊ธ์ ์ถ๊ฐํ๋๋ฐ ํ๋ฉด์ ์ ๋๊ธ์ด ์ ๋ .
// โ ์์ฒ ์ด์ Naive ๋ฐฐ์ด ์
๋ฐ์ดํธ
const [comments, setComments] = useState(['์ฌ๋ฐ๋ค์', 'ํผ๊ฐ์']);
const handleAddComment = () => {
comments.push('๋ฐ์ฌ์~'); // ๋ฐฐ์ด ์๋ณธ ํผ์ (Mutation)
setComments(comments); // ์ฃผ์๊ฐ์ด ๊ทธ๋๋ก์ด๋ฏ๋ก ๋ ๋๋ง ์นํ!
};push, pop, reverse, splice ๊ฐ์ ์ ๋ค์ ๊ธฐ์กด ๋ฉ๋ชจ๋ฆฌ ํต(๋ฐฐ์ด ์๋ณธ)์ ๋ฐ์ด ๋ด๊ณ ๋ด๋ถ๋ฅผ ๋ฐ๊พธ๋ ์
๋น๋ค์ด์ผ. ๋ฆฌ์กํธ์์ ์ด๋ฐ ์ ๋ค์ ํ์คํด.
โ
์ํธ์ ๋ฆฌํฉํ ๋ง: Spread ์ฐ์ฐ์ ๋์ง๊ธฐ
๋ถ์์ง ์๋ณธ์ ๊ณ ์น๋ ๊ฒ ์๋๋ผ, ์์ ๊น๋ํ ์ ์ง(์๋ก์ด ์ฐธ์กฐ ์ฃผ์) ์ ์ฌ์ ๊ธฐ์กด ์ง๋ค์ ๋ณต๋ถํด ์ค๋ ์ ๋ต์ด ํ์์ผ. ์ด๊ฒ ๊ทธ ์ ๋ช
ํ ๋ง์นจํ ์ธ ๊ฐ ... (์คํ๋ ๋ ๋ฌธ๋ฒ)์ ์กด์ฌ ์ด์ ์ง.
// โ
์ฐ์ํ ์ฝ๋ (Pro Approach)
const handleAddComment = () => {
// ์๋ก์ด ๋ฐฐ์ด ๊ป๋ฐ๊ธฐ []๋ฅผ ๋ง๋ค๊ณ , ๊ธฐ์กด ์ง(...comments)์ ํ๊ณ , ๋งจ ๋ค์ ์ ๋๊ธ์ ์ถ๊ฐํ๋ค.
setComments([...comments, '๋ฐ์ฌ์~']);
};์๋ก์ด []๊ฐ ์ ์ธ๋๋ ์๊ฐ ์์ ํ ์๋ก์ด ๋ฉ๋ชจ๋ฆฌ ๋ฌธํจ๊ฐ ํ์ํ๊ณ , ๋ฆฌ์กํธ๋ "์! ๋ฌธํจ๊ฐ ๋ฌ๋ผ์ก๋ค! ๋ฆฌ๋ ๋๋ง ํด์ผ์ง!" ํ๊ณ ๊ธฐ๋ถ ์ข๊ฒ ์์ง์ด๊ฒ ๋ผ.
๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
โ ์ค์ฒฉ ๊ฐ์ฒด(Nested Object)์ ๋ถ๋ถ ๊ฐฑ์ ๋๋ฝ ๋ฒ๊ทธ
์ธ์ ๋์ค๋๊ฐ?
const [user, setUser] = useState({
name: '์์ฒ ',
address: { city: 'Seoul', zip: '123' },
});
const handleCityChange = () => {
setUser({
...user, // ์์ ๋ณต์ฌ
address: { city: 'Busan' }, // ๐ฅ zip ๋ฐ์ดํฐ๊ฐ ๋ ์๊ฐ๋ฒ๋ฆผ!
});
};์์ธ: ์คํ๋ ๋ ์ฐ์ฐ์ ...๋ ๊ป๋ฐ๊ธฐ ํ ๊บผํ๋ง '์ ์ง'์ผ๋ก ๋ณต์ฌํด ์ฃผ๋ ์์ ๋ณต์ฌ(Shallow Copy) ๋๊ตฌ์ผ. address๋ผ๋ ์๋ฐฉ ๋ฌธ์ง๊น์ง ์๊ฑธ๋ก ๊ฐ์๋ผ์ ์ฃผ์ง๋ ์์. ๊ทธ๋์ ๋ฉ์น ํฐ JSON ๋ฉ์ด๋ฆฌ์ ๊น์ํ ๊ณณ์ ๋ฐ๊ฟ ๋ ๋จธ๋ฆฌ๊ฐ ํฐ์ ธ๋๊ฐ๊ฒ ๋์ง. ๋งค๋ฒ { ...user, address: { ...user.address, city: 'Busan' } } ์ฒ๋ผ ๋๋ ์์ด ๋ณต์ฌ ๊ป์ง์ ๊น์ผ ํ๋๊น ์ ์ง๋ณด์ ์ง์ฅ(Maintenance Nightmare)์ด ํผ์ณ์ ธ.
ํด๊ฒฐ์ฑ
:
์ด๋ด ๋ ์คํ๋ ๋๋ง ๋ฏฟ์ง ๋ง๊ณ ๋ฆฌ์กํธ ์ํ๊ณ์ ๊ตฌ์์, Immer ๊ฐ์ ๋ถ๋ณ์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋์
ํ๋ ๊ฒ ํ๋ก๋ค์ ์ ์์ด์ผ.
import { produce } from "immer";
const handleCityChange = () => {
setUser(produce((draft) => {
// ๋ง์น 'mutatation(์ง์ ์์ )' ํ๋ ๊ฒ์ฒ๋ผ ์ง๋ฉด, Immer๊ฐ ์์์ ๋ณต์ฌ๋ณธ์ ๋ฆฌํดํด์ค!
draft.address.city = 'Busan';
}));
}๐ ์ด๋ฒ์ ๋ฐฐ์ด ๋ด์ฉ ์ด์ ๋ฆฌ
| ์ํฉ | โ ๋์ ์ (Mutation ์ ๋ฐ) | โ ์ข์ ์ (Immutability ์ ์ง) |
|---|---|---|
| ๊ฐ์ฒด ์ ๋ฐ์ดํธ | user.name = '๊น'; setUser(user) | setUser({ ...user, name: '๊น' }) |
| ๋ฐฐ์ด ํญ๋ชฉ ์ถ๊ฐ | arr.push(newObj); setArr(arr); | setArr([...arr, newObj]); |
| ๋ฐฐ์ด ํญ๋ชฉ ์ญ์ | ์๋ณธ ๋ฐฐ์ด splice ์ ๊ฑฐ | setArr(arr.filter(item => item.id !== 1)) |
| ๋ณต์กํ ๋์ค ์์ | ๋์ฅ๋๋ ์ค์ฒฉ ์คํ๋ ๋ ...a, { ...b } | Immer ๋์
ํ์ฌ draft ์ง๊ด์ ์์ |
๐ก ํ ์ค๋ก ๊ธฐ์ตํ๊ธฐ
๋ฆฌ์กํธ์ ๋์ ํ๋ฆฟํ๋ค. ์ง(๊ฐ์ฒด) ๋ด๋ถ์ ์๋ ์ํ ์ํธ ์๊น์ด ๋ฐ๋์๋ค๊ณ ์์์ฑ์ง ๋ชปํ๋ค. ์๋ก์ด ์ง์ ํต์งธ๋ก ์ด์ฌ(...์ฌ์ฉ)ํด์ผ๋ง ๋น๋ก์ ๋์ ๋น๋น๋ฉฐ ๋ ๋๋ง์ ๋์ ํ๋ค.
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
๋ฐฐ์ด์ push ํ๊ณ ์ ํ๋ฉด ์ ๋ฐ๋์ง ํ๋ฉด์ ์ฝ์งํ๋ ์ด์ ์ ๋... ๋ฆฌ์กํธ๊ฐ ๊ฐ์ฒด ์๊น์ง ์ผ์ผ์ด ๊น๋ณด์ง ์๊ณ ๊ป๋ฐ๊ธฐ(๋ฉ๋ชจ๋ฆฌ ์ฃผ์)๋ง ๋ณธ๋ค๋ ์ฌ์ค์ ๊นจ๋ซ๊ณ ๋๋ ๋ ๋๋ง ํธ๋ฆฌ๊ฑฐ ๋งค์ปค๋์ฆ์ด ํ ์ดํด๋๋ค. ์ํธ ๋์ด ์๋ฅ์ด ์๊ธฐ ๋น์ ํด์ฃผ์
จ์ ๋ ์ง์ง ๋ช
์พํ๋ค.
๐ก "๋ฆฌ์กํธ์ ๋์ ํ๋ฆฟํ๋ค! ๊ฐ์ฒด๋ ๋ฐฐ์ด์ ๊ฑด๋๋ฆด ๋ ์๋ณธ์ ํผ์ํ์ง ๋ง๊ณ ๋ฌด์กฐ๊ฑด ์์ ๋ณต์ฌ(
...์คํ๋ ๋ ์ฐ์ฐ์)๋ก ์ ์ง์ ํ์ฃผ์."
์์ผ๋ก๋ ๊น์ ๋ณต์ฌ ํ๋๋ผ ์ค์ฒฉ ์คํ๋ ๋๋ก ๊ณ ํต๋ฐ์ง ๋ง๊ณ , ๋ด์ผ ๋น์ฅ ํ ํ๋ก์ ํธ์ Immer๋ฅผ ๋์
ํ์๊ณ ๊ฑด์ํด ๋ด์ผ๊ฒ ๋ค. ์กฐ๊ธ์ฉ ํ๋ก ํ๋ก ํธ์๋ ๊ฐ๋ฐ์์ ์์ผ๊ฐ ์๊ธฐ๋ ๊ฒ ๊ฐ์ ๋ฟ๋ฏํ๋ค. ์ผ๋ฅธ ํฌ์ค์ฅ ๊ฐ์ ๋ ์ซ ๋นผ๊ณ ๊ฟ์ ์์ผ์ง.
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ฐฐ์ด ๋ฉ์๋ ์ค์์ ๋ถ๋ณ์ฑ์ ํด์น๋ ์ ๋น(Mutating method)๊ณผ ์๋ณธ์ ๋ณด์กดํ๋ ์ฒ์ฌ(Non-mutating method)๊ฐ ์์ฌ ์์ต๋๋ค. ๋ฆฌ์กํธ ์ํ์ ์ง์ ๋๋ ค๋ฐ์ผ๋ฉด ์น๋ช ํ๋ฅผ ์ ํ๋ ์ ๋น๋ง์ ๋ฌถ์ ๊ฒ์?
- A)
splice(),map(),push() - B)
filter(),map(),concat() - C)
push(),pop(),reverse(),splice() - D)
slice(),filter(),reduce()
โ ์ ๋ต: C
๐ก ์์ธ ํด์ค: ๋ฆฌ์กํธ ๋ฐฐ์ด ์ํ๋ฅผ ๊ฑด๋๋ฆด ๋ B๋ D์ ๋ฉ์๋๋ค(map, filter, concat, slice ๋ฑ)์ ํจ์ ์คํ ๊ฒฐ๊ณผ๋ก "์์ ํ ์๋ก์ด ๋ฐฐ์ด"์ ๋ฆฌํดํ๊ธฐ ๋๋ฌธ์ ์์ ํฉ๋๋ค(์ฒ์ฌ). ํ์ง๋ง C์ ๋์ด๋ ๋ฉ์๋๋ค์ ๋ฉ๋ชจ๋ฆฌ์ ์ด๋ฏธ ํ ๋น๋ ์๋ณธ ๋ฐฐ์ด ์์ฒด์ ๋ด์ฉ์ ์ฐข์ด๋ฐ๊ธฐ๊ฑฐ๋ ๋ง๋ ํ ๊ธฐ์กด ์ฃผ์๋ฅผ ๊ทธ๋๋ก ๋ฐํํฉ๋๋ค(์ ๋น). ๊ทธ๋์ ๋ฆฌ์กํธ๊ฐ ๋ณํ๋ฅผ ๊ฐ์งํ์ง ๋ชปํ๊ณ ๋ ๋๋ง์ ๋ฉ์ถ๊ฒ ๋ง๋ญ๋๋ค.
Q2. ๋ ๊ฐ์ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด์ ์ผ์น ์ฌ๋ถ์ ๋ํ ์ง๋ฌธ์ ๋๋ค. ์ฝ๋ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋งํ๋ณด์ธ์.
const obj1 = { name: "์ํธ" };
const obj2 = { name: "์ํธ" };
console.log(Object.is(obj1, obj2)); // ๋๋ obj1 === obj2- A)
true(๋ด๋ถ ๋ด์ฉ๋ฌผ์ด ์๋ฒฝํ ๊ฐ์ผ๋ฏ๋ก) - B)
false(๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋ ๊ณ ์ ์ฐธ์กฐ ์ฃผ์๊ฐ์ด ์์ฐํ ๋ค๋ฅธ ๋ ๊ฐ์ ์ง์ด๋ฏ๋ก) - C)
undefined(์ ์ ์์)
โ ์ ๋ต: B
๐ก ์์ธ ํด์ค: ์ด๊ฒ ๋ฆฌ์กํธ๊ฐ ๊น์ ๋ ๋๋ง ๊ฐ์ง๋ฅผ ํฌ๊ธฐํ๊ณ ์์ ๋น๊ต(===)๋ฅผ ํ๋ ์ด์ ์
๋๋ค. ๋ชจ์๊ณผ ์์ฑ์ด 100% ๋๊ฐ๋๋ผ๋ ์ปดํจํฐ์ ํ(Heap) ๊ณต๊ฐ์ ๋ฐ๋ก ๋ฐฉ์ ํ ๊ธฐ ๋๋ฌธ์ ์ฃผ์๊ฐ ๋ค๋ฆ
๋๋ค. ์ญ์ผ๋ก ๋งํ๋ฉด, let a = { id: 1 }; let b = a; b.id = 2;๋ผ๊ณ ํ์ ๋ a === b๋ ๋ฌด์กฐ๊ฑด true๊ฐ ๋์ต๋๋ค. ๊ฐ์ ๋ฐฉ์ด๋๊น์! ๋ฆฌ์กํธ๊ฐ ๊ป๋ฐ๊ธฐ๋ง ์ณ๋ค๋ณผ ๋ ์ด๋ฅผ ํท๊ฐ๋ฆฌ๊ฒ ํ๋ฉด ๋ฐฉ๊ธ ์์ฒ ์ด ๊ฐ์ ๋์ฐธ์ฌ๊ฐ ์ผ์ด๋ฉ๋๋ค.
Q3. '๋ถ๋ณ์ฑ'์ ์งํจ๋ต์๊ณ ์๋์ฒ๋ผ ๊ธด๊ธ ์์ ์ ๋์ ํ์ง๋ง ์ฌ์ ํ ๋ฌธ์ ๊ฐ ์กด์ฌํฉ๋๋ค. ๋ฌด์์ด ์๋ชป๋์๋์ง, ์๋ฒฝํ ํด๊ฒฐ์ฑ ๊ณผ ์๋ฆฌ(์์ ๋ณต์ฌ์ ํ๊ณ)๋ฅผ ์ค๋ช ํด๋ณด์ธ์.
const [serverConfig, setConfig] = useState({
port: 8080,
settings: { timeout: 3000 }
});
const reduceTimeout = () => {
const newConfig = { ...serverConfig }; // ์ค, ๋ถ๋ณ์ฑ ์ง์ผฐ๋ค!
newConfig.settings.timeout = 1000; // ์ง์ ์์ ?
setConfig(newConfig);
};โ ์ ๋ต ๋ฐ ์ฃผ๊ด์ ํด์ค:
์์ธ(Why): ๋๋๊ฒ๋ ๋ถ๋ถ์ ์ธ ์น๋ช
ํ๋ฅผ ์
์ต๋๋ค! newConfig = { ...serverConfig }๋ ์์ ๋ณต์ฌ(Shallow Copy)๋ก, ๋ฐ๊นฅ์ชฝ ๊ป๋ฐ๊ธฐ(serverConfig ์์ฒด)์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ ์๊ฒ์ผ๋ก ๋ฐ๋์์ต๋๋ค. ๊ทธ๋์ ๋ฆฌ์กํธ๋ "์! ๋ฐ๋์๋ค?" ํ๊ณ ๋ ๋๋ง์ ๋์
ํ๊ธด ํฉ๋๋ค.
ํ์ง๋ง! ์์ ๋ณต์ฌ ํน์ฑ์ ๋ด๋ถ์ ์๋ ์์ ๊ฐ์ฒด settings์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ ์์ ํ ์๋ ๊ฒ๊ณผ ๋์ผํ๊ฒ ๋ณต์ฌ๋์ด ์ฐ๊ฒฐ๋์ด ์์ต๋๋ค. ๋ง์ฝ ์์ ์ปดํฌ๋ํธ ์ค ์ผ๋ถ๊ฐ React.memo ๋ฑ์ผ๋ก ์ต์ ํ๋์ด ์๋ค๋ฉด, ๊ฑ๋ค๋ค์ settings ์ฃผ์๊ฐ ์ ๋ฐ๋์์ผ๋ฏ๋ก ๋ ๋๋ง์ ๊ฑฐ๋ถํ๋ ํํธํ ๋ฒ๊ทธ๊ฐ ์๊น๋๋ค.
ํด๊ฒฐ ๋ก์ง: ๋ด๋ถ์ ์ค์ฒฉ ๊ฐ์ฒด๊น์ง ์์ ํ ์๋ก ๋ณต์ฌํด ์ฃผ์ด์ผ ํฉ๋๋ค. setConfig({ ...serverConfig, settings: { ...serverConfig.settings, timeout: 1000 } }) ์ฒ๋ผ ๊ฐ ๊น์ด๋ง๋ค ๋
๋ฆฝ๋ ์์ ๋ณต์ฌ๋ฅผ ์ํํ๊ฑฐ๋, ์ ์ผ ์ ํธํ๊ฒ Immer ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ๊น๋ํ๊ฒ ์ฐํํ๋ ๊ฒ ์ ์์
๋๋ค.