티스토리 뷰

반응형

자바스크립트에서 객체를 다루려면 참조와 복사의 개념에 대해 반드시 알아야 한다. 객체의 참조, 얕은 복사, 깊은 복사의 차이점에 대해 자세히 알아보도록 하겠다.

 

 

 

 

요약

 

  의미 방식
참조 (reference) 같은 객체를 참조 변수에 그대로 대입
얕은 복사 (shallow copy) 중첩된 객체를 복사했을 때, 가장 바깥 객체만 복사되며 내부 객체는 참조 관계를 유지.
깊은 복사와 참조의 중간 형식
스프레드 문법 사용
깊은 복사 (deep copy) 복사하여 새로운 객체를 생성
참조 관계가 생기지 않음
JSON 연산자 사용

 

 

 

 

참조 (Reference)

변수 array와 ref는 같은 객체를 참조하고 있기 때문에 어떤 걸 비교해도 true로 반환된다. 한쪽에서 변경하면 다른 쪽도 변경된다.

 

1
2
3
4
5
6
7
8
const array = [{Name: 'Kim'}, {Age: 30}, {Gender: 'W'}];
const ref = array;
 
console.log(array === ref); // true
console.log(array[0=== ref[0]); // true
 
array[0]['Name'= 'Lee';
console.log(ref[0]['Name']); // Lee
cs

 

 

 

 

 

얕은 복사 (Shallow copy)

얕은 복사를 하기 위해서는 '...' 연산자인 스프레드(Spread) 문법을 사용한다. 가장 바깥 배열만 복사되기 때문에 가장 바깥 객체를 비교하면 false이고 내부 객체를 비교하면 true이다. 가장 바깥에 있는 외부 객체는 참조 관계가 없으며, 내부 객체는 참조 관계가 있다.

 

1
2
3
4
5
6
7
8
const array = [{Name: 'Kim'}, {Age: 30}, {Gender: 'W'}];
const shallow = [...array];
 
console.log(array === shallow); // false
console.log(array[0=== shallow[0]); // true
 
array[0]['Name'= 'Lee';
console.log(shallow[0]['Name']); // Lee
cs

 

 

 

 

 

깊은 복사 (Deep copy)

깊은 복사는 원본과 완전히 참조 관계가 끊긴다. 깊은 복사를 하기 위해서는 JSON 메서드를 활용하여야 한다. JSON.stringify() 메서드는 객체를 문자열(String)로 바꿔주는데, 이 과정에서 참조 관계가 완전히 끊어지게 된다. 이렇게 문자열로 바뀐 객체를 다시 객체의 형태로 바꿔주는 메서드가 JSON.parse()이다. 다시 객체 형태로 변형되지만 참조 관계는 진작에 끊어진 상태이다. 이와 같은 과정을 통해 깊은 복사가 가능해지는 것이다.

 

1
2
3
4
5
6
7
8
const array = [{Name: 'Kim'}, {Age: 30}, {Gender: 'W'}];
const deep = JSON.parse(JSON.stringify(array));
 
console.log(array === deep); // false
console.log(array[0=== deep[0]); // false
 
array[0]['Name'= 'Lee';
console.log(deep[0]['Name']); // Kim
cs

 

 

JSON 메서드를 사용하는 깊은 복사 방식은 간단한 객체일 때는 괜찮지만 성능이 느리기 때문에 실무에서는 lodash 같은 객체 관련 라이브러리 사용을 추천한다.

 

 

 

 

 

 

그 외 여러 가지 자료형 복사 방식

1) 객체가 아닌 문자열, 숫자, 불 값 등의 자료형은 변수에 대입하더라도 참조 관계가 성립되지 않는다. 따라서 다른 변수에 바로 대입하는 방식을 사용하면 된다.

2) 배열의 경우 slice() 메서드를 사용한다.

3) 외부는 객체라도 내부에 중첩된 객체가 없는 경우 스프레드(...) 메서드를 활용한다.

4) 외부는 객체가 아니더라도 내부에 객체가 들어있는 경우 반드시 깊은 복사 방식을 사용하여야 한다.

5) 중첩된 객체의 경우 반드시 깊은 복사 방식을 사용한다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 1) 문자열 복사
const a = '가나다';
const b = a;
 
 
 
// 2) 배열 복사
const array = [123];
const copyArray = array.slice(); // 인덱스 값을 넣지 않으면 전체 요소가 추출됨
 
array[0= 5;
console.log(copyArray) // 1, 2, 3
 
 
 
// 3) 단순 객체
const obj = {a: 1, b: 2, c: 3};
const copyObj = {...obj}; // 스프레드 메서드를 사용하면 가장 바깥 객체는 참조 관계가 끊김
 
obj['a'= null;
console.log(copyObj['a']); // 1
 
 
 
// 4) 배열 내부 객체
const m = [{Name: 'Kim'}, {Age: 30}, {Gender: 'W'}];
const mCopy = JSON.parse(JSON.stringify(m));
 
m[0].Name = 'Lee';
console.log(mCopy[0].Name); // Kim
 
 
 
// 5) 중첩된 객체
const d = { 
    info: {Name: 'Kim', Age: 30, Gender: 'W'},
    grade: {math: 200, sci: 80, Eng: 100},
};
const dCopy = JSON.parse(JSON.stringify(d));
 
d.grade['math'= 90;
console.log(dCopy.grade['math']); // 200
cs

 

 

 

 

 

 

반응형
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31