[JavaScript] 배열, 객체 깊은 복사하는 법 - Array Deep Copy, Object Deep Copy

 


JavaScript는 기본적으로 얕은 복사(Shallow Copy)를 통해 변수값을 할당받습니다.

따라서, 전달받은 변수의 변경이 의도치 않게 참조대상 값을 변경하여 예상치 못한 결과를 얻기 기도 합니다.


이번 포스팅에서는 자주 쓰이는 Array, Object 객체에 대한 깊은 복사(Deep Copy) 방법들을 비교합니다.


1. Array

1) 얕은 복사(Shallow Copy)

  : 얕은 복사가 이뤄져 원본(target) 값이 변경된 경우.

[코드]
1
2
3
4
5
6
7
8
9
const target = ['a','b','c', 'd'];

let clone = target;

clone[3] = '123';


console.log('target : ' + target);
console.log('clone  : ' + clone);

[결과]



2) 전개 구문(Spread Syntax) 을 통한 복사

 : 깊은 복사가 이뤄져 원본(target) 값을 변경하지 않음. (#1)

  단, 전개 구문을 사용한 경우 2차원 배열 이상의 값은 Deep Copy가 이뤄지지 않음. (#2)

[코드 #1] : 1차원 배열

1
2
3
4
5
6
7
8
9
const target = ['a','b','c', 'd'];

let clone = [...target];

clone[3] = '123';


console.log('target : ' + target);
console.log('clone  : ' + clone);

[결과 #1]


[코드 #2] : 2차원 배열

1
2
3
4
5
const target = ['a','b','c', ['d','e']];   

let clone = [...target];

clone[3][0] = '123';

[결과 #2]



3) JSON 을 통한 복사

 : 전개 구문에서 2차원 배열 이상의 Deep Copy에 대한 해결 책이지만, 성능 상 지양하는 방법.

[코드]
1
2
3
4
5
const target = ['a','b','c', ['d','e']];

let clone = JSON.parse(JSON.stringify(target));    

clone[3][0] = '123';

[결과]




2. Object

 1) 얕은 복사(Shallow Copy)

  : 얕은 복사가 이뤄져 원본(target) 값이 변경된 경우.

[코드]

1
2
3
4
5
6
7
8
const target = { 'a': 123, 'b': 456, 'c': 789 };

let clone = target;

clone.c = '999'

console.log('target : ' + JSON.stringify(target));
console.log('clone  : ' + JSON.stringify(clone));

[결과]



 2) 전개 구문 (Spread Synctax)을 통한 복사

 : 깊은 복사가 이뤄져 원본(target) 값을 변경하지 않음. (#1)

  단, 배열 예제와 동일하게 중첩 객체(nested Object)에 대해서는 Deep Copy가 이뤄지 않음. (#2)

[코드 #1] 

1
2
3
4
5
6
7
8
const target = { 'a': 123, 'b': 456, 'c': 789 };

let clone = { ...target };

clone.c = '999'

console.log('target : ' + JSON.stringify(target));
console.log('clone  : ' + JSON.stringify(clone));

[결과 #1]


[코드 #2] : 중첩 객체 (nested Object)

1
2
3
4
5
6
7
8
const target = { 'a': 123, 'b': 456, 'c': {'d' : 789} };

let clone = { ...target };

clone.c.d = '999';

console.log('target : ' + JSON.stringify(target));
console.log('clone  : ' + JSON.stringify(clone));

[결과 #2]



 3) JSON을 통한 복사

 : 배열과 마찬가지로 JSON 변환을 통해 중첩 객체에 대한 Deep Copy를 해소할 수 있음. (#1)

 단, 객체의 경우 함수형(function) 원소는 변환 과정에서 소실됨. (#2)

 이 경우, 위 전개 구문 (Spread Syntax)을 사용하면 함수형 원소도 깊은 복사가 이뤄짐.

[코드 #1]

1
2
3
4
5
6
7
8
const target = { 'a': 123, 'b': 456, 'c': {'d' : 789} };

let clone = JSON.parse(JSON.stringify(target));

clone.c.d = '999';

console.log('target : ' + JSON.stringify(target));
console.log('clone  : ' + JSON.stringify(clone));

[결과 #1]


[코드 #2] : 함수형 원소 소실

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let target = {
	'a' : 123,
	'b' : 456,
	'c' : function(){
		alert('Function C');
	}
}

let clone = JSON.parse(JSON.stringify(target));     // Function Not Copy

clone.c();

[결과 #2]



 4) Object.assign() 을 통한 복사

 : 전개 구문과 같이 깊은 복사를 수행하지만, 중첩 객체에 대해서는 처리하지 못함.

[코드 #1]

1
2
3
4
5
6
7
8
const target = { 'a': 123, 'b': 456, 'c': 789 };

let clone = Object.assign({}, target);

clone.c = '999'

console.log('target : ' + JSON.stringify(target));
console.log('clone  : ' + JSON.stringify(clone));

[결과 #1] : 깊은 복사

[코드 #2]

1
2
3
4
5
6
7
8
const target = { 'a': 123, 'b': 456, 'c': {'d' : 789} };

let clone = Object.assign({}, target);

clone.c.d = '999';

console.log('target : ' + JSON.stringify(target));
console.log('clone  : ' + JSON.stringify(clone));

[결과 #2] : 중첩 객체에 대한 얕은 복사


0 댓글