๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Language/Javascript

[Javascript]์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Immutable Object ์™„๋ฒฝ ๊ฐ€์ด๋“œ: ์„ฑ๋Šฅ ํ–ฅ์ƒ๊ณผ ๋ถˆ๋ณ€์„ฑ ์œ ์ง€ ๋น„๋ฒ•

by YJ Dev 2024. 7. 1.
728x90
๋ฐ˜์‘ํ˜•
SMALL

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ Immutable Object(๋ถˆ๋ณ€ ๊ฐ์ฒด)๋Š” ์„ฑ๋Šฅ ํ–ฅ์ƒ๊ณผ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ ์ž‘์„ฑ์„ ์œ„ํ•ด ์ค‘์š”ํ•œ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. ์ด ๊ธ€์—์„œ๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด์˜ ์ •์˜์™€ ํ•„์š”์„ฑ, ์ƒ์„ฑ ๋ฐฉ๋ฒ• ๋“ฑ์„ ์ƒ์„ธํžˆ ๋‹ค๋ฃน๋‹ˆ๋‹ค.
Object.freeze(), Object.seal(), Object.preventExtensions() ๋“ฑ์˜ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‹ค์ œ ์˜ˆ์ œ์™€ ํ•จ๊ป˜ ์•Œ์•„๋ณด์„ธ์š”. ์ด ๊ธ€์„ ํ†ตํ•ด ๋ถˆ๋ณ€ ๊ฐ์ฒด์˜ ์žฅ์ ์„ ์ดํ•ดํ•˜๊ณ , ์ฝ”๋“œ์˜ ์•ˆ์ •์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Immutable Object


์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด์— ๊ด€ํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”๐Ÿ˜

 

[Javascript]์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด ์™„๋ฒฝ ๊ฐ€์ด๋“œ: ์„ ์–ธ, ์‚ฌ์šฉ๋ฒ•, ๋ณต์‚ฌ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๊ฐ์ฒด(Object)๋Š” ๋งค์šฐ ์ค‘์š”ํ•œ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. ๊ฐ์ฒด๋Š” ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ ๊ตฌ์กฐ๋กœ ๋ฌถ์–ด ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค. ์ด ๊ธ€์—์„œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ๊ฐœ๋…๋ถ€ํ„ฐ ๊ณ ๊ธ‰ ํ™œ

creativevista.tistory.com


01. Immutable Object๋ž€ ๋ฌด์—‡์ธ๊ฐ€?๐Ÿค”

Immutable Object(๋ถˆ๋ณ€ ๊ฐ์ฒด)๋Š” ์ƒ์„ฑ ํ›„์— ๊ทธ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฐ์ฒด๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ๋ณต์žกํ•œ ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•„์ง€๊ณ , ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋ถ€์ž‘์šฉ(side effects)์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


02. ์™œ Immutable Object๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”๊ฐ€?๐Ÿ’ก

์„ฑ๋Šฅ ํ–ฅ์ƒ: ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ๋ณต์‚ฌ๋ณธ์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์‹œ์— ์„ฑ๋Šฅ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์ ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ธก ๊ฐ€๋Šฅ์„ฑ: ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ๊ทธ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์ถ”์ ํ•˜๊ธฐ๊ฐ€ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋””๋ฒ„๊น…๊ณผ ์œ ์ง€ ๋ณด์ˆ˜๋ฅผ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

๋””๋ฒ„๊น… ์šฉ์ด์„ฑ: ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ์ƒํƒœ ๋ณ€ํ™”๋กœ ์ธํ•œ ๋ฒ„๊ทธ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


03. Immutable Object ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•๐Ÿš€

Object.freeze() ์‚ฌ์šฉํ•˜๊ธฐ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋‚ด์žฅ ํ•จ์ˆ˜์ธ Object.freeze()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด๋ฅผ ๋™๊ฒฐ(freeze)์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋™๊ฒฐ๋œ ๊ฐ์ฒด๋Š” ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

