외부 상태에 객체가 함수에서 매개변수로 받거나 다른 식으로 객체를 사용하게 된다. 만약 함수에서 객체를 사용해서 변하게 된다면 객체 값은 변하게 되면서 훼손하게 된다. 그 이유는 객체는 참조 값이 복사되어 전달 되기 때문에 같은 메모리 주소 값을 갖게 된다. 그러기 때문에 객체가 변하게 된다.
자바스크립트는 객체의 변경을 제한하거나 막는 메서드를 제공합니다. 이들은 객체의 변경 가능성을 단계적으로 제한합니다:
객체에 새로운 프로퍼티 추가를 금지합니다. 기존 프로퍼티의 수정과 삭제는 여전히 가능합니다.
const obj = { name: "John" };
Object.preventExtensions(obj);
obj.age = 30; // 무시됨
delete obj.name; // 가능
console.log(obj); // { name: "John" }
객체를 밀봉하여 프로퍼티 추가와 삭제를 금지하며, 기존 프로퍼티의 속성 재정의도 불가능하게 만듭니다. 단, 값 수정은 가능합니다.
const obj = { name: "John" };
Object.seal(obj);
obj.name = "Jane"; // 가능
delete obj.name; // 무시됨
console.log(obj); // { name: "Jane" }
객체를 동결하여 프로퍼티 추가, 삭제, 속성 재정의뿐만 아니라 값 수정도 금지합니다.
const obj = { name: "John" };
Object.freeze(obj);
obj.name = "Jane"; // 무시됨
delete obj.name; // 무시됨
console.log(obj); // { name: "John" }
이 메서드들은 얕은 변경 방지만 가능하므로 중첩된 객체까지 보호하려면 재귀적으로 적용해야 합니다
객체를 복사하여 새로운 객체를 생성하고, 원본을 변경하지 않는 방식으로 처리합니다. 예를 들어, 스프레드 연산자나 Object.assign()을 사용하여 복사본을 생성합니다:
const original = { name: "John", details: { age: 30 } };
const copy = { ...original, name: "Jane" }; // 얕은 복사
console.log(original); // { name: "John", details: { age: 30 } }
console.log(copy); // { name: "Jane", details: { age: 30 } }
깊은 복사가 필요한 경우 라이브러리(예: Lodash)나 JSON 메서드를 사용할 수 있습니다.
클로저를 사용하여 외부 상태에 직접 접근하지 못하도록 캡슐화할 수 있습니다. 이를 통해 의도치 않은 상태 변경을 방지할 수 있습니다:
function createImmutableObject(initialState) {
let state = { ...initialState }; // 초기 상태 복사
return {
getState() {
return { ...state }; // 상태 복사본 반환
},
updateState(updates) {
state = { ...state, ...updates }; // 상태 갱신
},
};
}
const objManager = createImmutableObject({ name: "John" });
console.log(objManager.getState()); // { name: "John" }
objManager.updateState({ age: 30 });
console.log(objManager.getState()); // { name: "John", age: 30 }
이 방법은 외부에서 내부 상태를 직접 수정하지 못하도록 보호합니다
결론
위 방법들 중 상황에 따라 적절한 방식을 선택하면 됩니다
- 단순히 변경을 막으려면 Object.freeze() 사용.
- 동적 업데이트가 필요하다면 클로저와 불변 객체 패턴 활용.