JAN's History
불변 객체(Immutable Object)란? 본문
이번에는 객체의 변경을 방지하고, 어떻게 객체를 불변(Immutable)하게 만들 수 있는지에 대해 알아보겠습니다. JavaScript에서 객체는 기본적으로 가변(Mutable)합니다. 하지만 Object 메서드를 사용해 객체의 수정, 삭제, 추가를 제한하여 불변 객체를 만들 수 있습니다. 자, 이제 예제와 함께 불변 객체에 대해 하나씩 살펴볼까요?🙌🏼
🎯 1. Object.isExtensible()와 Object.preventExtensions()
- Object.isExtensible(object): 객체에 속성을 추가할 수 있는지 여부를 확인합니다. 기본적으로 모든 객체는 확장 가능합니다.
- Object.preventExtensions(object): 객체에 새로운 속성을 추가하지 못하도록 막습니다. 하지만 이미 존재하는 속성의 삭제나 수정은 가능합니다.
📝 예시: 확장 가능 여부 확인 및 확장 방지
- Object.preventExtensions()를 사용하면 객체에 새로운 속성을 추가할 수 없게 됩니다. 하지만 기존 속성의 수정과 삭제는 여전히 가능합니다.
const pome = {
type: '포메라니안',
size: 'small',
year: 2021,
get age() {
return new Date().getFullYear() - this.year;
},
set age(age) {
this.year = new Date().getFullYear() - age;
}
};
console.log(Object.isExtensible(pome)); // true
pome['color'] = 'white'; // 새로운 속성 추가
console.log(pome); // { type: '포메라니안', size: 'small', year: 2021, color: 'white', ... }
Object.preventExtensions(pome); // 확장 방지
console.log(Object.isExtensible(pome)); // false
pome['cute'] = 'very cute'; // 새로운 속성 추가 시도
console.log(pome); // 에러는 없지만 'cute' 프로퍼티 생성되지 않음
delete pome['color']; // 기존 속성 삭제는 가능
console.log(pome); // { type: '포메라니안', size: 'small', year: 2021, ... }
🎯 2. Object.seal()와 Object.isSealed()
- Object.isSealed(object): 객체가 봉인(?)되었는지 여부를 확인합니다. 기본값은 false입니다.
- Object.seal(object): 객체를 봉인하여 속성의 추가 및 삭제를 막습니다. 단, 기존 속성의 값은 변경할 수 있습니다.
📝 예시: 객체 봉인 및 확인
- Object.seal()을 사용하면 객체에 속성을 추가하거나 삭제할 수 없게 됩니다. 하지만 기존 속성의 값을 변경할 수 있습니다.
const pome2 = {
type: '포메라니안',
size: 'small',
year: 2021,
get age() {
return new Date().getFullYear() - this.year;
},
set age(age) {
this.year = new Date().getFullYear() - age;
}
};
console.log(Object.isSealed(pome2)); // false
Object.seal(pome2); // 객체 봉인
console.log(Object.isSealed(pome2)); // true
pome2['cute'] = 'very cute'; // 새로운 속성 추가 시도
console.log(pome2); // 에러는 없지만 'cute' 프로퍼티 생성되지 않음
delete pome2['type']; // 기존 속성 삭제 시도
console.log(pome2); // 삭제 불가
🎯 3. Object.freeze()와 Object.isFrozen()
- `Object.isFrozen(object): 객체가 동결되었는지 여부를 확인합니다.
- `Object.freeze(object): 객체를 동결하여 속성의 추가, 삭제, 수정 모두를 불가능하게 만듭니다.
📝 예시: 객체 동결 및 확인
- Object.freeze()를 사용하면 객체를 동결하여 속성의 추가, 삭제, 수정이 모두 불가능해집니다. 이는 객체를 아예 불변하게 만들어 안전하게 사용할 수 있도록 하는 방법입니다!
const pome3 = {
type: '포메라니안',
size: 'small',
year: 2021,
get age() {
return new Date().getFullYear() - this.year;
},
set age(age) {
this.year = new Date().getFullYear() - age;
}
};
Object.freeze(pome3); // 객체 동결
console.log(Object.isFrozen(pome3)); // true
pome3['cute'] = 'very cute'; // 새로운 속성 추가 시도
console.log(pome3); // 에러는 없지만 'cute' 프로퍼티 생성되지 않음
delete pome3['type']; // 기존 속성 삭제 시도
console.log(pome3); // 삭제 불가
// Object.defineProperties(pome3, 'name', { value: '말티즈' }); -> 에러 발생
console.log(Object.getOwnPropertyDescriptor(pome3, 'type')); // writable도 false임
🎯 4. 중첩 객체의 동결
Object.freeze()는 객체의 중첩 객체에는 영향을 주지 않습니다. 즉, 객체의 프로퍼티가 또 다른 객체일 경우 그 내부의 속성은 여전히 변경 가능합니다.
📝 예시: 중첩 객체의 동결
- 내부 객체까지 동결하고 싶다면 내부 객체를 각각 Object.freeze()로 동결해야 합니다.
const pome5 = {
type: '포메라니안',
size: 'small',
year: 2021,
maltese: {
type: '말티즈',
year: 2019,
},
};
Object.freeze(pome5); // 객체 동결
console.log(Object.isFrozen(pome5)); // true
console.log(Object.isFrozen(pome5['maltese'])); // false (내부 객체는 동결되지 않음)
pome5.maltese.type = '허스키';
console.log(pome5.maltese); // { type: '허스키', year: 2019 }
⭐ 중요: 불변 객체 생성 시 주의사항
- Object.preventExtensions()는 속성의 추가를 막지만, 속성의 수정과 삭제는 가능합니다.
- Object.seal()은 속성의 추가와 삭제를 막지만, 속성의 값은 수정할 수 있습니다.
- Object.freeze()는 속성의 추가, 삭제, 수정 모두를 막아 객체를 완전한 불변 상태로 만듭니다.
- 중첩된 객체를 별도로 동결하지 않으면 내부 값이 변경될 수 있습니다.
🛠 실무적인 팁
- 불변객체는 데이터의 무결성을 보장하고, 예기치 않은 버그를 방지하는 데 유용합니다.
- 중첩된 객체를 완전히 동결하려면 재귀적으로 모든 내부 객체에 Object.freeze()를 적용해야 합니다.
- 불변 객체의 사용을 통해 상태 관리가 필요한 라이브버리(예: React, Redux)에서 더욱 안전하게 객체를 다룰 수 있습니다.
📌 결론
불변 객체를 만드는 방법에는 Object.preventExtensions(), Object.seal(), Object.freeze()가 있으며, 각각 객체의 수정, 추가, 삭제를 제한하는 정도가 다릅니다. 불변 객체를 적절하게 활용하여 코드의 안정성과 유지보수성을 높일 수 있답니다. 😁
이번에는 불변 객체에 대해 자세히 알아보았습니다! 객체를 안전하게 관리하고 싶다면, 상황에 맞는 불변화 방식을 선택하는 것이 중요하니까 프로젝트에 맞는 선택을 하시는 것이 좋겠죠? ㅎㅎ
'Javascript' 카테고리의 다른 글
프로토타입 체인과 객체 상속의 이해 (1) | 2024.10.26 |
---|---|
생성자 함수와 new.target을 이해해보자!_! (0) | 2024.10.23 |
프로퍼티 어트리뷰트란(Property Attribute)? (0) | 2024.10.19 |
화살표 함수 vs 일반 함수: this를 더 쉽게 이해하기! 🚀 (2) | 2024.10.17 |
상속과 super 키워드 그리고 오버라이딩까지 쉽게 알아보기 🐶 (0) | 2024.10.16 |