[JavsScript] 깊은 복사, 얕은 복사

공진용·2023년 5월 27일
1

JavaScript

목록 보기
3/3

▶ 깊은 복사? 얕은 복사?

Javascript 의 얕은 복사는 객체의 참조값(주소 값)을 복사하고, 깊은 복사는 객체의 실제 값을 복사한다.

즉, 복사된 녀석의 값을 변경했을 때, 원본 녀석도 바뀌면 얕은 복사, 복사된 녀석을 지지고 볶아도 원본 녀석이 그대로면 깊은 복사 이다.

이렇게만 설명해 놓으면 헷갈리는 부분이
'원시값' 과 '참조값' 의 개념이다.

대입을 통한 원시값 복사 -> 깊은 복사가 된다.


const a = 'a';
let b = 'b';
 
b = 'c';

console.log(a, b);

================================
출력 (원본은 그대로!)
a c

대입을 통한 참조값 복사 -> 얕은 복사가 된다

const a = {
  one: 1,
  two: 2,
};
let b = a;
 
b.one = 333;
 
console.log(a, b); 

================================
출력 (원본이 변했다!)
{ one: 333, two: 2 }
{ one: 333, two: 2 } 

그럼 이제 참조값(객체) 의 복사되는 모냥을 알아보자. 이게 또 골치 아프다.

▶ 참조값의 얕은 복사

참조값을 그냥 대입으로 하면 위처럼 얕은 복사가 된다. 그건 JavaScript 의 참조값들은 주소를 가르키고 있기 때문인데, 지금 설명하는 녀석들은 얕은 복사 중에서도 좀 다르다.

slice() 와 spread 연산자, Object.asign() 등등을 한다면, 1depth 는 깊복, 2depth 는 얕복을 한다. 이 녀석들을 참조값의 얕복이라 부른다.

const original = [
  {
    a: 1,
    b: 2,
  },
  true,
];
const copy = original.slice();
  
// 복사된 배열만 변경.
copy[0].a = 99;
copy[1] = false;
  
console.log(original);
// [ { a: 99, b: 2 }, true ]
console.log(copy);
// [ { a: 99, b: 2 }, false ]

a 는 얕복이라 같이 바뀌고 
true는 깊복처럼 따로국밥이다.
하지만 얕복.

▶ 참조값 깊은 복사 방법

const copy = JSON.parse(JSON.stringify(object));

실무에서 진짜 많이 쓴다 이거.
찾아보며 알았는데, 이 녀석 객체 안에 함수가 있으면 undefinded가 되어서 나온다.
(당연히 Json 으로 바꾼 걸 다시 바꾸려니 알 수 없겠지)

const object = {
  a: "a",
  number: {
    one: 1,
    two: 2,
  },
  arr: [1, 2, [3, 4]],
};
 
const copy = JSON.parse(JSON.stringify(object));
 
copy.number.one = 3;
copy.arr[2].push(5);
 
console.log(object); // { a: 'a', number: { one: 1, two: 2 }, arr: [ 1, 2, [ 3, 4 ] ] }
console.log(copy); // { a: 'a', number: { one: 3, two: 2 }, arr: [ 1, 2, [ 3, 4, 5 ] ] }

Lodash 라이브러리를 쓰면 더 편하게 깊복할 수 있다.
근데 Lodash 맛을 봐 버리면 계속 그거만 쓸 거 같아서 일단 나는 안 쓰고 있다.

structuredClone

찾아보다 나온 녀석. 아직은 일부 브라우저(Web API 형태로) 및 환경에서만 지원한다고 하는데, 깊은 복사본을 제공하는 녀석이다.

JSON.stringify()의 많은 (전부는 아니지만) 단점을 해결한다고 하는데, 순환되는 데이터 구조를 처리할 수 있고, 내장 데이터 타입(Map 같은 녀석)을 지원할 수 있으며 일반적으로 더 강력하고 더 빠르다고 한다.


const obj1 = {
  a: 1,
  b: 2,
  // c: function () { return this.a + this.b }, 아직 함수는 안됨
  d: new Date(), // Date 도 Date 로 가져온다!
  e: 1n //BigInt 도 된다!
}

const obj2 = structuredClone(obj1);

▶ 마치며

우리고 그냥 알고 있던 복사는 깊은 복사이다. 애초에 얕은 복사가 말이 되냐. 생활 레벨의 개념에서 복사라는 말의 의미엔 원본과 같이라는 개념은 존재하지 않는다. 상관없는 얘기지만, 삶은 깊이 있게 살아야 한다. 가벼운 말과 행동은 잘못되지 않았지만, 가벼운 삶과 철학으로 인생을 강에 흘려보내지 말자. 그렇게 도착한 곳은 안식처일 수 없다.

이거 보는 게 낫다.
https://bbangson.tistory.com/78 [뺑슨 - JavaScript 깊은 복사 얕은 복사]

profile
좋은 문장이 될 FE 개발자

0개의 댓글