JavaScript์ ๋ง๋ฒ ๐ช: ๋ถ๋ณ์ฑ๊ณผ ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ก ์ฝ๋์ ๋ ๊ฐ ๋ฌ๊ธฐ

์๋ ? ์ค๋์ JavaScript ์ธ๊ณ์์ ์ ๋ง ์ค์ํ์ง๋ง ์ข ์ข ๊ฐ๊ณผ๋๋ ๊ฐ๋ ์ธ ๋ถ๋ณ์ฑ(Immutability)๊ณผ ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ(Persistent Data Structures)์ ๋ํด ํจ๊ป ์์๋ณผ ๊ฑฐ์ผ. ๐
์ด ๊ฐ๋ ๋ค์ด ์ ์ค์ํ๋๊ณ ? ์ต์ ํ๋ก ํธ์๋ ํ๋ ์์ํฌ๋ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ๋ชจ๋ ์ด ์์น์ ๊ธฐ๋ฐ์ผ๋ก ํ๊ณ ์๊ฑฐ๋ ! React, Redux, Vuex ๋ฑ์ ์ฌ์ฉํด๋ดค๋ค๋ฉด ์ด๋ฏธ ๋ถ๋ณ์ฑ์ ์ค์์ฑ์ ์ด๋ ดํ์ด ๋๊ผ์ ๊ฑฐ์ผ. ํ์ง๋ง ์ค๋์ ๊ทธ ๊ฐ๋ ์ ๋ ๊น์ด ํํค์ณ๋ณผ ๊ฑฐ์ผ. ๐ต๏ธโโ๏ธ
ํ๋ก๊ทธ๋๋ฐ ์ธ๊ณ์์ ์ฌ๋ฅ์ ๋ฐํํ๊ณ ์ถ๋ค๋ฉด, ์ด๋ฐ ํต์ฌ ๊ฐ๋ ๋ค์ ์ ๋๋ก ์ดํดํ๋ ๊ฒ์ด ์ค์ํด. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ๊ฑฐ๋ํ๋ฏ, ์ฐ๋ฆฌ๋ ์ค๋ ๋ถ๋ณ์ฑ์ด๋ผ๋ ์ฌ๋ฅ์ ์ต๋ํด๋ณด์! ๐
๐ ๋ชฉ์ฐจ
- ๋ถ๋ณ์ฑ์ด๋ ๋ฌด์์ธ๊ฐ? ๊ทธ๋ฆฌ๊ณ ์ ์ค์ํ ๊น?
- JavaScript์์์ ๊ฐ๋ณ์ฑ ๋ฌธ์ ์
- ๋ถ๋ณ์ฑ ๊ตฌํํ๊ธฐ: ๊ธฐ๋ณธ ํ ํฌ๋
- ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋?
- Immer, Immutable.js ๋ฑ ์ธ๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ดํด๋ณด๊ธฐ
- ์ค์ ์์ : ๋ถ๋ณ์ฑ์ผ๋ก ์ฑ๋ฅ ์ต์ ํํ๊ธฐ
- 2025๋ ์ต์ ํธ๋ ๋์ ๋ฏธ๋ ์ ๋ง
1. ๋ถ๋ณ์ฑ์ด๋ ๋ฌด์์ธ๊ฐ? ๊ทธ๋ฆฌ๊ณ ์ ์ค์ํ ๊น? ๐ค
๋ถ๋ณ์ฑ(Immutability)์ ํ๋ฒ ์์ฑ๋ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ ์ ์๊ฒ ๋ง๋๋ ๊ฐ๋ ์ด์ผ. ์ฝ๊ฒ ๋งํ๋ฉด, "ํ๋ฒ ๋ง๋ค์ด์ง ๊ฒ์ ๋ฐ๊พธ์ง ์๊ณ , ํ์ํ๋ฉด ์๋ก ๋ง๋ ๋ค"๋ ์์น์ด์ง. ๋ง์น ๋์ ์ผ๊ธฐ์ฅ์ฒ๋ผ - ํ๋ฒ ์ด ๋ด์ฉ์ ์ง์ฐ๊ฐ๋ก ์ง์ฐ๊ณ ๋ค์ ์ฐ๋ ๊ฒ ์๋๋ผ, ์ ํ์ด์ง์ ์๋ก์ด ๋ด์ฉ์ ์ฐ๋ ๊ฑฐ์ผ. ๐
๐ ๊ฐ๋ณ์ฑ vs ๋ถ๋ณ์ฑ
๊ฐ๋ณ์ฑ(Mutability):
- ๋ฐ์ดํฐ๊ฐ ์์ฑ๋ ํ์๋ ๋ด์ฉ์ ๋ณ๊ฒฝํ ์ ์์
- ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ๊ณ์ ์ฌ์ฉ
- ์: ๋ฐฐ์ด์ push(), pop(), ๊ฐ์ฒด ์์ฑ ์ง์ ์์
๋ถ๋ณ์ฑ(Immutability):
- ๋ฐ์ดํฐ๊ฐ ์์ฑ๋ ํ์๋ ๋ด์ฉ์ ๋ณ๊ฒฝํ ์ ์์
- ๋ณ๊ฒฝ์ด ํ์ํ๋ฉด ์๋ก์ด ๋ฉ๋ชจ๋ฆฌ์ ๋ณต์ฌ๋ณธ ์์ฑ
- ์: ๋ฌธ์์ด ๋ฉ์๋๋ค, Array.map(), Array.filter()
์ ๋ถ๋ณ์ฑ์ด ์ค์ํ ๊น? ๐
- ์์ธก ๊ฐ๋ฅ์ฑ: ๋ฐ์ดํฐ๊ฐ ์ธ์ ์ด๋์ ๋ณํ ์ง ๊ฑฑ์ ํ ํ์๊ฐ ์์ด. ํ๋ฒ ๋ง๋ค์ด์ง ๋ฐ์ดํฐ๋ ํญ์ ๊ฐ์ ์ํ๋ฅผ ์ ์งํ๋๊น!
- ๋๋ฒ๊น ์ฉ์ด์ฑ: ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ์ ๋ ๋ฐ์ดํฐ ๋ณํ๋ฅผ ์ถ์ ํ๊ธฐ ์ฌ์์ ธ. "๋๊ฐ ์ด ๋ฐ์ดํฐ๋ฅผ ๋ฐ๊ฟจ์ง?"๋ผ๋ ์ง๋ฌธ์ด ์ฌ๋ผ์ง๋๊น.
- ๋์์ฑ ์ฒ๋ฆฌ: ์ฌ๋ฌ ํจ์๋ ์ค๋ ๋๊ฐ ๋์์ ๊ฐ์ ๋ฐ์ดํฐ์ ์ ๊ทผํด๋ ์ถฉ๋์ด ์์ด.
- ์๊ฐ ์ฌํ ๋๋ฒ๊น : ์ด์ ์ํ๋ก ์ฝ๊ฒ ๋์๊ฐ ์ ์์ด. Redux DevTools ๊ฐ์ ๋๊ตฌ๊ฐ ์ด๋ฅผ ํ์ฉํ์ง.
- ์ฐธ์กฐ ๋๋ฑ์ฑ ์ต์ ํ: ๊ฐ์ฒด๊ฐ ๋ณ๊ฒฝ๋์๋์ง ๋น ๋ฅด๊ฒ ํ์ธํ ์ ์์ด (๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ง ๋น๊ตํ๋ฉด ๋จ).
"๋ถ๋ณ์ฑ์ ๋จ์ํ ์ฝ๋ฉ ์คํ์ผ์ด ์๋๋ผ, ์ํํธ์จ์ด ์ค๊ณ์ ์ฒ ํ์ด๋ค."
- ์ด๋ค ํ๋ช ํ ๊ฐ๋ฐ์ ๐
2. JavaScript์์์ ๊ฐ๋ณ์ฑ ๋ฌธ์ ์ ๐ฑ
JavaScript๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ๋ณ(mutable) ์ธ์ด์ผ. ํนํ ๊ฐ์ฒด์ ๋ฐฐ์ด์ ์ฐธ์กฐ ํ์ ์ด๋ผ์ ์์์น ๋ชปํ ๋ถ์์ฉ(side effects)์ ์ผ์ผํค๊ธฐ ์ฝ์ง. ์๋ ์์ ๋ฅผ ํ๋ฒ ๋ณผ๊น?
// ๊ฐ๋ณ์ฑ์ผ๋ก ์ธํ ๋ฌธ์ ์์
const user = { name: '์ฒ ์', age: 25 };
const userCopy = user; // ์ฐธ์กฐ๋ง ๋ณต์ฌ๋จ
userCopy.age = 26; // userCopy๋ง ๋ณ๊ฒฝํ๋ ค๊ณ ํ๋๋ฐ...
console.log(user.age); // 26 - ์๋ณธ user๋ ๋ณ๊ฒฝ๋จ! ๐ฑ
์ ์ฝ๋์์ ์ฐ๋ฆฌ๋ userCopy๋ง ๋ณ๊ฒฝํ๋ ค๊ณ ํ์ง๋ง, ์ค์ ๋ก๋ ์๋ณธ user ๊ฐ์ฒด๋ ํจ๊ป ๋ณ๊ฒฝ๋์์ด. ์ด๊ฒ ๋ฐ๋ก ๊ฐ๋ณ์ฑ์ ํจ์ ์ด์ผ! ์ด๋ฐ ํ์์ "์๋์น ์์ ๋ถ์์ฉ(side effect)"์ด๋ผ๊ณ ํด.
๐จ ๊ฐ๋ณ์ฑ์ด ์ผ์ผํค๋ ์ฃผ์ ๋ฌธ์ ๋ค
- ์์ธก ๋ถ๊ฐ๋ฅํ ์ฝ๋: ๊ฐ์ฒด๊ฐ ์ธ์ ์ด๋์ ๋ณ๊ฒฝ๋ ์ง ์ ์ ์์ด ์ฝ๋ ํ๋ฆ์ ์ถ์ ํ๊ธฐ ์ด๋ ค์์ ธ.
- ๋ฒ๊ทธ ์ฐพ๊ธฐ ์ด๋ ค์: "์ด ๋ฐ์ดํฐ๋ ๋ถ๋ช ์ด๋ ๊ฒ ์ค์ ํ๋๋ฐ ์ ๋ฐ๋์์ง?" ๊ฐ์ ์ํฉ์ด ๋ฐ์ํด.
- ํจ์ ์์์ฑ ํผ์: ๊ฐ์ ์ ๋ ฅ์ ํญ์ ๊ฐ์ ์ถ๋ ฅ์ ๋ณด์ฅํ๋ ์์ ํจ์๋ฅผ ๋ง๋ค๊ธฐ ์ด๋ ค์์ ธ.
- ํ ์คํธ ๋ณต์ก์ฑ ์ฆ๊ฐ: ๊ฐ๋ณ ๋ฐ์ดํฐ๋ ํ ์คํธ ํ๊ฒฝ์ ์ค์ ํ๊ณ ๊ฒ์ฆํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค์ด.
- ๋์์ฑ ๋ฌธ์ : ์ฌ๋ฌ ํจ์๊ฐ ๋์์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ฉด ๊ฒฝ์ ์ํ(race condition)๊ฐ ๋ฐ์ํ ์ ์์ด.
์ด๋ฐ ๋ฌธ์ ๋ค ๋๋ฌธ์ ํ๋ JavaScript ๊ฐ๋ฐ์์๋ ๋ถ๋ณ์ฑ์ ์ ๊ทน์ ์ผ๋ก ๋์ ํ๊ณ ์์ด. React, Redux, Vue ๊ฐ์ ์ธ๊ธฐ ํ๋ ์์ํฌ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค๋ ๋ถ๋ณ์ฑ ์์น์ ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณ๋์์ง. ํนํ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ์ํคํ ์ฒ์์๋ ์ํ ๋ณํ๋ฅผ ์์ธก ๊ฐ๋ฅํ๊ฒ ๊ด๋ฆฌํ๋ ๊ฒ์ด ๋งค์ฐ ์ค์ํ๊ฑฐ๋ . ๐งฉ
3. ๋ถ๋ณ์ฑ ๊ตฌํํ๊ธฐ: ๊ธฐ๋ณธ ํ ํฌ๋ ๐ ๏ธ
์ด์ JavaScript์์ ๋ถ๋ณ์ฑ์ ์ด๋ป๊ฒ ๊ตฌํํ ์ ์๋์ง ์์๋ณด์! ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ๋ถํฐ ์์ํด์ ์ ์ ๊ณ ๊ธ ํ ํฌ๋์ผ๋ก ๋์๊ฐ๊ฒ. ๐
๊ธฐ๋ณธ ์์ ํ์ ์ ์ด๋ฏธ ๋ถ๋ณ์ด์ผ! ๐
JavaScript์ ์์ ํ์ (primitive types)์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ถ๋ณ์ด์ผ:
let a = 5;
let b = a; // ๊ฐ ๋ณต์ฌ
b = 10; // b๋ง ๋ณ๊ฒฝ๋จ
console.log(a); // 5 (๋ณ๊ฒฝ๋์ง ์์)
console.log(b); // 10
ํ์ง๋ง ๊ฐ์ฒด์ ๋ฐฐ์ด์ ์ฐธ์กฐ ํ์ ์ด๋ผ ํน๋ณํ ์ฒ๋ฆฌ๊ฐ ํ์ํด. ์๋ ๋ฐฉ๋ฒ๋ค์ ํตํด ๋ถ๋ณ์ฑ์ ๊ตฌํํ ์ ์์ด:
1. ์์ ๋ณต์ฌ(Shallow Copy) ๋ฐฉ๋ฒ๋ค ๐
๊ฐ์ฒด ๋ณต์ฌํ๊ธฐ
// 1. ์คํ๋ ๋ ์ฐ์ฐ์ ์ฌ์ฉ (ES6+)
const original = { name: '์ํฌ', age: 28 };
const copy = { ...original, age: 29 }; // ์ ๊ฐ์ฒด ์์ฑ + age ์์ฑ ๋ณ๊ฒฝ
// 2. Object.assign() ์ฌ์ฉ
const anotherCopy = Object.assign({}, original, { age: 30 });
console.log(original); // { name: '์ํฌ', age: 28 }
console.log(copy); // { name: '์ํฌ', age: 29 }
console.log(anotherCopy); // { name: '์ํฌ', age: 30 }
๋ฐฐ์ด ๋ณต์ฌํ๊ธฐ
// 1. ์คํ๋ ๋ ์ฐ์ฐ์ ์ฌ์ฉ
const numbers = [1, 2, 3];
const newNumbers = [...numbers, 4]; // [1, 2, 3, 4]
// 2. concat() ์ฌ์ฉ
const moreNumbers = numbers.concat(5); // [1, 2, 3, 5]
// 3. slice() ์ฌ์ฉ
const numbersCopy = numbers.slice(); // [1, 2, 3]
โ ๏ธ ์ฃผ์: ์์ ๋ณต์ฌ๋ ์ค์ฒฉ๋ ๊ฐ์ฒด๋ ๋ฐฐ์ด์์๋ ๋ถ๋ณ์ฑ์ ๋ณด์ฅํ์ง ์์! 1๋จ๊ณ ๊น์ด์์๋ง ์ ์ฐธ์กฐ๊ฐ ์์ฑ๋๊ณ , ๋ด๋ถ ๊ฐ์ฒด๋ ์ฌ์ ํ ์๋ณธ๊ณผ ๊ฐ์ ์ฐธ์กฐ๋ฅผ ๊ณต์ ํ๊ฒ ๋ผ.
2. ๊น์ ๋ณต์ฌ(Deep Copy) ๊ตฌํํ๊ธฐ ๐
// 1. JSON์ ํ์ฉํ ๊น์ ๋ณต์ฌ (๊ฐ๋จํ์ง๋ง ์ ํ์ )
const original = { user: { name: '๋ฏผ์', hobbies: ['์ถ๊ตฌ', '๊ฒ์'] } };
const deepCopy = JSON.parse(JSON.stringify(original));
// 2. ๊ตฌ์กฐ๋ถํด์ ์คํ๋ ๋๋ฅผ ํ์ฉํ ์๋ ๊น์ ๋ณต์ฌ
const manualDeepCopy = {
...original,
user: {
...original.user,
hobbies: [...original.user.hobbies]
}
};
JSON ๋ฐฉ์์ ํจ์, undefined, Symbol ๋ฑ์ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ ํ๊ณ๊ฐ ์์ด. ์ค๋ฌด์์๋ ๋ณดํต ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, ํ์์ ๋ง๊ฒ ์ง์ ๊น์ ๋ณต์ฌ ํจ์๋ฅผ ๊ตฌํํด.
3. ๋ถ๋ณ ๋ฐ์ดํฐ ๋ค๋ฃจ๊ธฐ ์ํ ํจ์ํ ์ ๊ทผ๋ฒ ๐ง
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ ํ์ฉํ๋ฉด ๋ถ๋ณ์ฑ์ ๋ ์ฐ์ํ๊ฒ ๋ค๋ฃฐ ์ ์์ด:
// ๋ฐฐ์ด์ ๋ถ๋ณ์ ์กฐ์
const numbers = [1, 2, 3, 4, 5];
// โ ๊ฐ๋ณ์ ๋ฐฉ์ (์๋ณธ ๋ณ๊ฒฝ)
// numbers.push(6);
// numbers.pop();
// numbers[0] = 10;
// โ
๋ถ๋ณ์ ๋ฐฉ์ (์ ๋ฐฐ์ด ๋ฐํ)
const added = [...numbers, 6]; // ์ถ๊ฐ
const removed = numbers.slice(0, -1); // ๋ง์ง๋ง ์์ ์ ๊ฑฐ
const replaced = [10, ...numbers.slice(1)]; // ์ฒซ ์์ ๊ต์ฒด
const filtered = numbers.filter(n => n % 2 === 0); // ์ง์๋ง ํํฐ๋ง
const mapped = numbers.map(n => n * 2); // ๋ชจ๋ ์์ 2๋ฐฐ๋ก
๊ฐ์ฒด๋ ๋น์ทํ ํจํด์ผ๋ก ๋ค๋ฃฐ ์ ์์ด:
const user = {
name: '์ง๋ฏผ',
age: 27,
address: {
city: '์์ธ',
district: '๊ฐ๋จ๊ตฌ'
}
};
// ๋ถ๋ณ์ ์ผ๋ก ์ค์ฒฉ ์์ฑ ์
๋ฐ์ดํธํ๊ธฐ
const updatedUser = {
...user,
age: 28, // ๋์ด ์
๋ฐ์ดํธ
address: {
...user.address,
district: '์กํ๊ตฌ' // ๊ตฌ๋ง ๋ณ๊ฒฝ
}
};
์ด๋ฐ ํจํด๋ค์ ์ตํ๋ฉด ๋ณต์กํ ์ค์ฒฉ ๊ตฌ์กฐ์์๋ ๋ถ๋ณ์ฑ์ ์ ์งํ๋ฉด์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ์ ์์ด. ํ์ง๋ง ๊ตฌ์กฐ๊ฐ ๊น์ด์ง์๋ก ์ฝ๋๊ฐ ๋ณต์กํด์ง๋ ๋จ์ ์ด ์์ง. ์ด๋ด ๋ ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ์ ๋ฌธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋์์ ๋ฐ์ ์ ์์ด. ๋ค์ ์น์ ์์ ์ดํด๋ณด์! ๐
4. ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋? ๐ณ
์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ(Persistent Data Structures)๋ ๋ถ๋ณ์ฑ์ ํจ์จ์ ์ผ๋ก ๊ตฌํํ๊ธฐ ์ํ ํน๋ณํ ์๋ฃ๊ตฌ์กฐ์ผ. "์์์ "์ด๋ผ๋ ๋ง์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์ด์ ๋ฒ์ ์ด ํญ์ ๋ณด์กด๋๋ค๋ ์๋ฏธ์ผ. ๐ฐ๏ธ
์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ํต์ฌ ๊ฐ๋
์ผ๋ฐ์ ์ธ ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌํ์ ๋ณ๊ฒฝ์ด ํ์ํ ๋๋ง๋ค ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํด์ผ ํด์ ๋ฉ๋ชจ๋ฆฌ์ ์ฑ๋ฅ ์ธก๋ฉด์์ ๋นํจ์จ์ ์ผ ์ ์์ด. ํ์ง๋ง ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ๊ตฌ์กฐ ๊ณต์ (Structural Sharing)๋ผ๋ ๊ธฐ๋ฒ์ ์ฌ์ฉํด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด.
๊ตฌ์กฐ ๊ณต์ ๋ ์ ๋ฒ์ ์ ๋ง๋ค ๋ ๋ณ๊ฒฝ๋์ง ์์ ๋ถ๋ถ์ ์๋ณธ๊ณผ ๊ณต์ ํ๊ณ , ๋ณ๊ฒฝ๋ ๋ถ๋ถ๋ง ์๋ก ์์ฑํ๋ ๋ฐฉ์์ด์ผ. ์ด๋ ๊ฒ ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ํฌ๊ฒ ์ค์ด๋ฉด์๋ ๋ถ๋ณ์ฑ์ ์ด์ ์ ๋๋ฆด ์ ์์ง!
ํธ๋ผ์ด(Trie)์ ๊ฐ์ ์์ ์๋ฃ๊ตฌ์กฐ ์ดํดํ๊ธฐ ๐ฒ
์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ํ์ ์ธ ์๋ก๋ ํธ๋ผ์ด(Trie), ํนํ ๊ทธ ๋ณํ์ธ HAMT(Hash Array Mapped Trie)๊ฐ ์์ด. ์ด ๊ตฌ์กฐ๋ค์ Immutable.js๋ Immer ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ธฐ๋ฐ์ด ๋๋ ๊ฐ๋ ์ด์ผ.
์ ๊ทธ๋ฆผ์์ ๋ณผ ์ ์๋ฏ์ด, ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ๋ณ๊ฒฝ๋ ๊ฒฝ๋ก์ ์๋ ๋ ธ๋๋ค๋ง ์๋ก ์์ฑํ๊ณ , ๋๋จธ์ง๋ ๊ธฐ์กด ๊ตฌ์กฐ๋ฅผ ์ฌ์ฌ์ฉํด. ์ด๋ฐ ๋ฐฉ์์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ๊ณผ ๋ถ๋ณ์ฑ์ ๋์์ ๋ฌ์ฑํ ์ ์์ด.
์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์ฅ์ ๐
- ํจ์จ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ: ๋ณ๊ฒฝ๋ ๋ถ๋ถ๋ง ์๋ก ์์ฑํ๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ต์ํ๋ผ.
- ๋น ๋ฅธ ๋น๊ต ์ฐ์ฐ: ์ฐธ์กฐ ๋๋ฑ์ฑ ๊ฒ์ฌ๋ง์ผ๋ก ๋ณ๊ฒฝ ์ฌ๋ถ๋ฅผ ๋น ๋ฅด๊ฒ ํ์ธํ ์ ์์ด.
- ์๊ฐ ์ฌํ(Time Travel): ๋ชจ๋ ์ด์ ๋ฒ์ ์ด ๋ณด์กด๋๋ฏ๋ก ์ํ ํ์คํ ๋ฆฌ๋ฅผ ์ฝ๊ฒ ๊ด๋ฆฌํ ์ ์์ด.
- ํธ๋์ญ์ ์์ ์ฑ: ์์ ์ค๊ฐ์ ์คํจํด๋ ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ด ์ ์ง๋ผ.
- ๋์์ฑ ์ง์: ์ฌ๋ฌ ์์ ์ด ๋์์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ฒ ๋ค๋ฃฐ ์ ์์ด.
์ค์ ์: Immutable.js์ List ์ฌ์ฉ ์์
import { List } from 'immutable';
// ๋ถ๋ณ ๋ฆฌ์คํธ ์์ฑ
const list1 = List([1, 2, 3, 4]);
// ์ ๋ฆฌ์คํธ ์์ฑ (์๋ณธ์ ๋ณ๊ฒฝ๋์ง ์์)
const list2 = list1.push(5);
const list3 = list1.set(0, 10);
console.log(list1.toArray()); // [1, 2, 3, 4] - ์๋ณธ ์ ์ง
console.log(list2.toArray()); // [1, 2, 3, 4, 5]
console.log(list3.toArray()); // [10, 2, 3, 4]
// ํจ์จ์ ์ธ ๋น๊ต
console.log(list1 === list2); // false - ๋ค๋ฅธ ๊ฐ์ฒด
console.log(list1.equals(list2)); // false - ๋ด์ฉ์ด ๋ค๋ฆ
์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ์ฌ๋ฅ๋ท์์ ํ๋ก๊ทธ๋๋ฐ ๊ด๋ จ ์ฌ๋ฅ์ ๊ณต์ ํ๋ ๊ฐ๋ฐ์๋ค ์ฌ์ด์์๋ ์ธ๊ธฐ ์๋ ์ฃผ์ ์ผ. ํนํ ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ๋ ์ํ ๊ด๋ฆฌ๋ฅผ ํจ์จ์ ์ผ๋ก ํ ์ ์๊ฒ ํด์ฃผ๊ฑฐ๋ . ๋ค์ ์น์ ์์๋ ์ด๋ฐ ๊ฐ๋ ์ ์ค์ ๋ก ๊ตฌํํ ์ธ๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ดํด๋ณผ๊ฒ! ๐
5. Immer, Immutable.js ๋ฑ ์ธ๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ดํด๋ณด๊ธฐ ๐ฆ
๋ถ๋ณ์ฑ์ ์ฝ๊ฒ ๋ค๋ฃจ๊ธฐ ์ํ ๋ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์์ด. 2025๋ ํ์ฌ ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ดํด๋ณด์! ๐
์ฃผ์ ๋ถ๋ณ์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋น๊ต
1. Immer ๐ฅ
Immer๋ 2025๋ ํ์ฌ ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ๋ถ๋ณ์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. ์ง๊ด์ ์ธ API์ ๋ฐ์ด๋ ์ฑ๋ฅ์ผ๋ก ๋ง์ ๊ฐ๋ฐ์๋ค์ ์ฌ๋์ ๋ฐ๊ณ ์์ง.
ํน์ง:
- ๊ฐ๋ณ์ ์ธ ์ฝ๋ ์คํ์ผ๋ก ๋ถ๋ณ ์ ๋ฐ์ดํธ๋ฅผ ์์ฑํ ์ ์์ด (draft ๊ฐ๋ )
- ์ค์ฒฉ๋ ๊ฐ์ฒด๋ ์ฝ๊ฒ ์ ๋ฐ์ดํธ ๊ฐ๋ฅ
- ๋ฒ๋ค ํฌ๊ธฐ๊ฐ ์๊ณ ์ฑ๋ฅ์ด ์ข์
- TypeScript์์ ํธํ์ฑ์ด ๋ฐ์ด๋จ
- React์ Redux์์ ํนํ ์ ์๋
์ฌ์ฉ ์์ :
import produce from 'immer';
const baseState = {
users: [
{ id: 1, name: '์ฒ ์' },
{ id: 2, name: '์ํฌ' }
],
settings: {
darkMode: false,
notifications: true
}
};
// ๋ถ๋ณ ์
๋ฐ์ดํธ๋ฅผ ๊ฐ๋ณ์ ์คํ์ผ๋ก ์์ฑ
const nextState = produce(baseState, draft => {
// ๋ง์น ์ง์ ์์ ํ๋ ๊ฒ์ฒ๋ผ ์ฝ๋๋ฅผ ์์ฑ
draft.users.push({ id: 3, name: '๋ฏผ์' });
draft.users[0].name = '์ํผ ์ฒ ์';
draft.settings.darkMode = true;
});
// baseState๋ ๋ณ๊ฒฝ๋์ง ์๊ณ , nextState๋ ์ ๊ฐ์ฒด
2. Immutable.js ๐ฅ
Facebook์ด ๊ฐ๋ฐํ Immutable.js๋ ์์ ํ ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ ์ธํธ๋ฅผ ์ ๊ณตํด. ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์ ์์ ํนํ ๊ฐ๋ ฅํด.
ํน์ง:
- Map, List, Set ๋ฑ ๋ค์ํ ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ ์ ๊ณต
- ๊ตฌ์กฐ ๊ณต์ ๋ฅผ ํตํ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ
- ํ๋ถํ API์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ
- ๋๊ท๋ชจ ๋ฐ์ดํฐ์ ์์๋ ๋ฐ์ด๋ ์ฑ๋ฅ
- ๊น์ ์ค์ฒฉ ๊ตฌ์กฐ์์ ํจ์จ์
์ฌ์ฉ ์์ :
import { Map, List } from 'immutable';
// ๋ถ๋ณ ๋งต ์์ฑ
const state = Map({
users: List([
Map({ id: 1, name: '์ฒ ์' }),
Map({ id: 2, name: '์ํฌ' })
]),
settings: Map({
darkMode: false,
notifications: true
})
});
// ๋ถ๋ณ ์
๋ฐ์ดํธ
const nextState = state
.updateIn(['users'], users => users.push(Map({ id: 3, name: '๋ฏผ์' })))
.setIn(['users', 0, 'name'], '์ํผ ์ฒ ์')
.setIn(['settings', 'darkMode'], true);
// ๋ฐ์ดํฐ ์ ๊ทผ
console.log(nextState.getIn(['users', 0, 'name'])); // '์ํผ ์ฒ ์'
3. Immutability Helper ๐ฅ
React์์ ์๋ ์ ๊ณต๋์๋ ๊ฐ๋จํ ์ ํธ๋ฆฌํฐ๋ก, ์ง๊ธ์ ๋ณ๋ ํจํค์ง๋ก ๋ถ๋ฆฌ๋์์ด.
ํน์ง:
- ๊ฐ๋จํ API๋ก ์ฝ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅ
- MongoDB์ ์ฟผ๋ฆฌ ์ธ์ด์ ์ ์ฌํ ๋ฌธ๋ฒ
- ๋ฒ๋ค ํฌ๊ธฐ๊ฐ ์์
- ๊ธฐ๋ณธ์ ์ธ ๋ถ๋ณ ์ ๋ฐ์ดํธ ์์ ์ ์ ํฉ
์ฌ์ฉ ์์ :
import update from 'immutability-helper';
const state = {
users: [
{ id: 1, name: '์ฒ ์' },
{ id: 2, name: '์ํฌ' }
],
settings: {
darkMode: false,
notifications: true
}
};
const nextState = update(state, {
users: {
$push: [{ id: 3, name: '๋ฏผ์' }],
0: { name: { $set: '์ํผ ์ฒ ์' } }
},
settings: { darkMode: { $set: true } }
});
4. 2025๋ ์ ํฅ ๋ผ์ด๋ธ๋ฌ๋ฆฌ: ImmutableState ๐
2025๋ ์ ์๋กญ๊ฒ ๋ ์ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, AI ๊ธฐ๋ฐ ์ต์ ํ์ ์น์ด์ ๋ธ๋ฆฌ ๊ฐ์์ ํน์ง์ผ๋ก ํด.
ํน์ง:
- ์น์ด์ ๋ธ๋ฆฌ๋ก ๊ตฌํ๋์ด ๋ค์ดํฐ๋ธ์ ๊ฐ๊น์ด ์ฑ๋ฅ
- AI ๊ธฐ๋ฐ ์ฌ์ฉ ํจํด ๋ถ์์ผ๋ก ์๋ ์ต์ ํ
- ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ค์๊ฐ ๋ชจ๋ํฐ๋ง ๊ธฐ๋ฅ
- ๋๊ท๋ชจ ๋ฐ์ดํฐ์ ์ ์ต์ ํ๋จ
- TypeScript์ ์๋ฒฝํ๊ฒ ํตํฉ
์ฌ์ฉ ์์ :
import { createState, mutate } from 'immutablestate';
// ์ด๊ธฐ ์ํ ์์ฑ
const state = createState({
users: [
{ id: 1, name: '์ฒ ์' },
{ id: 2, name: '์ํฌ' }
],
settings: {
darkMode: false,
notifications: true
}
});
// AI ์ต์ ํ๋ ๋ถ๋ณ ์
๋ฐ์ดํธ
const nextState = mutate(state, state => {
state.users.push({ id: 3, name: '๋ฏผ์' });
state.users[0].name = '์ํผ ์ฒ ์';
state.settings.darkMode = true;
// ๋ด๋ถ์ ์ผ๋ก ์ต์ ์ ๋ถ๋ณ ์
๋ฐ์ดํธ ์ ๋ต์ ์๋ ์ ํ
});
๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋น๊ต ์ฐจํธ
์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ํํด์ผ ํ ๊น? ๐ค
์ํฉ๋ณ ์ถ์ฒ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- ์ผ๋ฐ์ ์ธ React/Redux ํ๋ก์ ํธ: Immer - ์ง๊ด์ ์ธ API์ ํ๋ฅญํ ์ฑ๋ฅ ๋ฐธ๋ฐ์ค
- ๋๊ท๋ชจ ๋ฐ์ดํฐ์ ๋ค๋ฃจ๋ ์ ํ๋ฆฌ์ผ์ด์ : Immutable.js ๋๋ ImmutableState - ์ต์ ํ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ
- ๋ฒ๋ค ํฌ๊ธฐ๊ฐ ์ค์ํ ์๊ท๋ชจ ํ๋ก์ ํธ: Immutability Helper - ์์ ํฌ๊ธฐ์ ๊ฐ๋จํ API
- ์ต์ ๊ธฐ์ ์คํ๊ณผ ์ต๊ณ ์ ์ฑ๋ฅ์ด ํ์ํ ๊ฒฝ์ฐ: ImmutableState - ์น์ด์ ๋ธ๋ฆฌ ๊ฐ์๊ณผ AI ์ต์ ํ
ํ๋ก์ ํธ์ ํน์ฑ๊ณผ ํ์ ์น์๋๋ฅผ ๊ณ ๋ คํด ์ ํํ๋ ๊ฒ์ด ์ค์ํด. ์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ถ๋ณ์ฑ์ ๊ธฐ๋ณธ ์์น์ ์ดํดํ๊ณ ์๋ค๋ฉด ํ์์ ๋ฐ๋ผ ์ ํํ๊ธฐ ์ฌ์ธ ๊ฑฐ์ผ!
์ด๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ฌ๋ฅ๋ท์์๋ ๋ง์ ๊ฐ๋ฐ์๋ค์ด ๊ณต์ ํ๊ณ ํ ๋ก ํ๋ ์ฃผ์ ์ผ. ํนํ ํ๋ก ํธ์๋ ๊ฐ๋ฐ ์ฌ๋ฅ์ ๊ฐ์ง ์ฌ๋๋ค์ด ์์ฃผ ๋ค๋ฃจ๋ ๋ด์ฉ์ด์ง. ๋ค์ ์น์ ์์๋ ์ด๋ฐ ๋ถ๋ณ์ฑ ๊ฐ๋ ์ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํด ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ์์๋ณผ๊ฒ! ๐
6. ์ค์ ์์ : ๋ถ๋ณ์ฑ์ผ๋ก ์ฑ๋ฅ ์ต์ ํํ๊ธฐ โก
์ด๋ก ์ ์ถฉ๋ถํ ์์๋ดค์ผ๋, ์ด์ ์ค์ ์ฝ๋์์ ๋ถ๋ณ์ฑ์ ํ์ฉํด ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด์! ๐
React์์ ๋ถ๋ณ์ฑ์ ํ์ฉํ ๋ ๋๋ง ์ต์ ํ ๐
React๋ ์ปดํฌ๋ํธ์ ๋ฆฌ๋ ๋๋ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ๋ ์์ ๋น๊ต(shallow comparison)๋ฅผ ์ฌ์ฉํด. ๋ถ๋ณ์ฑ์ ํ์ฉํ๋ฉด ์ด ๋ฉ์ปค๋์ฆ์ ํ์ฉํด ๋ถํ์ํ ๋ ๋๋ง์ ๋ฐฉ์งํ ์ ์์ด.
React.memo์ ๋ถ๋ณ์ฑ์ ํ์ฉํ ์ต์ ํ
import React, { useState } from 'react';
import { produce } from 'immer';
// ์ต์ ํ๋ ํ ์ผ ํญ๋ชฉ ์ปดํฌ๋ํธ
const TodoItem = React.memo(({ todo, onToggle }) => {
console.log(`TodoItem ๋ ๋๋ง: ${todo.text}`);
return (
<div style="{{" textdecoration: todo.completed :>
<input type="checkbox" checked onchange="{()"> onToggle(todo.id)}
/>
{todo.text}
</div>
);
});
// ํ ์ผ ๋ชฉ๋ก ์ปดํฌ๋ํธ
function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, text: '๋ถ๋ณ์ฑ ๊ณต๋ถํ๊ธฐ', completed: false },
{ id: 2, text: 'React ์ต์ ํํ๊ธฐ', completed: false },
{ id: 3, text: '์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ ์ดํดํ๊ธฐ', completed: false }
]);
// ๋ถ๋ณ์ ์ผ๋ก ํ ์ผ ์ํ ํ ๊ธํ๊ธฐ
const handleToggle = (id) => {
setTodos(
produce(todos, draft => {
const todo = draft.find(t => t.id === id);
if (todo) {
todo.completed = !todo.completed;
}
})
);
};
return (
<div>
<h2>ํ ์ผ ๋ชฉ๋ก</h2>
{todos.map(todo => (
<todoitem key="{todo.id}" todo="{todo}" ontoggle="{handleToggle}"></todoitem>
))}
</div>
);
}
์ ์์ ์์ React.memo์ Immer๋ฅผ ํจ๊ป ์ฌ์ฉํด ์ต์ ํ๋ฅผ ๊ตฌํํ์ด. ํน์ ํ ์ผ ํญ๋ชฉ์ ํ ๊ธํ ๋, ํด๋น ํญ๋ชฉ๋ง ์ ๊ฐ์ฒด๋ก ์์ฑ๋๊ณ ๋๋จธ์ง๋ ๊ทธ๋๋ก ์ ์ง๋ผ. ๋ฐ๋ผ์ ๋ณ๊ฒฝ๋ ํญ๋ชฉ๋ง ๋ฆฌ๋ ๋๋ง๋์ด ์ฑ๋ฅ์ด ํฅ์๋ผ!
์ต์ ํ ์ /ํ ๋น๊ต
Redux์์ ๋ถ๋ณ์ฑ์ ํ์ฉํ ์ํ ๊ด๋ฆฌ ์ต์ ํ ๐
Redux๋ ๋ถ๋ณ์ฑ์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. Immer๋ฅผ Redux์ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋ณต์กํ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ์์ฑํ ์ ์์ด.
Redux + Immer๋ฅผ ํ์ฉํ ์ํ ๊ด๋ฆฌ
// Redux ๋ฆฌ๋์์ Immer ์ ์ฉํ๊ธฐ
import { createSlice } from '@reduxjs/toolkit';
const todosSlice = createSlice({
name: 'todos',
initialState: {
items: [],
loading: false,
error: null
},
reducers: {
// createSlice๋ ๋ด๋ถ์ ์ผ๋ก Immer๋ฅผ ์ฌ์ฉํจ
addTodo: (state, action) => {
// ๊ฐ๋ณ์ ์ธ ์ฝ๋ ์คํ์ผ๋ก ๋ถ๋ณ ์
๋ฐ์ดํธ ์์ฑ
state.items.push({
id: Date.now(),
text: action.payload,
completed: false
});
},
toggleTodo: (state, action) => {
const todo = state.items.find(item => item.id === action.payload);
if (todo) {
todo.completed = !todo.completed;
}
},
removeTodo: (state, action) => {
state.items = state.items.filter(item => item.id !== action.payload);
}
}
});
export const { addTodo, toggleTodo, removeTodo } = todosSlice.actions;
export default todosSlice.reducer;
Redux Toolkit์ ๋ด๋ถ์ ์ผ๋ก Immer๋ฅผ ์ฌ์ฉํด ์ง๊ด์ ์ธ ์ฝ๋ ์คํ์ผ๋ก ๋ถ๋ณ ์ ๋ฐ์ดํธ๋ฅผ ์์ฑํ ์ ์๊ฒ ํด์ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋๋ ๊ฐ๊ฒฐํด์ง๋ฉด์๋ ๋ถ๋ณ์ฑ์ ๋ชจ๋ ์ด์ ์ ๋๋ฆด ์ ์์ด!
๋๊ท๋ชจ ๋ฐ์ดํฐ์ ์์์ ์ฑ๋ฅ ์ต์ ํ ๐
์์ฒ ๊ฐ์ ํญ๋ชฉ์ ๊ฐ์ง ๋๊ท๋ชจ ๋ฐ์ดํฐ์ ์ ๋ค๋ฃฐ ๋๋ ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ํ์ฉํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํนํ ์ ์ฉํด.
Immutable.js๋ฅผ ํ์ฉํ ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
import { List, Map } from 'immutable';
// ๋๊ท๋ชจ ์ฌ์ฉ์ ๋ฐ์ดํฐ (์์ฒ ๋ช
)
let users = List();
// ์ด๊ธฐ ๋ฐ์ดํฐ ์์ฑ
for (let i = 0; i < 10000; i++) {
users = users.push(Map({
id: i,
name: `User ${i}`,
active: Math.random() > 0.5
}));
}
// ํน์ ์กฐ๊ฑด์ ์ฌ์ฉ์๋ง ํํฐ๋ง (๋ถ๋ณ์ ์ฐ์ฐ)
const activeUsers = users.filter(user => user.get('active'));
// ๋ชจ๋ ์ฌ์ฉ์์ ์ด๋ฆ์ ๋ณํ (๋ถ๋ณ์ ์ฐ์ฐ)
const userNames = users.map(user => user.get('name'));
// ํน์ ID์ ์ฌ์ฉ์ ์ฐพ๊ธฐ (ํจ์จ์ ์ธ ๊ฒ์)
const findUser = (id) => {
// ์ด์ง ๊ฒ์ ๋ฑ์ ์ต์ ํ๋ ์๊ณ ๋ฆฌ์ฆ ํ์ฉ ๊ฐ๋ฅ
return users.find(user => user.get('id') === id);
};
// ํน์ ์ฌ์ฉ์ ์ ๋ณด ์
๋ฐ์ดํธ (๋ถ๋ณ์ ์
๋ฐ์ดํธ)
const updateUser = (id, updates) => {
const index = users.findIndex(user => user.get('id') === id);
if (index !== -1) {
users = users.update(index, user => user.merge(updates));
}
return users;
};
Immutable.js๋ ๋ด๋ถ์ ์ผ๋ก ํจ์จ์ ์ธ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด ๋๊ท๋ชจ ๋ฐ์ดํฐ์ ์์๋ ๋น ๋ฅธ ์ฑ๋ฅ์ ์ ๊ณตํด. ํนํ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ด ๋น๋ฒํ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋๊ณผ ์ฑ๋ฅ์ ํฌ๊ฒ ๊ฐ์ ํ ์ ์์ด.
โก ์ฑ๋ฅ ์ต์ ํ ํ
- ์์ ๋น๊ต ํ์ฉํ๊ธฐ: React.memo, PureComponent, shouldComponentUpdate ๋ฑ์ ํ์ฉํด ๋ถ๋ณ์ฑ์ ์ด์ ์ ์ต๋ํํ์ธ์.
- ์ ํ์ ๋ ๋๋ง: ์ํ ๋ณ๊ฒฝ ์ ์ํฅ๋ฐ๋ ์ปดํฌ๋ํธ๋ง ๋ ๋๋ง๋๋๋ก ์ํ ๊ตฌ์กฐ๋ฅผ ์ค๊ณํ์ธ์.
- ์ ๊ทํ๋ ์ํ ๊ตฌ์กฐ: ์ค์ฒฉ์ ์ต์ํํ๊ณ ID ๊ธฐ๋ฐ ์ฐธ์กฐ๋ฅผ ํ์ฉํด ์ํ ์ ๋ฐ์ดํธ๋ฅผ ๋จ์ํํ์ธ์.
- ๋ฉ๋ชจ์ด์ ์ด์ : useMemo์ useCallback์ ํ์ฉํด ๊ณ์ฐ ๋น์ฉ์ด ํฐ ์ฐ์ฐ์ ์ต์ ํํ์ธ์.
- ๋ฐฐ์น ์ ๋ฐ์ดํธ: ์ฌ๋ฌ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ํ ๋ฒ์ ์ฒ๋ฆฌํด ๋ถํ์ํ ๋ ๋๋ง์ ์ค์ด์ธ์.
์ด๋ฐ ์ต์ ํ ๊ธฐ๋ฒ๋ค์ ์ค์ ํ๋ก์ ํธ์์ ๋์ ๋๋ ์ฑ๋ฅ ํฅ์์ ๊ฐ์ ธ์ฌ ์ ์์ด. ํนํ ์ฌ์ฉ์ ์ธํฐํ์ด์ค์ ๋ฐ์์ฑ๊ณผ ๋ถ๋๋ฌ์์ด ์ค์ํ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋์ฑ ๊ทธ๋ ์ง. ๋ค์ ์น์ ์์๋ 2025๋ ํ์ฌ์ ๋ถ๋ณ์ฑ ํธ๋ ๋์ ๋ฏธ๋ ์ ๋ง์ ๋ํด ์์๋ณผ๊ฒ! ๐ฎ
7. 2025๋ ์ต์ ํธ๋ ๋์ ๋ฏธ๋ ์ ๋ง ๐ฎ
2025๋ ํ์ฌ, JavaScript ์ํ๊ณ์์ ๋ถ๋ณ์ฑ๊ณผ ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ๊ณ์ ๋ฐ์ ํ๊ณ ์์ด. ์ต์ ํธ๋ ๋์ ์์ผ๋ก์ ์ ๋ง์ ์ดํด๋ณด์! ๐
2025๋ ํ์ฌ์ ๋ถ๋ณ์ฑ ํธ๋ ๋ ๐
-
์น์ด์
๋ธ๋ฆฌ ๊ธฐ๋ฐ ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ
์ต์ ๋ถ๋ณ์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ฑ๋ฅ ํฅ์์ ์ํด ์น์ด์ ๋ธ๋ฆฌ(WebAssembly)๋ฅผ ํ์ฉํ๊ณ ์์ด. ์ด๋ฅผ ํตํด ๋ค์ดํฐ๋ธ์ ๊ฐ๊น์ด ์ฑ๋ฅ์ผ๋ก ๋ถ๋ณ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋์์ง.
-
AI ์ต์ ํ ๋ถ๋ณ์ฑ
๋จธ์ ๋ฌ๋์ ํ์ฉํด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ดํฐ ์ ๊ทผ ํจํด์ ๋ถ์ํ๊ณ , ์๋์ผ๋ก ์ต์ ์ ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ ํํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ๋ฑ์ฅํ์ด.
-
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ฃผ๋ฅํ
๋ถ๋ณ์ฑ์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ด JavaScript ์ํ๊ณ์์ ๋์ฑ ์ฃผ๋ฅ๊ฐ ๋์์ด. ํนํ React์ ๊ฐ์ ์ธ๊ธฐ ํ๋ ์์ํฌ์ ์ํฅ์ด ํฌ์ง.
-
ํ์
์์คํ
๊ณผ์ ํตํฉ
TypeScript์ ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ํตํฉ์ด ๋์ฑ ๊ฐํ๋์ด, ํ์ ์์ ์ฑ๊ณผ ๋ถ๋ณ์ฑ์ ๋์์ ๋ณด์ฅํ๋ ํจํด์ด ์ธ๊ธฐ๋ฅผ ๋๊ณ ์์ด.
-
์ค์๊ฐ ํ์
์ ํ๋ฆฌ์ผ์ด์
CRDT(Conflict-free Replicated Data Types)์ ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ๊ณผ ๋ถ๋ณ์ฑ์ ๊ฒฐํฉํด ์ค์๊ฐ ํ์ ์ ํ๋ฆฌ์ผ์ด์ ์์์ ๋ฐ์ดํฐ ์ผ๊ด์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์ ๊ทผ๋ฒ์ด ์ฃผ๋ชฉ๋ฐ๊ณ ์์ด.
๋ถ๋ณ์ฑ์ ๋ฏธ๋ ์ ๋ง
๋ฏธ๋์ ๋ถ๋ณ์ฑ ๋ฐ์ ๋ฐฉํฅ ๐
-
์ธ์ด ์์ค์ ๋ถ๋ณ์ฑ ์ง์
JavaScript ์ธ์ด ์์ฒด์ ๋ถ๋ณ ๋ฐ์ดํฐ ํ์ ๊ณผ ์ฐ์ฐ์๊ฐ ์ถ๊ฐ๋ ๊ฐ๋ฅ์ฑ์ด ๋์. ECMAScript ์ ์ ์ค์๋ Record & Tuple์ด๋ผ๋ ์๋ก์ด ๋ถ๋ณ ๋ฐ์ดํฐ ํ์ ์ด ์์ด.
// ๋ฏธ๋์ JavaScript ๋ฌธ๋ฒ (์์) // Record๋ ๋ถ๋ณ ๊ฐ์ฒด, Tuple์ ๋ถ๋ณ ๋ฐฐ์ด const user = #{ name: "์ฒ ์", age: 30, hobbies: #["์ฝ๋ฉ", "๋ ์"] }; // ๋ถ๋ณ์ฑ์ด ๋ณด์ฅ๋จ // user.age = 31; // ์ค๋ฅ ๋ฐ์! // ์ Record ์์ฑ const updatedUser = #{...user, age: 31};
-
ํ๋์จ์ด ๊ฐ์ ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ
GPU๋ ์ ์ฉ ํ๋์จ์ด๋ฅผ ํ์ฉํด ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์ฐ์ฐ์ ๊ฐ์ํํ๋ ๊ธฐ์ ์ด ๋ฐ์ ํ ๊ฑฐ์ผ. ์ด๋ ๋๊ท๋ชจ ๋ฐ์ดํฐ์ ์์ ํนํ ์ค์ํ ๋ฐ์ ์ด ๋ ๊ฑฐ์ผ.
-
์์ ์ปดํจํ
๊ณผ ๋ถ๋ณ์ฑ
์์ ์ปดํจํ ์ด ๋ฐ์ ํจ์ ๋ฐ๋ผ, ์์ ์ํ์ ๋ถ๋ณ์ฑ์ ํ์ฉํ ์๋ก์ด ์๊ณ ๋ฆฌ์ฆ๊ณผ ๋ฐ์ดํฐ ๊ตฌ์กฐ๊ฐ ๋ฑ์ฅํ ์ ์์ด.
-
๋ถ์ฐ ์์คํ
์์์ ๋ถ๋ณ์ฑ
๋ธ๋ก์ฒด์ธ๊ณผ ๊ฐ์ ๋ถ์ฐ ์์คํ ์์ ๋ถ๋ณ์ฑ์ ๋์ฑ ์ค์ํ ์ญํ ์ ํ๊ฒ ๋ ๊ฑฐ์ผ. ํนํ ๋ฐ์ดํฐ ์ผ๊ด์ฑ๊ณผ ๊ฐ์ฌ ์ถ์ (audit trail)์ด ์ค์ํ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ง์ด์ผ.
-
AI์ ๋ถ๋ณ์ฑ์ ๊ฒฐํฉ
AI ๋ชจ๋ธ์ด ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๋ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ณ ์ต์ ํํ๋ ๋ฐฉํฅ์ผ๋ก ๋ฐ์ ํ ๊ฑฐ์ผ. ์ด๋ ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ์ค์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์์ ํ์ ์ ๊ฐ์ ธ์ฌ ์ ์์ด.
๊ฒฐ๋ก : ๋ถ๋ณ์ฑ์ ๋ฏธ๋์ ํต์ฌ ํจ๋ฌ๋ค์
๋ถ๋ณ์ฑ๊ณผ ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ๋จ์ํ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฒ์ ๋์ด, ์ํํธ์จ์ด ์ค๊ณ์ ๊ทผ๋ณธ์ ์ธ ํจ๋ฌ๋ค์์ผ๋ก ์๋ฆฌ ์ก๊ณ ์์ด. ๋ฐ์ดํฐ์ ์์ด ํญ๋ฐ์ ์ผ๋ก ์ฆ๊ฐํ๊ณ , ๋ถ์ฐ ์์คํ ๊ณผ ์ค์๊ฐ ํ์ ์ด ์ผ์ํ๋๋ ๋ฏธ๋์๋ ๋ถ๋ณ์ฑ์ ์ค์์ฑ์ด ๋์ฑ ์ปค์ง ๊ฑฐ์ผ.
JavaScript ๊ฐ๋ฐ์๋ผ๋ฉด ๋ถ๋ณ์ฑ๊ณผ ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ํ ๊น์ ์ดํด๋ฅผ ๊ฐ์ถ๋ ๊ฒ์ด ๋ฏธ๋๋ฅผ ๋๋นํ๋ ์ค์ํ ํฌ์๊ฐ ๋ ๊ฑฐ์ผ. ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ์์ ์ด๋ฐ ์ง์์ ๊ณต์ ํ๊ณ ๋ฐฐ์ฐ๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด์ง!
๋ถ๋ณ์ฑ์ ๋จ์ํ ๋ฒ๊ทธ๋ฅผ ์ค์ด๋ ๊ฒ์ ๋์ด, ๋ ์์ธก ๊ฐ๋ฅํ๊ณ , ํ ์คํธํ๊ธฐ ์ฝ๊ณ , ํ์ฅ ๊ฐ๋ฅํ ์ํํธ์จ์ด๋ฅผ ๋ง๋๋ ์ด์ ์ผ. ์์ผ๋ก๋ ์ด ๊ฐ๋ ์ ๊ณ์ ๋ฐ์ ํ๊ณ ์งํํ ํ ๋, ๊ณ์ํด์ ๊ด์ฌ์ ๊ฐ์ง๊ณ ๋ฐ๋ผ๊ฐ ๋ณด์! ๐
๋ถ๋ณ์ฑ์ ์ธ๊ณ๋ก ๋ฐ์ด๋ค ์ค๋น๊ฐ ๋์๋์? ๐
์ด ๊ธ์ด JavaScript์ ๋ถ๋ณ์ฑ๊ณผ ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ํ ์ดํด๋ฅผ ๋์ด๋ ๋ฐ ๋์์ด ๋์๊ธธ ๋ฐ๋ผ! ๋ ๋ง์ ํ๋ก๊ทธ๋๋ฐ ์ง์๊ณผ ํ์ ์ป๊ณ ์ถ๋ค๋ฉด ์ฌ๋ฅ๋ท์ '์ง์์ธ์ ์ฒ'์ ๊ณ์ ๋ฐฉ๋ฌธํด์ฃผ์ธ์.
๋ํ ํ๋ก๊ทธ๋๋ฐ ๊ด๋ จ ๋์์ด ํ์ํ๊ฑฐ๋ ์์ ์ ํ๋ก๊ทธ๋๋ฐ ์ฌ๋ฅ์ ๊ณต์ ํ๊ณ ์ถ๋ค๋ฉด, ์ฌ๋ฅ๋ท์์ ๋ค์ํ ๊ฐ๋ฐ์๋ค๊ณผ ์ฐ๊ฒฐ๋ ์ ์์ด์! ํจ๊ป ์ฑ์ฅํ๋ ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ์์ ๋ง๋์! ๐
1. ๋ถ๋ณ์ฑ์ด๋ ๋ฌด์์ธ๊ฐ? ๊ทธ๋ฆฌ๊ณ ์ ์ค์ํ ๊น? ๐ค
๋ถ๋ณ์ฑ(Immutability)์ ํ๋ฒ ์์ฑ๋ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ ์ ์๊ฒ ๋ง๋๋ ๊ฐ๋ ์ด์ผ. ์ฝ๊ฒ ๋งํ๋ฉด, "ํ๋ฒ ๋ง๋ค์ด์ง ๊ฒ์ ๋ฐ๊พธ์ง ์๊ณ , ํ์ํ๋ฉด ์๋ก ๋ง๋ ๋ค"๋ ์์น์ด์ง. ๋ง์น ๋์ ์ผ๊ธฐ์ฅ์ฒ๋ผ - ํ๋ฒ ์ด ๋ด์ฉ์ ์ง์ฐ๊ฐ๋ก ์ง์ฐ๊ณ ๋ค์ ์ฐ๋ ๊ฒ ์๋๋ผ, ์ ํ์ด์ง์ ์๋ก์ด ๋ด์ฉ์ ์ฐ๋ ๊ฑฐ์ผ. ๐
๐ ๊ฐ๋ณ์ฑ vs ๋ถ๋ณ์ฑ
๊ฐ๋ณ์ฑ(Mutability):
- ๋ฐ์ดํฐ๊ฐ ์์ฑ๋ ํ์๋ ๋ด์ฉ์ ๋ณ๊ฒฝํ ์ ์์
- ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ๊ณ์ ์ฌ์ฉ
- ์: ๋ฐฐ์ด์ push(), pop(), ๊ฐ์ฒด ์์ฑ ์ง์ ์์
๋ถ๋ณ์ฑ(Immutability):
- ๋ฐ์ดํฐ๊ฐ ์์ฑ๋ ํ์๋ ๋ด์ฉ์ ๋ณ๊ฒฝํ ์ ์์
- ๋ณ๊ฒฝ์ด ํ์ํ๋ฉด ์๋ก์ด ๋ฉ๋ชจ๋ฆฌ์ ๋ณต์ฌ๋ณธ ์์ฑ
- ์: ๋ฌธ์์ด ๋ฉ์๋๋ค, Array.map(), Array.filter()
์ ๋ถ๋ณ์ฑ์ด ์ค์ํ ๊น? ๐
- ์์ธก ๊ฐ๋ฅ์ฑ: ๋ฐ์ดํฐ๊ฐ ์ธ์ ์ด๋์ ๋ณํ ์ง ๊ฑฑ์ ํ ํ์๊ฐ ์์ด. ํ๋ฒ ๋ง๋ค์ด์ง ๋ฐ์ดํฐ๋ ํญ์ ๊ฐ์ ์ํ๋ฅผ ์ ์งํ๋๊น!
- ๋๋ฒ๊น ์ฉ์ด์ฑ: ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ์ ๋ ๋ฐ์ดํฐ ๋ณํ๋ฅผ ์ถ์ ํ๊ธฐ ์ฌ์์ ธ. "๋๊ฐ ์ด ๋ฐ์ดํฐ๋ฅผ ๋ฐ๊ฟจ์ง?"๋ผ๋ ์ง๋ฌธ์ด ์ฌ๋ผ์ง๋๊น.
- ๋์์ฑ ์ฒ๋ฆฌ: ์ฌ๋ฌ ํจ์๋ ์ค๋ ๋๊ฐ ๋์์ ๊ฐ์ ๋ฐ์ดํฐ์ ์ ๊ทผํด๋ ์ถฉ๋์ด ์์ด.
- ์๊ฐ ์ฌํ ๋๋ฒ๊น : ์ด์ ์ํ๋ก ์ฝ๊ฒ ๋์๊ฐ ์ ์์ด. Redux DevTools ๊ฐ์ ๋๊ตฌ๊ฐ ์ด๋ฅผ ํ์ฉํ์ง.
- ์ฐธ์กฐ ๋๋ฑ์ฑ ์ต์ ํ: ๊ฐ์ฒด๊ฐ ๋ณ๊ฒฝ๋์๋์ง ๋น ๋ฅด๊ฒ ํ์ธํ ์ ์์ด (๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ง ๋น๊ตํ๋ฉด ๋จ).
"๋ถ๋ณ์ฑ์ ๋จ์ํ ์ฝ๋ฉ ์คํ์ผ์ด ์๋๋ผ, ์ํํธ์จ์ด ์ค๊ณ์ ์ฒ ํ์ด๋ค."
- ์ด๋ค ํ๋ช ํ ๊ฐ๋ฐ์ ๐
2. JavaScript์์์ ๊ฐ๋ณ์ฑ ๋ฌธ์ ์ ๐ฑ
JavaScript๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ๋ณ(mutable) ์ธ์ด์ผ. ํนํ ๊ฐ์ฒด์ ๋ฐฐ์ด์ ์ฐธ์กฐ ํ์ ์ด๋ผ์ ์์์น ๋ชปํ ๋ถ์์ฉ(side effects)์ ์ผ์ผํค๊ธฐ ์ฝ์ง. ์๋ ์์ ๋ฅผ ํ๋ฒ ๋ณผ๊น?
// ๊ฐ๋ณ์ฑ์ผ๋ก ์ธํ ๋ฌธ์ ์์
const user = { name: '์ฒ ์', age: 25 };
const userCopy = user; // ์ฐธ์กฐ๋ง ๋ณต์ฌ๋จ
userCopy.age = 26; // userCopy๋ง ๋ณ๊ฒฝํ๋ ค๊ณ ํ๋๋ฐ...
console.log(user.age); // 26 - ์๋ณธ user๋ ๋ณ๊ฒฝ๋จ! ๐ฑ
์ ์ฝ๋์์ ์ฐ๋ฆฌ๋ userCopy๋ง ๋ณ๊ฒฝํ๋ ค๊ณ ํ์ง๋ง, ์ค์ ๋ก๋ ์๋ณธ user ๊ฐ์ฒด๋ ํจ๊ป ๋ณ๊ฒฝ๋์์ด. ์ด๊ฒ ๋ฐ๋ก ๊ฐ๋ณ์ฑ์ ํจ์ ์ด์ผ! ์ด๋ฐ ํ์์ "์๋์น ์์ ๋ถ์์ฉ(side effect)"์ด๋ผ๊ณ ํด.
๐จ ๊ฐ๋ณ์ฑ์ด ์ผ์ผํค๋ ์ฃผ์ ๋ฌธ์ ๋ค
- ์์ธก ๋ถ๊ฐ๋ฅํ ์ฝ๋: ๊ฐ์ฒด๊ฐ ์ธ์ ์ด๋์ ๋ณ๊ฒฝ๋ ์ง ์ ์ ์์ด ์ฝ๋ ํ๋ฆ์ ์ถ์ ํ๊ธฐ ์ด๋ ค์์ ธ.
- ๋ฒ๊ทธ ์ฐพ๊ธฐ ์ด๋ ค์: "์ด ๋ฐ์ดํฐ๋ ๋ถ๋ช ์ด๋ ๊ฒ ์ค์ ํ๋๋ฐ ์ ๋ฐ๋์์ง?" ๊ฐ์ ์ํฉ์ด ๋ฐ์ํด.
- ํจ์ ์์์ฑ ํผ์: ๊ฐ์ ์ ๋ ฅ์ ํญ์ ๊ฐ์ ์ถ๋ ฅ์ ๋ณด์ฅํ๋ ์์ ํจ์๋ฅผ ๋ง๋ค๊ธฐ ์ด๋ ค์์ ธ.
- ํ ์คํธ ๋ณต์ก์ฑ ์ฆ๊ฐ: ๊ฐ๋ณ ๋ฐ์ดํฐ๋ ํ ์คํธ ํ๊ฒฝ์ ์ค์ ํ๊ณ ๊ฒ์ฆํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค์ด.
- ๋์์ฑ ๋ฌธ์ : ์ฌ๋ฌ ํจ์๊ฐ ๋์์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ฉด ๊ฒฝ์ ์ํ(race condition)๊ฐ ๋ฐ์ํ ์ ์์ด.
์ด๋ฐ ๋ฌธ์ ๋ค ๋๋ฌธ์ ํ๋ JavaScript ๊ฐ๋ฐ์์๋ ๋ถ๋ณ์ฑ์ ์ ๊ทน์ ์ผ๋ก ๋์ ํ๊ณ ์์ด. React, Redux, Vue ๊ฐ์ ์ธ๊ธฐ ํ๋ ์์ํฌ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค๋ ๋ถ๋ณ์ฑ ์์น์ ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณ๋์์ง. ํนํ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ์ํคํ ์ฒ์์๋ ์ํ ๋ณํ๋ฅผ ์์ธก ๊ฐ๋ฅํ๊ฒ ๊ด๋ฆฌํ๋ ๊ฒ์ด ๋งค์ฐ ์ค์ํ๊ฑฐ๋ . ๐งฉ
3. ๋ถ๋ณ์ฑ ๊ตฌํํ๊ธฐ: ๊ธฐ๋ณธ ํ ํฌ๋ ๐ ๏ธ
์ด์ JavaScript์์ ๋ถ๋ณ์ฑ์ ์ด๋ป๊ฒ ๊ตฌํํ ์ ์๋์ง ์์๋ณด์! ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ๋ถํฐ ์์ํด์ ์ ์ ๊ณ ๊ธ ํ ํฌ๋์ผ๋ก ๋์๊ฐ๊ฒ. ๐
๊ธฐ๋ณธ ์์ ํ์ ์ ์ด๋ฏธ ๋ถ๋ณ์ด์ผ! ๐
JavaScript์ ์์ ํ์ (primitive types)์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ถ๋ณ์ด์ผ:
let a = 5;
let b = a; // ๊ฐ ๋ณต์ฌ
b = 10; // b๋ง ๋ณ๊ฒฝ๋จ
console.log(a); // 5 (๋ณ๊ฒฝ๋์ง ์์)
console.log(b); // 10
ํ์ง๋ง ๊ฐ์ฒด์ ๋ฐฐ์ด์ ์ฐธ์กฐ ํ์ ์ด๋ผ ํน๋ณํ ์ฒ๋ฆฌ๊ฐ ํ์ํด. ์๋ ๋ฐฉ๋ฒ๋ค์ ํตํด ๋ถ๋ณ์ฑ์ ๊ตฌํํ ์ ์์ด:
1. ์์ ๋ณต์ฌ(Shallow Copy) ๋ฐฉ๋ฒ๋ค ๐
๊ฐ์ฒด ๋ณต์ฌํ๊ธฐ
// 1. ์คํ๋ ๋ ์ฐ์ฐ์ ์ฌ์ฉ (ES6+)
const original = { name: '์ํฌ', age: 28 };
const copy = { ...original, age: 29 }; // ์ ๊ฐ์ฒด ์์ฑ + age ์์ฑ ๋ณ๊ฒฝ
// 2. Object.assign() ์ฌ์ฉ
const anotherCopy = Object.assign({}, original, { age: 30 });
console.log(original); // { name: '์ํฌ', age: 28 }
console.log(copy); // { name: '์ํฌ', age: 29 }
console.log(anotherCopy); // { name: '์ํฌ', age: 30 }
๋ฐฐ์ด ๋ณต์ฌํ๊ธฐ
// 1. ์คํ๋ ๋ ์ฐ์ฐ์ ์ฌ์ฉ
const numbers = [1, 2, 3];
const newNumbers = [...numbers, 4]; // [1, 2, 3, 4]
// 2. concat() ์ฌ์ฉ
const moreNumbers = numbers.concat(5); // [1, 2, 3, 5]
// 3. slice() ์ฌ์ฉ
const numbersCopy = numbers.slice(); // [1, 2, 3]
โ ๏ธ ์ฃผ์: ์์ ๋ณต์ฌ๋ ์ค์ฒฉ๋ ๊ฐ์ฒด๋ ๋ฐฐ์ด์์๋ ๋ถ๋ณ์ฑ์ ๋ณด์ฅํ์ง ์์! 1๋จ๊ณ ๊น์ด์์๋ง ์ ์ฐธ์กฐ๊ฐ ์์ฑ๋๊ณ , ๋ด๋ถ ๊ฐ์ฒด๋ ์ฌ์ ํ ์๋ณธ๊ณผ ๊ฐ์ ์ฐธ์กฐ๋ฅผ ๊ณต์ ํ๊ฒ ๋ผ.
2. ๊น์ ๋ณต์ฌ(Deep Copy) ๊ตฌํํ๊ธฐ ๐
// 1. JSON์ ํ์ฉํ ๊น์ ๋ณต์ฌ (๊ฐ๋จํ์ง๋ง ์ ํ์ )
const original = { user: { name: '๋ฏผ์', hobbies: ['์ถ๊ตฌ', '๊ฒ์'] } };
const deepCopy = JSON.parse(JSON.stringify(original));
// 2. ๊ตฌ์กฐ๋ถํด์ ์คํ๋ ๋๋ฅผ ํ์ฉํ ์๋ ๊น์ ๋ณต์ฌ
const manualDeepCopy = {
...original,
user: {
...original.user,
hobbies: [...original.user.hobbies]
}
};
JSON ๋ฐฉ์์ ํจ์, undefined, Symbol ๋ฑ์ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ ํ๊ณ๊ฐ ์์ด. ์ค๋ฌด์์๋ ๋ณดํต ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, ํ์์ ๋ง๊ฒ ์ง์ ๊น์ ๋ณต์ฌ ํจ์๋ฅผ ๊ตฌํํด.
3. ๋ถ๋ณ ๋ฐ์ดํฐ ๋ค๋ฃจ๊ธฐ ์ํ ํจ์ํ ์ ๊ทผ๋ฒ ๐ง
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ ํ์ฉํ๋ฉด ๋ถ๋ณ์ฑ์ ๋ ์ฐ์ํ๊ฒ ๋ค๋ฃฐ ์ ์์ด:
// ๋ฐฐ์ด์ ๋ถ๋ณ์ ์กฐ์
const numbers = [1, 2, 3, 4, 5];
// โ ๊ฐ๋ณ์ ๋ฐฉ์ (์๋ณธ ๋ณ๊ฒฝ)
// numbers.push(6);
// numbers.pop();
// numbers[0] = 10;
// โ
๋ถ๋ณ์ ๋ฐฉ์ (์ ๋ฐฐ์ด ๋ฐํ)
const added = [...numbers, 6]; // ์ถ๊ฐ
const removed = numbers.slice(0, -1); // ๋ง์ง๋ง ์์ ์ ๊ฑฐ
const replaced = [10, ...numbers.slice(1)]; // ์ฒซ ์์ ๊ต์ฒด
const filtered = numbers.filter(n => n % 2 === 0); // ์ง์๋ง ํํฐ๋ง
const mapped = numbers.map(n => n * 2); // ๋ชจ๋ ์์ 2๋ฐฐ๋ก
๊ฐ์ฒด๋ ๋น์ทํ ํจํด์ผ๋ก ๋ค๋ฃฐ ์ ์์ด:
const user = {
name: '์ง๋ฏผ',
age: 27,
address: {
city: '์์ธ',
district: '๊ฐ๋จ๊ตฌ'
}
};
// ๋ถ๋ณ์ ์ผ๋ก ์ค์ฒฉ ์์ฑ ์
๋ฐ์ดํธํ๊ธฐ
const updatedUser = {
...user,
age: 28, // ๋์ด ์
๋ฐ์ดํธ
address: {
...user.address,
district: '์กํ๊ตฌ' // ๊ตฌ๋ง ๋ณ๊ฒฝ
}
};
์ด๋ฐ ํจํด๋ค์ ์ตํ๋ฉด ๋ณต์กํ ์ค์ฒฉ ๊ตฌ์กฐ์์๋ ๋ถ๋ณ์ฑ์ ์ ์งํ๋ฉด์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ์ ์์ด. ํ์ง๋ง ๊ตฌ์กฐ๊ฐ ๊น์ด์ง์๋ก ์ฝ๋๊ฐ ๋ณต์กํด์ง๋ ๋จ์ ์ด ์์ง. ์ด๋ด ๋ ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ์ ๋ฌธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋์์ ๋ฐ์ ์ ์์ด. ๋ค์ ์น์ ์์ ์ดํด๋ณด์! ๐
4. ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋? ๐ณ
์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ(Persistent Data Structures)๋ ๋ถ๋ณ์ฑ์ ํจ์จ์ ์ผ๋ก ๊ตฌํํ๊ธฐ ์ํ ํน๋ณํ ์๋ฃ๊ตฌ์กฐ์ผ. "์์์ "์ด๋ผ๋ ๋ง์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์ด์ ๋ฒ์ ์ด ํญ์ ๋ณด์กด๋๋ค๋ ์๋ฏธ์ผ. ๐ฐ๏ธ
์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ํต์ฌ ๊ฐ๋
์ผ๋ฐ์ ์ธ ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌํ์ ๋ณ๊ฒฝ์ด ํ์ํ ๋๋ง๋ค ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํด์ผ ํด์ ๋ฉ๋ชจ๋ฆฌ์ ์ฑ๋ฅ ์ธก๋ฉด์์ ๋นํจ์จ์ ์ผ ์ ์์ด. ํ์ง๋ง ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ๊ตฌ์กฐ ๊ณต์ (Structural Sharing)๋ผ๋ ๊ธฐ๋ฒ์ ์ฌ์ฉํด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด.
๊ตฌ์กฐ ๊ณต์ ๋ ์ ๋ฒ์ ์ ๋ง๋ค ๋ ๋ณ๊ฒฝ๋์ง ์์ ๋ถ๋ถ์ ์๋ณธ๊ณผ ๊ณต์ ํ๊ณ , ๋ณ๊ฒฝ๋ ๋ถ๋ถ๋ง ์๋ก ์์ฑํ๋ ๋ฐฉ์์ด์ผ. ์ด๋ ๊ฒ ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ํฌ๊ฒ ์ค์ด๋ฉด์๋ ๋ถ๋ณ์ฑ์ ์ด์ ์ ๋๋ฆด ์ ์์ง!
ํธ๋ผ์ด(Trie)์ ๊ฐ์ ์์ ์๋ฃ๊ตฌ์กฐ ์ดํดํ๊ธฐ ๐ฒ
์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ํ์ ์ธ ์๋ก๋ ํธ๋ผ์ด(Trie), ํนํ ๊ทธ ๋ณํ์ธ HAMT(Hash Array Mapped Trie)๊ฐ ์์ด. ์ด ๊ตฌ์กฐ๋ค์ Immutable.js๋ Immer ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ธฐ๋ฐ์ด ๋๋ ๊ฐ๋ ์ด์ผ.
์ ๊ทธ๋ฆผ์์ ๋ณผ ์ ์๋ฏ์ด, ์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ๋ณ๊ฒฝ๋ ๊ฒฝ๋ก์ ์๋ ๋ ธ๋๋ค๋ง ์๋ก ์์ฑํ๊ณ , ๋๋จธ์ง๋ ๊ธฐ์กด ๊ตฌ์กฐ๋ฅผ ์ฌ์ฌ์ฉํด. ์ด๋ฐ ๋ฐฉ์์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ๊ณผ ๋ถ๋ณ์ฑ์ ๋์์ ๋ฌ์ฑํ ์ ์์ด.
์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์ฅ์ ๐
- ํจ์จ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ: ๋ณ๊ฒฝ๋ ๋ถ๋ถ๋ง ์๋ก ์์ฑํ๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ต์ํ๋ผ.
- ๋น ๋ฅธ ๋น๊ต ์ฐ์ฐ: ์ฐธ์กฐ ๋๋ฑ์ฑ ๊ฒ์ฌ๋ง์ผ๋ก ๋ณ๊ฒฝ ์ฌ๋ถ๋ฅผ ๋น ๋ฅด๊ฒ ํ์ธํ ์ ์์ด.
- ์๊ฐ ์ฌํ(Time Travel): ๋ชจ๋ ์ด์ ๋ฒ์ ์ด ๋ณด์กด๋๋ฏ๋ก ์ํ ํ์คํ ๋ฆฌ๋ฅผ ์ฝ๊ฒ ๊ด๋ฆฌํ ์ ์์ด.
- ํธ๋์ญ์ ์์ ์ฑ: ์์ ์ค๊ฐ์ ์คํจํด๋ ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ด ์ ์ง๋ผ.
- ๋์์ฑ ์ง์: ์ฌ๋ฌ ์์ ์ด ๋์์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ฒ ๋ค๋ฃฐ ์ ์์ด.
์ค์ ์: Immutable.js์ List ์ฌ์ฉ ์์
import { List } from 'immutable';
// ๋ถ๋ณ ๋ฆฌ์คํธ ์์ฑ
const list1 = List([1, 2, 3, 4]);
// ์ ๋ฆฌ์คํธ ์์ฑ (์๋ณธ์ ๋ณ๊ฒฝ๋์ง ์์)
const list2 = list1.push(5);
const list3 = list1.set(0, 10);
console.log(list1.toArray()); // [1, 2, 3, 4] - ์๋ณธ ์ ์ง
console.log(list2.toArray()); // [1, 2, 3, 4, 5]
console.log(list3.toArray()); // [10, 2, 3, 4]
// ํจ์จ์ ์ธ ๋น๊ต
console.log(list1 === list2); // false - ๋ค๋ฅธ ๊ฐ์ฒด
console.log(list1.equals(list2)); // false - ๋ด์ฉ์ด ๋ค๋ฆ
์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ์ฌ๋ฅ๋ท์์ ํ๋ก๊ทธ๋๋ฐ ๊ด๋ จ ์ฌ๋ฅ์ ๊ณต์ ํ๋ ๊ฐ๋ฐ์๋ค ์ฌ์ด์์๋ ์ธ๊ธฐ ์๋ ์ฃผ์ ์ผ. ํนํ ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ๋ ์ํ ๊ด๋ฆฌ๋ฅผ ํจ์จ์ ์ผ๋ก ํ ์ ์๊ฒ ํด์ฃผ๊ฑฐ๋ . ๋ค์ ์น์ ์์๋ ์ด๋ฐ ๊ฐ๋ ์ ์ค์ ๋ก ๊ตฌํํ ์ธ๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ดํด๋ณผ๊ฒ! ๐
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