const student = {
  name: "Alice",
  year: 2002,

  get age() {
    return new Date().getFullYear() - this.year;
  },

  set age(age) {
    this.year = new Date().getFullYear() - age;
  },
};

Object.freeze(student);

student.name = "Bob"; // ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Œ
console.log(student.name); // "Alice"

Immutable.js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉ

Facebook์—์„œ ๊ฐœ๋ฐœํ•œ Immutable.js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋ถˆ๋ณ€ ๋ฐ์ดํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค. Immutable.js๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋”์šฑ ๊ฐ•๋ ฅํ•œ ๋ถˆ๋ณ€์„ฑ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const { Map } = require('immutable');

let map1 = Map({ name: "John" });
let map2 = map1.set("name", "Doe");

console.log(map1.get("name")); // "John"
console.log(map2.get("name")); // "Doe"

04. ๋ถˆ๋ณ€ ๊ฐ์ฒด์™€ ๊ฐ€๋ณ€ ๊ฐ์ฒด์˜ ์ฐจ์ด์ ๐Ÿ”„

๋ถˆ๋ณ€ ๊ฐ์ฒด์˜ ํŠน์ง•

  • ์ƒ์„ฑ ์ดํ›„ ์ƒํƒœ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€
  • ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ๋Š” ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๊ฐ์ฒด ์ƒ์„ฑ

๊ฐ€๋ณ€ ๊ฐ์ฒด์˜ ๋ฌธ์ œ์ 

  • ์ƒํƒœ ๋ณ€ํ™” ์ถ”์  ์–ด๋ ค์›€
  • ๋””๋ฒ„๊น… ์‹œ ํ˜ผ๋ž€ ๋ฐœ์ƒ ๊ฐ€๋Šฅ
  • ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋ฉด ์˜๋„์น˜ ์•Š์€ ๋ถ€์ž‘์šฉ ๋ฐœ์ƒ ๊ฐ€๋Šฅ

05. ์‹ค์ œ ์˜ˆ์ œ ์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๋Š” Immutable Object๐Ÿ’ป

JavaScript์˜ ๊ฐ์ฒด ์†์„ฑ ์„ค์ •์—์„œ Extensible, Seal, Freeze๋Š” ๊ฐ์ฒด์˜ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์„ ์ œ์–ดํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋“ค์€ ๊ฐ๊ฐ ๋‹ค๋ฅธ ์ˆ˜์ค€์˜ ์ œํ•œ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Extensible ์†์„ฑ

 

๊ฐ์ฒด์˜ ํ™•์žฅ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๊ฐ์ฒด๋Š” ํ™•์žฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋Š” ์ƒˆ๋กœ์šด ์†์„ฑ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Object.isExtensible(obj): ๊ฐ์ฒด๊ฐ€ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • Object.preventExtensions(obj): ๊ฐ์ฒด๋ฅผ ํ™•์žฅ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ์†์„ฑ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†์ง€๋งŒ ๊ธฐ์กด ์†์„ฑ์€ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
let obj = { a: 1 };
console.log(Object.isExtensible(obj)); // true

Object.preventExtensions(obj);
console.log(Object.isExtensible(obj)); // false

obj.b = 2; // ์ถ”๊ฐ€ ๋ถˆ๊ฐ€๋Šฅ
console.log(obj.b); // undefined

Seal ์†์„ฑ

๊ฐ์ฒด๋ฅผ ๋ฐ€๋ด‰ํ•˜๋ฉด ์ƒˆ๋กœ์šด ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด ์†์„ฑ์„ ์‚ญ์ œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ธฐ์กด ์†์„ฑ์˜ ๊ฐ’์€ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Object.isSealed(obj): ๊ฐ์ฒด๊ฐ€ ๋ฐ€๋ด‰๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • Object.seal(obj): ๊ฐ์ฒด๋ฅผ ๋ฐ€๋ด‰ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์ฒด์˜ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ์ˆ˜ ์—†๊ฒŒ ๋˜๋ฉฐ, ๊ฐ์ฒด๋Š” ์ž๋™์œผ๋กœ ํ™•์žฅ ๋ถˆ๊ฐ€๋Šฅ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
let obj = { a: 1 };
console.log(Object.isSealed(obj)); // false

