반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- React #리액트 이벤트 주기 #리액트 이벤트
- 버블링 #갭쳐링 #이벤트 #JS
- 백준 #직각삼각형
- React-Query
- 노마드 코더 #타입스크립트 #typescript #class
- npm #not being able to find a file #npm install Error
- react
- 플로이드 #c++
- DP #c++
- React #controlled component #비제어 컴포넌트 #제어 컴포넌트
- JWT #토큰 #refreshToken #accessToken #Token #token #localStorage #sessionStorage
- raect typescript #react #typescript #styled-component
- 이친수
- donwstream #upstream #origin
- 코드스테이츠 #알고리즘 #그리디
- useState #Hooks
- react #useCallback #react Hook
- 백준 #적록색약
- RateLimit
- rate limit
- react fragment
- React #effect hook #useEffect
- axios
- 얕은 복사 #깊은 복사 #shallow copy #deep copy
- 빡킹독
- 다익스트라 #파티 #백준
- html entities
- interceptors
- React #Hook rules #Hook 규칙
- #useRef #언제 쓰는데?
Archives
- Today
- Total
꿈꾸는 개발자
얕은 복사(shallow copy) vs 깊은 복사(deep copy)-Javascript 본문
공통: 얕은 복사든 깊은 복사든 생성된 객체는 기존과 다른 별개의 객체이다!
복사에 대한 정의: 여기에서 복사란, 원시값처럼 새로운 값을 복사한다는 의미로 복사되지 않았다는 것은 곧 참조값이 넘어갔다는 의미로, 상호간의 영향을 줌을 의미한다.
얕은 복사(Shallow Copy): 객체에 중첩되어 있는 객체의 경우 참조값을 복사한다
- 객체 트리의 노드의 최말단을 복사하지 않는 방식 (따라서, 중첩 객체의 참조값을 복사한다고 한다!)
const original = {
num: 3,
age: 24,
arr: ["a", "b", "c"],
};
const clone1 = { ...original }; //참고 spread문법은 iterable한 객체만 사용할 수 있다
original.num = 4;
console.log(clone1.num); // 3이 나온다
original.arr.push("d");
console.log(original.arr === clone1.arr); //true가 나온다!
- 언뜻 보면, num의 예시만 보면, 상호간의 영향을 주지 않는 것으로 이해할 수 있지만, arr 즉 배열을 다룰 때는 참조값(reference)을 공유하고 있음을 확인할 수 있다!
- Ojbect.assign() 또한 마찬가지로 shallow copy에 머물고 있다.
- “For deep cloning, we need to use alternatives because Object.assign() copies property values. If the source value is a reference to an object, it only copies that reference value.” (출처 MDN)
- JS Method: ex) slice(), concat(), Array.from() 등
- 원본 배열을 변경하지 않는다!
- 얕은 복사이기에 중첩 객체가 있을 경우 복사하지 않고 반환 즉 참조값을 반환하기 때문에 상호간 영향 받음을 의미한다.
let arr1 = [{ a: 1 }, { b: 2 }, { c: 3 }];
let arr2 = arr1.slice();
arr1[0].a = 10;
arr2[1] = "addd";
console.log(arr1, arr2);
- 위와 같은 예시를 돌려서 코드를 확인해보면
- 배열 내의 객체의 경우 얕은 복사의 경우 복사되지 않기 때문에 참조값을 공유한다. 따라서, arr1[0].a 의 객체값을 변경하면, arr2의 객체값도 영향을 받음을 확인할 수 있다.
깊은 복사(Deep Copy): 객체에 중첩되어 있는 객체까지 모두 복사해서 원시 값처럼 완전한 복사본을 만든다.
- 객체 트리의 최말단 노드까지 복제하는 방식
const original = {
num: 1000,
bool: true,
arr1: [1, 2, 3, 4, 5],
obj1: {
x: 5,
y: 10
},
arr2: [
[11, 22],
[33, 44],
[55, 66]
],
obj2: {
obj3: {
1: 1,
2: 2
},
obj4: {
3: 3,
4: 4,
obj5: {
mushroom: "🍄"
}
}
},
func: function () {
console.log("func");
}
};
const copy = JSON.parse(JSON.stringify(original));
original.bool = false;
console.log(copy.bool); // true 안바뀜
original.obj2.obj4.obj5.mushroom = "💎";
console.log(copy.obj2.obj4.obj5.mushroom); // 🍄 안바뀜
- 위의 코드에서는 JSON stringify()와 parse()을 연속적으로 호출했을 때 상호간의 영향을 주지 않음을 확인할 수 있다! 즉 얕은 복사와 달리 중첩 객체까지 함께 복사되는 것이다. 즉, 동일한 객체 트리를 가지는 새로운 객체를 복제하는 것!
- 하지만, JSON에서 함수는 적용되지 않기 때문에 함수가 누락된다는 단점이 존재한다.
- 그 외에도 직접 구현이 있지만, 재귀적으로 말단 노드까지 모두 복사해주는 함수를 구현해줘야 하기 때문에 이 마저도 쉽지는 않다!
Deep Copy 쉽지 않은 것은 알겠다 그래서 해결책은....?
- 기본적으로 자바스크립트에서 깊은 복사를 수행하기란 쉽지 않다. 내부적으로 그렇게 모델링돼 있지 않기 때문이라 한다. 따라서, 다소 낮은 퍼포먼스를 보이더라도 라이브러리(Lodash 등 )를 이용해서 깊은 복사를 수행해주는 것도 나쁜 방법은 아니다. 하지만, 아키텍처의 관점에서 과연 필요한지를 고민하는 것 또한 개발자의 판단 역량이라고 말하고 있다.
참고자료:
- https://www.daleseo.com/js-objects-clone/