JavaScript에서 객체는 참조 형태로 값을 주고 받는데, 하나의 객체가 생성되고 그 값을 다른 객체들이 참조하고 있다면 의도하지 않은 값의 변형으로 사이드이펙트가 발생하는 경우가 있을 수 있습니다. 보통 이런 경우 래퍼런스를 참조한 다른 객체를 변경하기 때문입니다. 이와 같은 문제를 방지하기 위해서는 불변의(Immutable) 객체를 만들거나 객체 복사를 통해 새로운 객체를 생성한 후 변경하는 것이 안전합니다.
이를 더 자세하게 살펴보기 위해서는 JavaScript의 원시값과 참조값의 차이점을 알아야합니다.
아래 간단한 예시가 있습니다.
/* ex1) */
let numA = 10;
let numB = numA;
numA = 20;
console.log(numA,numB); // 20 10
/* ex2) */
let arrA = [1,2,3];
let arrB = arrA;
arrA.push(4);
console.log(arrA,arrB); // [ 1, 2, 3, 4 ] [ 1, 2, 3, 4 ]
ex1) 코드는 변수 numA에 10을 할당하고, 변수 numB는 numA가 가리키는 주소를 가리킵니다. 이때 a를 20으로 변경하면 numA와 numB 모두 20이 아닌 numA만 20으로 바뀌게 됩니다.
ex2) 코드는 변수 arrA에 값을 할당하고, 변수 arrB는 arrA가 가리키는 주소를 가리킵니다.
이때 arrA에 값을 변경하면 arrA, arrB 모두 값이 바뀌게 됩니다.
원시값, 원시 타입 : string, number, boolean, null, undefined, symbol
원시값은 변경 불가능한 값입니다. 한 번 생성된 원시값은 읽기 전용으로 그 값을 변경할 수 없습니다.
원시값은 변수에 할당하면 변수에는 실제 값이 저장됩니다.
변경 불가능한 값이란 재할당을 못한다는 것이 아닌 재할당을 하면 새로운 메모리 공간을 확보하여 값을 넣어준다는 것을 의미합니다.
참조값, 객체 타입 : Array, Object, Function
원시타입은 값이 복사되어 전달된다고 했습니다. 이것을 값에 의한 전달이라고 합니다.
아래와 같이 copyNum에 numA를 할당하면 값 1이 복사되어 전달되고, numA와 copyNum의 값 1은 다른 메모리 공간에 저장된 값입니다. 따라서 numA와 copyNum은 별개의 메모리에 할당되어 있기 때문에 numA 값을 변경해도 copyNum에는 영향을 주지 않습니다.
let numA = 1;
let copyNum = numA;
console.log(numA === copyNum); // true
numA = 10;
console.log(numA === copyNum); // false
참조타입은 실제 값이 아닌 참조값이 전달된다고 했습니다. 즉 참조값이 저장된 메모리 주소가 전될되는데 이것을 참조에 의한 전달이라고합니다.
아래와 같이 copyNum에 numA를 복사하면 {value:1} 객체가 저장된 메모리의 주소를 같이 공유하는 상태가 되기때문에 numA의 value를 변경하면 copyNum의 값도 변하게 됩니다.
let numA = {
value : 1
};
let copyNum = numA;
console.log(numA.value === copyNum.value); // true
numA.value = 10;
console.log(numA === copyNum); // true
JavaScript 라이브러리의 하나로서 사용자 인터페이스를 만들기 위해 사용하는 React에서도 불변성이 중요합니다. 그 이유는 React의 브라우저 렌더링 과정과 관련이 있는데, 간략하게 요약하자면 React는 가상돔을 사용하여 바뀐 부분을 찾는 과정 Diffing, 바뀐 부분만 실제 돔에 적용시키는 Reconciliation을 통해 렌더링을 합니다. 이때 Diffing과정에서 이전 객체와 현재 객체를 얕은 비교를 통해 변화를 판단하기 때문에 불변성의 유지가 중요합니다.
얕은 비교란 원시타입은 값이 동일한지만 비교하고, 참조타입은 값이 아닌 래퍼런스(참조 위치, 주소)를 비교하는 것을 말합니다.
따라서 참조타입 state를 직접 변경하게 되면 값은 바뀌지만 참조값이 바뀌지 않아 렌더링이 일어나지 않는 현상이 발생합니다.
그렇다면 불변성을 어떻게 지킬까요 ?
등과 같은 여러가지 방법이 있습니다. 예시까지 첨부하면 글이 너무 길어질 것 같아, 간략한 예시를 확인하고 싶으신 분들은 제가 이전 티스토리에 정리해둔 글을 참고해주시면 감사하겠습니다 :)