본문 바로가기
programming language/Javascript

얕은복사 깊은복사 개념

by cariño 2022. 9. 2.
728x90
반응형

코딩을 하다보면 얕/깊은 복사 개념을 모르면 중간중간 멈추게 된다.

어렴풋이 살짝만 알고 있던 상태에서 그순간만 이해하려고 대충 넘겼는데

데이터 타입정리하다보니 얕 깊복사 확실히 알아두자 맘을 먹게됐다. 

 

어짜피 해야하면서 ㅋㅋㅋ 왜이리도 어슬렁 하는거니 ㅠㅠㅠㅠ

앞에 데이터타입에 대한 개념을 정리한것을 토대로 
얕은 복사는 객체의 참조 값(주소 값) 을 복사, 깊은 복사는 객체의  '실제 값'을 새로운 메모리 공간 복사한다.

 

🍓[ 얕은 복사 (shallow Copy) ]

 

흔히 알고 있듯,  객체에 담겨있는 변수를 다른 변수에 할당하면 call by reference

(데이터 복사가 아닌 참조 형태)가 일어나게 되며, 한 변수를 변경하면 다른 변수의 데이터도 변경이 된다.

 

🔷 [참조형 데이터]

기본형 데이터의 할당과 다르게 참조형 데이터는 할당 전에 한 단계를 더 거치게 된다. 

var obj = {
    a: 1,
    b: 'bbb'
}

 

주소 1002 1003 ...
데이터 이름: obj
값: @5002
   
주소 5002 5003 5004
데이터 @7103 ~? 1 'bbb'

▼ 한 단계 더 걸쳐서 

주소 7103 7104 ...
데이터 이름: a
값: @5003
이름: b
값: @5004
 

 

참조 타입을 복사할 때 생성된 인스턴스들은 (참조 값)주소 값을 공유한다.

(변수가 가리키는 주소값이 같은 주소값을 가리킬 때 얕은 복사가 이루어진다. )

let obj1 = {c : 'a'}
let obj2 = c

obj1.c = 'ww'

console.log(c) //{c : 'a'}
console.log(d) //{c : 'a'}
console.log(c === d) //true

변수에 객체를 저장하면 독립적인 메모리 공간을 저장하고, 변수에 저장된 메모리 공간의 참조를 저장한다.

할당된 변수들은 사실 해당 객체를 참조(주소 값) 을 조작한다. 

  • obj2.c의 값을 수정해도 obj2는 obj1과 같은 주소를 바라보고 있기 때문에 obj1과 값이 동일하다. 

🍇 [ 깊은복사 (Deep Copy) ]

 

데이터의 공유가 아닌, 똑같은 구조의 객체를 하나 더 생성하여 사용하고자 할 때 

변수에 원시값을 저장하면 메모리 공간에 실제 데이터 값이 저장된다.

할당된 변수 조작시에 저장된 실제 값이 변한다. 

  • 데이터 자체를 통째로 복사한다.
  • 복사된 두 객체는 완전히 독립적인 메모리를 차지한다.
  • value type의 객체들은 깊은 복사를 하게 된다. 
const a = 1
let b = a

b = 3

console.log(a)
console.log(b)
console.log(a === b) //false

원시값을 복사할 때 또 다른 독립적인 메모리 공간에 할당하기 때문에

복사를 하고 갚을 수정해도 기존 원시값을 저장한 변수에는 영향이 가지 않는다. 

 


[ Javascript의 복사 ]

1. 일반적인 복사

변수에 값을 할당하는 형태의 복사를 말한다. 

const a = { name: 'bin' }

const b = a



console.log(a === b) //true

 

- 같은 참조 값을 가지고 있다.

- a와 b 둘중 무엇이든 데이터를 조작하게 되면 a, b모두 동일 하게 변경된다. 

 

얕은 복사와 깊은 복사를 쓰는 이유?

 

객체를 그대로 사용하게 되면 기존 객체의 원본 데이터가 손상이 된다.
그래서 객체의 깊은 복사는 매우 중요하게 짚고 넘어가야한다.
얕은 복사와 깊은 복사는 참조 값이 아닌 값 자체를 복사하기 위함이다. 

 

2. 얕은 복사

- 객체의 1dept까지만 복사한다. 

- Object.assign() / spread operator

- 얕은 복사의 객체들은 복사된 값들과 원본이 다르다.

- 중첩 객체는 값이 복사되지 않고 참조 값이 복사되어 서로 같다고 나온다.  

let user = {
    name: 'mimi',
    age: 20,
    id: 1,
    birthday: {
        month : 'june',
        day: 18
    }
}

const assignUser = Object.assign({}, user)
const spreadUser = {...user}

console.log(user);
console.log(assignUser);
console.log(spreadUser);
//{ name: 'mimi', age: 20, id: 1, brith: { month: 'june', day: 18 } }
//{ name: 'mimi', age: 20, id: 1, brith: { month: 'june', day: 18 } }
//{ name: 'mimi', age: 20, id: 1, brith: { month: 'june', day: 18 } }


console.log(user === assignUser); //false
console.log(user === spreadUser); //false
console.log(assignUser === spreadUser); //false

console.log(user.birthday === spreadUser.birthday); //true
console.log(user.birthday === spreadUser.birthday); //true
console.log(assignUser.birthday === spreadUser.birthday); //true

 

3. 깊은복사

- 2dept이상이여도 전부 복사 한다.

- 재귀적으로 깊은 복사를 수행 :  Time Complexity(시간 복잡도)도 늘어나게 된다. 

- Lodash의 cloneDeep 사용 : 자바스크립트 고차함수 집합 및 함수형 라이브러리로 완벽 깊은 복사 가능

- JSON.stringify() :  문자열로 변환하는 순간 참조 값이 끊기기 때문에 새로운 Object로 만들어 사용할 수 있다.

 

728x90

'programming language > Javascript' 카테고리의 다른 글

callback, promise, async/await  (0) 2022.11.03
변수에 대하여  (0) 2022.10.13
Symbol  (0) 2022.09.01
자바스크립트 DATA Types  (0) 2022.09.01
모던 자바스크립트 Deep Dive 훑기  (1) 2022.08.30

댓글