SPACE RUMI

Hi, I am rumi. Let's Splattack!

[IT] 프로덕트 개발/Javascript - 자바스크립트

[Javascript ] 깊은복사와 얕은복사, 그리고 원시형 참조형 데이터

백루미 2022. 5. 31. 14:43
반응형

JS 데이터에는 원시자료형(primitive type), 참조 자료형(reference type) 타입이 있다. 
변수에는 하나의 값이나 주소만 저장할수있다.

원시 자료형 (primitive type)

원시 자료형이 할당될 때, 변수에 할당할 때 값(value)을 저장하며, 하나의 데이터를 담는다.
number, string, boolean, undefined, null(엄밀하게는 객체다), symbol 등이 있다.

const stringA = 'a';
const number123 = 123;
const boolSample = true;

 

참조 자료형 (reference type)

원시 자료형이 아닌 모든 타입.
원시 자료형 데이터들의 집합이며, 변수에 할당할때 메모리 주소를 저장한다.
배열, 객체, 함수 등이 있다.

const로 선언한 변수에 Array.push로 값을 추가할 수 있는 이유는, 배열이 참조 자료형이기 때문이다. 값이 저장된 주소값을 할당하는것이다.

const myLanguage = 'js';
const languages = ['js','ts','c'];

myLanguage = 'c' // error
languages = 'ruby' // error

language.push('ruby') // ['js','ts','c','ruby'];


/* 발견한것 */
language.push = 'c++'

/*
이렇게 하면 어떻게 될까?
['js','ts','c','ruby', push:'c++']
위와같이 들어가지만, push라는 Array 메서드를 'c++'로 재정의 했기 때문에
이후 language.push('go')처럼 push 메서드를 사용할 수 없다.
이때 language는 Array이나( Array.isArray(language) ), 
push:'c++'를 카운트하지않는다.
language.pop()을 하면, push:'c++'이 아닌 'ruby'가 출력된다.
*/

 

얕은복사 (shallow copy)

참조값을 복사한다. 같은 데이터를 바라보고 있기 때문에, 데이터를 변경하면 원시데이터도 바뀐다.

const origin = {key : 30};
const copyOrigin = origin;

copyOrigin.key = 1;

console.log(origin.key) // 1

 

깊은복사 (deep copy)

값 자체를 복사하여 다른 메모리 주소를 할당한다. JS의 원시형 데이터는 깊은복사를 한다.
원시 데이터와 연결(참조)이 완전히 끊긴 새로운 데이터이다.

let original = 35;
let copyOriginal = original;

copyOriginal = 1;

console.log(original) // 35
console.log(copyOriginal) // 1


참조형 데이터를 SpreadOperator(...), 혹은 Object.assign( { }, 원본) 를 이용해 복사를 하고, 서로 비교하면 false 가 나온다.
서로 참조 주소가 다르다는걸 알수있다.

const data = {
    name:'rumi',
    isE : true,
    book:{
       0:'테스트',
       1:'JS 원리'
    }
}

const copyData = data;
console.log(data === copyData); // true

const spreadData = {...data};
console.log(data === spreadData; //false

const objAssignData = Object.assign({}, data);
console.log(data === objAssignData); // false

하지만 SpreadOperator(...), 혹은 Object.assign( { }, 원본) 은 1depth 밖에 깊은복사되지 않는다. 
참조형 내부의 참조형데이터는 얕은복사가 된다.

const data = {
    name:'rumi',
    isE : true,
    book:{
       0:'테스트',
       1:'JS 원리'
    }
}

const spreadData = {...data};

spreadData.book[0] = 'test'; // 복사한 데이터를 변경했더니
console.log(data.book[0]) // 원본 데이터가 test로 바뀐다.

 

따라서 완전한 깊은복사를 하려면 JSON.parse(JSON.stringify(data))를 사용하거나, lodash 라이브러리를 사용한다.
* JSON.parse(JSON.stringify()) 방법은 함수에 대한 깊은복사는 수행하지않는다.

반응형