Iriton's log
0. JavaScript Immutability 본문
스터디 참고 자료
https://youtube.com/playlist?list=PLuHgQVnccGMBxNK38TqfBWk-QpEI7UkY8&si=l0cktZbzZIUvhKWS
불변성이란 데이터 원본이 훼손되는 것을 막는 것이다.
데이터를 불변하게 다루면 데이터들 간의 간섭으로 인한 버그의 가능성을 획기적으로 낮출 수 있다.
또, 데이터가 변경되었는지 여부를 쉽게 체크할 수 있으며 특히 CRUD(Create, Read, Update, Delete) 작업 시, 불변성을 보장하는 것이 매우 중요하다.
이름에 대한 불변함
const를 사용하여 이름을 불변하게 만든다.
const를 사용하게 되면 선언한 변수를 수정할 수 없게 되며, 수정을 시도하는 경우 error를 발생시킨다. (var을 사용할 경우 error가 발생하지 않고 시스템 크기에 따라 크고 작은 버그들이 발생하여 시스템이 잘 작동하지 않게 될 수 있다.)
변수 할당 방식 비교
JavaScript는 값이 바뀌지 않는 원시 데이터 타입과 값이 바뀔 수 있는 객체 타입을 다르게 취급한다.
- 원시 데이터 타입(Primitive): Number, String, Boolean, Null, Undefined, Symbol…
- 객체 타입(Object): Object, Array, Funcfion…
원시 데이터 타입의 경우 다른 변수여도 같은 값을 가진다면 같은 메모리 위치를 가리키기에 비교 연산 === 를 했을 때 true가 나오지만 객체 타입의 경우에는 아무리 같은 값을 가진다 해도 다른 메모리에 위치하기 때문에 false가 나오게 된다.
객체의 가변성
원시 데이터 타입은 같은 값을 가질 땐 같은 위치를 가리키다가 하나의 변수가 다른 값을 가지게 된다면 그때부터는 다른 공간에 값을 넣고 그 위치를 가리키게 된다.
객체 타입은 var o1 = {name: ‘kim’}; var o2=o1; 로 두고 o2.name=’lee’ 를 대입하면 새 메모리 공간을 가리키게 되는 것이 아니라 기존 공간에 있던 데이터가 변경되는 것이다.
객체의 복사
Object.assign( {}, o1 )을 통해서 빈 객체와 o1이란 이름을 가진 객체를 병합하여 하나의 객체로 만들게 되면 o1과 같은 값을 복사해서 다른 위치에 저장한다. 따라서 해당 객체 이름이 o2라 했을 때 o2.name=’lee’; 코드를 실행하면 o1의 값은 변하지 않고 o2가 가리키는 메모리 상의 데이터만 변경된다.
중첩된 객체의 복사
원시 데이터 타입인 string과 달리 배열 score는 별도의 공간에 저장되고 그 공간을 가리키게 된다.
이때, 객체를 복사하게 되면 원시 데이터 타입의 값은 복사되어 별도의 공간에 저장되지만 배열은 별도 공간에 복사되는 것이 아니라 똑같은 공간을 가리키게 된다.(포인터가 복사되는 것이라 생각하면 될 것 같다.)
따라서, 복사된 객체의 배열에 push를 하게 되면 원본 데이터에도 영향이 간다.
해결하는 방법은 아래와 같다.
배열을 복사하는 함수(concat 등등)을 사용하여 원본 데이터를 복사하여 별도의 공간에 저장해야 한다.
불변의 함수
function fn(person){
person.name = 'lee';
}
var o1 = {name: 'kim'}
fn(o1);
console.log(o1);
위 코드를 실행하면 원본 데이터인 o1.name이 kim이 날라가고 lee가 될 것이다.
원본 데이터를 불변하게 유지하는 함수는 아래와 같이 작성해야 한다.
function fn(person){
person = Object.assign({}, person};
person.name = 'lee';
return person;
}
var o1 = {name: 'kim'}
var o2 = fn(o1);
console.log(o1, o2);
그럼 새로운 o2가 생성되면서 원본 데이터는 바뀌지 않고 원하는 값을 출력할 수 있다.
function fn(person){
person.name = 'lee';
}
var o1 = {name: 'kim'}
var o2 = Object.assign({}, o1);
fn(o2);
console.log(o1, o2);
위 코드도 같은 결과가 나온다.
Object freeze로 객체를 불변하게 만들기
var o1 = {name:'kim', score:[1,2]}
Object.freeze(o1);
o1.name='lee';
console.log(o1);
위 코드를 실행하면 freeze 함수로 인해 원본 데이터가 바뀌지 않고 o1이 출력되는 것을 확인할 수 있다.
근데 주의할 점은 한 번 freeze 한 것을 푸는 방법은 없다. 복제를 해서 써야 한다.
또 유의할 점은 score에 push를 할 경우엔 원본 데이터가 변경이 된다.
이유는 score 배열은 원시 데이터 타입이 아니라서 별도의 공간에 저장되기 때문이다.
따라서 Object.freeze(o1.score); 코드를 추가해야지 오류가 뜨면서 push 하지 못한다고 뜬다.
const vs Object.freeze
const는 가리키는 주소 자체를 바꾸지 못하는 것
freeze는 값 자체를 변경하지 못하게 하는 것
'Frontend > Study' 카테고리의 다른 글
누구든지 하는 리액트 7편: 배열 다루기 (1) 생성과 렌더링 (1) | 2024.10.16 |
---|---|
누구든지 하는 리액트 6편: input 상태 관리하기 (0) | 2024.10.16 |
누구든지 하는 리액트 5편: LifeCycle API (0) | 2024.10.16 |
누구든지 하는 리액트 4편: props 와 state (0) | 2024.10.16 |
누구든지 하는 리액트 3편: JSX (1) | 2024.10.16 |