[JavaScript] mutable and immutable object
mutable의 사전적인 의미는 '변화 가능한'이다. 프로그래밍 쪽에 있는 사람이라면 mutable, immutable이라는 말을 가끔 듣는다. 이번 기회에 나도 정리해 보려고 한다.
자바스크립트 기준으로 const 키워드로 정의되는 변수들은 immutable, 즉 '변경 불가능한' 변수다. 그리고 let 키워드로 정의되는 변수들이 mutable, 즉 '변경 가능한' 변수들이다. O.K. 어렵지 않다.
· immutable: 값의 변경을 허락하지 않는 변수들이다. 예, const 키워드로 선언된 변수들.
· mutable: 값의 변경을 허용하는 변수들이다. 예, let 키워드로 선언된 변수들.
이제 이야기를 객체(object)로 조금 확장시켜보자. 아래와 같이 자바스크립트 객체를 const 키워드를 이용해서 선언하고 값을 할당해보자.
const imObj = {};
imObj["value"] = 5;
console.log(imObj);
결과를 살펴보면, 값이 할당된다. 여기서 약간의 의문이 생긴다. immutable 이라며?
{value: 5}
객체가 immutable 하다는 의미는 객체의 reference가 immutable하다는 뜻이다. 즉, imObj 변수는 객체의 메모리 주소를 저장하고 있는 것이지 객체 자체를 저장하고 있는 것은 아니다. 따라서 imObj 변수가 가리키는 객체의 내용이 변해도, 객체의 메모리 주소는 변하지 않고 이를 불변(immutable)이라고 보는 것이다.
· 객체가 immutable 하다: 어떤 객체가 저장되어 있는 메모리 주소(=reference)가 변하지 않는다는 뜻이다. 하지만 객체의 내용은 변경될 수 있다.
따라서 객체의 mutability를 가지고 객체의 내용이 수정되었는지 아닌지 알 수는 없다. 이 점이 변수와는 다른 점이다. 일반적인 변수가 값(value)을 저장하고 있는데 반해, 객체를 저장하는 변수는 객체의 위치에 해당하는 메모리 주소(reference)를 저장하고 있기 때문이다. 즉, 객체의 내용이 바뀌어도 메모리 주소는 그대로이기 때문에 객체의 내용 수정 여부를 변수의 값으로는 알 수 없다.
immutable한 객체가 문제가 되는 경우는 객체를 나타내는 변수의 값으로 객체 내용의 변화를 감지할 수 없다는데서 온다. 예를 들어 리액트(React)를 사용하는 경우 객체의 내용을 변경해도 리액트 엔진은 내용 변화를 감지할 수 없다. 그러면 객체 내용이 바뀌었는데도 불구하고 리액트는 내용이 변경된 사실을 알지 못하고 re-rendering과 같은 이어지는 작업을 수행하지 않는다. 따라서 객체 내용이 변경되면 일반적으로 객체를 새로 할당하고 변경된 값을 새 객체에 써주는 것이 원칙이다. 아래 코드를 보자.
const newObj = Object.assign({}, imObj);
newObj["value"] = 6;
console.log(newObj); // {value: 6}
console.log(newObj === imObj); // false
imObj 객체의 내용을 변경할 때 새 객체 newObj를 할당하고 값을 변경해주었다. 이와 같이 새 객체를 할당한 후 값을 업데이트하는 것을 immutable update라고 한다.
ES6(ECMA Script 2015) 부터는 아래와 같이 간단하게 전개 구문(spread operator)을 이용할 수 있다.
const newObj2 = {...newObj, "value": 6};
console.log(newObj2); // {value: 6}
console.log(newObj2 === imObj); // false
결론 1:
객체의 메모리에서의 주소를 저장하는 변수가 immutable한 것이다. 객체 내용은 변경될 수 있다. 즉, 객체 내용은 mutable하다.
결론 2:
객체의 값을 변경할 때는 새 객체를 할당하고 값을 변경해 준다. 이전 객체는 가비지 콜렉션(garbage collection)되어 해제되므로 걱정할 필요는 없다.
■