Object.seal(obj);
console.log(Object.isSealed(obj)); // true

obj.b = 2; // ์ถ”๊ฐ€ ๋ถˆ๊ฐ€๋Šฅ
delete obj.a; // ์‚ญ์ œ ๋ถˆ๊ฐ€๋Šฅ
console.log(obj); // { a: 1 }

obj.a = 3; // ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
console.log(obj); // { a: 3 }

Freeze ์†์„ฑ

๊ฐ์ฒด๋ฅผ ๋™๊ฒฐํ•˜๋ฉด ์ƒˆ๋กœ์šด ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด ์†์„ฑ์„ ์‚ญ์ œํ•  ์ˆ˜ ์—†๊ณ , ์†์„ฑ์˜ ๊ฐ’๋„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

  • Object.isFrozen(obj): ๊ฐ์ฒด๊ฐ€ ๋™๊ฒฐ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • Object.freeze(obj): ๊ฐ์ฒด๋ฅผ ๋™๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์ฒด๋Š” ์ž๋™์œผ๋กœ ๋ฐ€๋ด‰ ์ƒํƒœ๊ฐ€ ๋˜๋ฉฐ, ์†์„ฑ ๊ฐ’๋„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
let obj = { a: 1 };
console.log(Object.isFrozen(obj)); // false

Object.freeze(obj);
console.log(Object.isFrozen(obj)); // true

obj.b = 2; // ์ถ”๊ฐ€ ๋ถˆ๊ฐ€๋Šฅ
delete obj.a; // ์‚ญ์ œ ๋ถˆ๊ฐ€๋Šฅ
obj.a = 3; // ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ
console.log(obj); // { a: 1 }

ํ•˜์œ„ ๊ฐ์ฒด ์ฒ˜๋ฆฌ

๊ฐ์ฒด์˜ ํ•˜์œ„ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ๋Š” seal์ด๋‚˜ freeze ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด๋„ ์ž๋™์œผ๋กœ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์œ„ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ๋„ ๋™์ผํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

let obj = {
  a: 1,
  b: {
    c: 2
  }
};

Object.freeze(obj);
console.log(Object.isFrozen(obj)); // true
console.log(Object.isFrozen(obj.b)); // false

Object.freeze(obj.b);
console.log(Object.isFrozen(obj.b)); // true

์ด์™€ ๊ฐ™์ด, ๊ฐ์ฒด์˜ ํ™•์žฅ ๊ฐ€๋Šฅ์„ฑ, ๋ฐ€๋ด‰ ๋ฐ ๋™๊ฒฐ ์ƒํƒœ๋Š” ํ•ด๋‹น ๊ฐ์ฒด์˜ ์ง์ ‘์ ์ธ ์†์„ฑ์—๋งŒ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋ฉฐ, ํ•˜์œ„ ๊ฐ์ฒด์— ๋Œ€ํ•ด์„œ๋Š” ๋ณ„๋„๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


06. ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ: ๋ถˆ๋ณ€ ๊ฐ์ฒด vs ๊ฐ€๋ณ€ ๊ฐ์ฒดโš–๏ธ

์„ฑ๋Šฅ ๋น„๊ต

๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ์ƒํƒœ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฏ€๋กœ, ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์—์„œ๋Š” ์„ฑ๋Šฅ ์ €ํ•˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋Ÿฌํ•œ ์„ฑ๋Šฅ ์ €ํ•˜๋Š” ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ๋นˆ๋„๊ฐ€ ๋‚ฎ์€ ๊ฒฝ์šฐ์—๋Š” ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜์ค€์ž…๋‹ˆ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋น„๊ต

 ๊ฐ€๋ณ€ ๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋ฅผ ๊ณต์œ ํ•˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ ์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ๋ณ€๊ฒฝ ์‹œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ตœ์‹  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์€ ์ด๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋‹ค์–‘ํ•œ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

728x90
๋ฐ˜์‘ํ˜•