프로그래밍/Javascript

javascript object의 shallow copy와 deep copy

yongkshire 2020. 2. 25. 21:27

이번엔 javascript object (array 포함)에서 shallow copy와 deep copy를 하는 법과 어떻게 하면 deep copy의 속도를 높일 수가 있는 지에 대해서 얘기해보고자 한다. 

javascript에서 array나 object를 copy하게 될 일이 생기는데 일반

[1,2,3]

이런 경우는 그냥 array.slice() 이런 식으로 shallow copy할 수 있지만

[[1,2],[3,4]]

 

이런식으로 nested된 경우는 shallow copy를 했다가는 내부의 array들 (위에서는 [1,2], [3,4 ] 같은 경우는 reference값만 복사하게 되고, 결국 의도한 것과 다르게 쓰일 수가 있다. 나의 경우 복사해서 복사본의 값을 변형시켰을때 나의 의도와는 다르게 원본 값도 계속 변형되는 사태가 발생했다. 원본값을 복사한 복사본 값을 변화시켰을 때 원본값에 영향을 주지 않으려면 reference가 아니라 값을 그대로 긁어오고 새로운 reference 값을 가져야 하고, 이를 deep copy 혹은 deep clone 이라고 한다.

내가 이 문제에서 헤맸던 것도 shallow copy를 했었다는 것이고, 이 문제를 알게 되고, deep copy로 바꿨는데 deep copy를 하는 방법으로 search 결과 가장 먼저 찾은 것은

JSON.parse(JSON.stringify( array ))

이런 방식. 하지만 이 방식은 간단하긴 하지만 json으로 한번 변형했다 오니 보다 속도가 느렸다. 그래서 찾은게 제로초님 블로그에서 찾은

const copyObj = (obj) => {
  var copy = {};
  if (Array.isArray(obj)) {
    copy = obj.slice().map((v) => {
      return copyObj(v);
    });
  } else if (typeof obj === 'object' && obj !== null) {
    for (var attr in obj) {
      if (obj.hasOwnProperty(attr)) {
        copy[attr] = copyObj(obj[attr]);
      }
    }
  } else {
    copy = obj;
  }
  return copy;
}

이 코드였다. 이 코드를 쓰니 대략 스피드가 2배정도 빨라짐을 확인할 수 있었지만, 여전히 문제에서 요구한 스피드를 충족시키기엔 역부족이었다. 위의 code는 여러겹의 nested 및 모든 array, object를 만족시키는 코드이고, 지금 문제에서는 2중 array 문제만 해결하면 되므로 결국 내가

const copyObj = (arr) => {
  let copy = [];
  for (let i = 0; i < arr.length; i += 1) {
    copy.push(arr[i].slice());  
  }
  return copy;
}

간단하게 이런식으로 2중 nested array를 복사하는 코드를 짰고, 이렇게 하니 속도가 또 2배이상 빨라져서 결국 과제를 통과할 수 있었다.

앞으로 deep copy를 써야 하는 상황일 때 shallow copy를 쓰지 않도록 주의해야겠고, 가급적 속도에 신경쓴다면 아래와 같은 방식으로 code를 짜야함을 배웠다.