현업에 들어와 본격적으로 JavaScript를 접하게 되면서 항상 의문이 들었던 부분이 있었다.
" var 선언문 하나로 number, Array 등 다양한 데이터 타입들을 다루면서 어떤 타이밍에 값을 유지하고 변화시켜야 하지? "
적은 양의 변수가 아닌 10000개, 또는 그 이상의 수많은 변수를 선언하는 경우 이를 제어하기는 쉽지 않을 것이다.
JS Immutability는 특히 React와 같은 라이브러리 또는 redux, time travel과 같은 고급 기법을 구현하는데 기초가 되기도 한다.
참고로 JS Immutability가 React의 기초 지식 state를 이해하는 데 큰 도움이 된다.
필자는 react를 처음 접한 뒤 Immutability를 정리하면서 유레카를 외쳤다...
JavaScript Immutability를 통해 원본 데이터 유지를 위해 생각해야 하는 부분이 무엇인지 살펴보도록 하자.
(이 글은 opentutorial egoing님의 생활코딩 강좌를 토대로 작성하였습니다.)
JavaScript Immutability
Immutability ?
= 불변성
= 데이터의 원본이 훼손되는 것을 막는 것
데이터를 불변하게 다루면 데이터들 간의 간섭으로 인한 버그의 가능성을 획기적으로 낮출 수 있다. 또 데이터가 변경되었는지 여부를 매우 쉽게 체크할 수 있으며 특히 CRUD(Create, Read, Update, Delete) 작업 시, 불변성을 보장하는 것은 매우 중요하다.
이름에 대한 불변함
var v = 1; // v는 name, 1은 value를 뜻한다.
v = 2;
console.log(v); // 2
const a = 1;
a = 2; // error
이름을 불변하게 하는 방법은 바로 const를 사용하는 것이다.
const를 사용하게 되면 선언한 변수를 수정할 수 없게 되며, 수정을 시도하는 경우 error를 발생시킨다.
내용에 대한 불변함
var p1 = 1;
var p2 = 1;
console.log(p1===p2); // true
var o1 = {name:'kim'}
var o2 = {name:'kim'}
console.log(o1===o2); // false
JavaScript는 값이 바뀌지 않는 원시 데이터 타입과 값이 바뀔 수 있는 객체 타입(Object)을 다르게 취급한다.
Data Type
- 원시 데이터 타입 (Primitive) : Number, String, Boolean, Null, Undefined, Symbol...
- 객체 타입 (Object) : Object, Array, Function...
객체의 가변성
객체의 복사
var o1 = {name:'kim'}
var o2 = Object.assign({}, o1); // 첫 번째 파라미터와 두 번째 파라미터를 합쳐서 return
o2.name = 'lee';
console.log(o1, o2, o1 === o2); // {name:'kim'} {name:'lee'} false
원본 객체를 수정하지 않고 복제본을 수정하는 방법
var o1 = {name:'kim', score:[1,2]}
var o2 = Object.assign({}, o1);
o2.score = o2.score.concat(); // o2.score를 복제
o2.score.push(3);
console.log(o1, o2, o1 === o2, o1.score === o2.score);
// {name:'kim', score:[1,2]} {name:'kim', score:[1,2,3]} false false
- Nested Data의 복제 (concat)
Object가 Object 형태로 내부 property를 갖고 있는 경우 Nested Data (중첩된 데이터)라고 부른다.
아래와 같이 Array(Object)를 property로 가지고 있는 경우, 해당 값 변경 시 원본 데이터 값이 영향을 받게 된다.
따라서 Object와 내부 property 값도 복제(concat)해서 사용해야 원본 데이터를 유지할 수 있다.
이렇게 JS는 함수의 파라미터의 인자가 원시 데이터인지 객체인지에 따라 동작 방법이 달라진다.
따라서 아래와 같이 함수를 정의할 때 원본 데이터를 유지할 것인지 아닌지에 따라 assign, concat 함수를 통해 불변성을 유지해야 한다.
// function fn(person){
// person = Object.assign({}, person);
// person.name = 'lee';
// return person;
// }
// var o1 = {name:'kim'}
// var o2 = fn(o1);
// console.log(o1, o2);
function fn(person){
person.name = 'lee';
}
var o1 = {name:'kim'}
var o2 = Object.assign({}, o1);
fn(o2);
console.log(o1, o2); // {name:'kim'} {name:'lee'}
var score = [1,2,3];
var a = score;
var b = score;
// 1~
// score.push(4);
var score2 = score.concat(4);
console.log(score, score2, a, b); // [1,2,3] [1,2,3,4] [1,2,3] [1,2,3]
const vs Object.freeze ?
const : name이 가리키는 값을 다른 것으로 못 바꾸게 하는 것
Object.freeze : 값 자체를 못 바꾸게 하는 것
따라서 const와 freeze를 적재적소에 활용하면 값을 불변하게 유지할 수 있다.
무작정 JavaScript 입문 과정에서 이 내용을 접했다면 대충 보고 넘어갔을 것 같은 내용이지만
2년 차 개발자가 된 지금까지 해 온 삽질을 생각해보면 기초적인 내용에 대한 정확한 이해도가 가장 큰 자산이 되는 것 같다...
위 내용이 memory leak과 같은 복잡한 생각이 필요한 부분에서 분명 빛을 발할 것이다. :)
'JavaScript' 카테고리의 다른 글
ES6_템플릿 리터럴 (Template Literals) (0) | 2022.02.12 |
---|---|
JSDoc을 통해 JavaScript API 문서 만들기 (0) | 2020.12.07 |
클로져 (Closure) (0) | 2020.10.27 |
JavaScript의 Array 관련 함수들 (0) | 2020.10.11 |
JavaScript를 위한 자료구조 (3) | 2020.10.10 |