# [1장] 데이터 타입 - 북 스터디

<div class="bg-yellow-50 text-3xl text-center font-bold my-4">🤓 스터디원 🤓</div>

<div class="w-full flex flex-col md:flex-row items-center justify-center gap-8 text-sm border dark:border-slate-700 rounded-xl p-4">

<div class="w-24 md:ml-4 p-2 flex flex-col justify-center items-center">
  <img class="rounded-full" src="https://github.com/eeeyooon.png" />
  <span class="font-semibold">강지윤</span>
  <a href="https://github.com/eeeyooon">@eeeyooon</a>
</div>
<div class="w-24 p-2 flex flex-col justify-center items-center">
  <img class="rounded-full" src="https://github.com/lulla-by.png" />
  <span class="font-semibold">이예솔</span>
  <a href="https://github.com/lulla-by">@lulla-by</a>
</div>
<div class="w-24 p-2 flex flex-col justify-center items-center">
  <img class="rounded-full" src="https://github.com/sryung1225.png" />
  <span class="font-semibold">이성령</span>
  <a href="https://github.com/sryung1225">@sryung1225</a>
</div>
<div class="w-24 p-2 flex flex-col justify-center items-center">
  <img class="rounded-full" src="https://github.com/Stilllee.png" />
  <span class="font-semibold">이에스더</span>
  <a href="https://github.com/Stilllee">@Stilllee</a>
</div>
<div class="w-24 p-2 flex flex-col justify-center items-center">
  <img class="rounded-full" src="https://github.com/chaehaeun.png" />
  <span class="font-semibold">채하은</span>
  <a href="https://github.com/chaehaeun">@chaehaeun</a>
</div>

</div>

<br>
<br>

# [코딩 마을 방범대 : 1장. 데이터 타입](https://github.com/Coding-Village-Protector/core-js/blob/main/%5B1%EC%9E%A5%5D%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%ED%83%80%EC%9E%85/%EC%9D%B4%EC%84%B1%EB%A0%B9.md)

## 질문과 답변

### 1\. [가비지 컬렉터](https://github.com/Coding-Village-Protector/core-js/issues/1)

####  가비지 컬렉터의 작동 방식과 메모리 수거 대상이 되는 기준에 대해 설명해주세요.

<details data-node-type="hn-details-summary"><summary>eeeyooon</summary><div data-type="detailsContent">가비지컬렉터는 런타임 환경에 따라 특정 시점이나 메모리 사용량이 포화 상태에 임박할 때마다 자동으로 수거 대상들을 수거합니다. 어떤 데이터에 대해 자신의 주소를 참조하는 변수의 개수를 참조 카운트라고 하는데, 이때 참조 카운트가 0인 메모리 주소는 가비지 컬렉터의 수거 대상이 됩니다. 수거된 메모리는 다시 새로운 값을 할당할 수 있는 빈 공간이 됩니다.</div></details>

<details data-node-type="hn-details-summary"><summary>lulla-by</summary><div data-type="detailsContent">가비지 컬렉터의 메모리 수거 대상은 참조 카운트가 0인 메모리 주소입니다. 참조 카운트는 어떤 데이터에 대해 자신의 주소를 참조하는 변수의 개수를 뜻합니다. 즉 자신의 주소를 더 이상 참조하는 변수가 없을 때 참조 카운트는 0이 되며 가비지 컬렉터는 런타임 환경에 따라 특정 시점이나 메모리 사용량이 포화 상태에 임박할 때 자동으로 이러한 수거 대상들을 수거합니다.</div></details>

<details data-node-type="hn-details-summary"><summary>chaehaeun</summary><div data-type="detailsContent">가비지컬렉터는 런타임 환경에 따라 특정시점이나, 메모리 사용량이 특정 임계값에 도달했을 때에 자동으로 수거 대상들을 수거합니다. 
<br>
<br>

수거 대상 : 도달 가능성이 없는 값. (도달 가능한 값 : 코드의 실행 흐름에서 어떤 방식으로든 참조할 수 있는 변수나 객체) 특정 시점 : 함수가 실행을 마치고 해당 콜스택에서 제거 될 때</div></details>

<details data-node-type="hn-details-summary"><summary>sryung1225</summary><div data-type="detailsContent">가비지 컬렉터(garbage collector, GC)는 자신의 주소를 참조하는 변수의 개수(참조 카운트)가 0이 된 메모리 주소를 수거 대상으로 자동 수집합니다. 그리고 런타임 환경에 따라 특정 시점이나 메모리 사용량이 포화 상태에 임박할 때마다 자동으로 수거 대상들을 수거(collecting)합니다. 수거된 메모리는 다시 새로운 값을 할당할 수 있는 빈 공간이 됩니다.</div></details>

**출제자 : Stilllee**
> 가비지 컬렉터는 프로그래밍에서 메모리 관리를 자동화하는 시스템으로, 다음과 같이 작동합니다
>
**1. 참조 카운트**
프로그램 내 각 데이터 객체에는 그 객체의 주소를 참조하는 변수의 수를 나타내는 '참조 카운트'가 있습니다. 변수나 다른 데이터 구조가 객체를 참조할 때마다 이 카운트는 증가하고, 참조가 해제되면 감소합니다.
 >  
**2. 수거 대상 식별**
참조 카운트가 0이 된 메모리 주소, 즉 더 이상 어떤 변수나 객체에 의해 참조되지 않는 데이터는 가비지 컬렉터의 수거 대상이 됩니다.  이것은 해당 데이터가 더 이상 필요하지 않다는 것을 의미합니다.
>    
**3. 메모리 수거 및 재할당**
가비지 컬렉터는 이러한 '수거 대상' 메모리를 자동으로 찾아내어 해제합니다. 수거된 메모리는 그 후 다시 프로그램에 의해 새로운 데이터를 저장할 수 있는 빈 공간으로 재활용됩니다.
>    
**4. 자동화 및 최적화**
가비지 컬렉터는 런타임 환경에 따라 자동으로 작동합니다. 일반적으로 메모리 사용량이 포화 상태에 임박하거나 특정 시점에 도달했을 때 활성화되어, 메모리를 효율적으로 관리하고 시스템의 안정성을 유지합니다.
>
이러한 방식으로 가비지 컬렉터는 프로그램의 메모리 관리를 자동화하고 최적화하여, 개발자가 메모리 관리에 대해 걱정할 필요를 줄여줍니다.

<br>

---

<br>

### 2\. [null과 undefined](https://github.com/Coding-Village-Protector/core-js/issues/2)

####  null과 undefined는 모두 값이 "없음" 을 나타내지만 사용되는 상황과 의미에는 약간의 차이가 있는데요. 이 부분에 대해 설명해주세요.

<details data-node-type="hn-details-summary"><summary>eeeyooon</summary><div data-type="detailsContent">
둘 다 "없음"을 나타내기 위해 사용됩니다. undefined는 어떤 변수에 값이 존재하지 않을 경우를 의미하고 null은 사용자가 명시적으로 "없음"을 표현하기 위해 대입한 값입니다. <br> 
undefined는 오직 "값을 대입하지 않은 변수에 접근하고자 할 때 자바스크립트 엔진이 반환해주는 값"으로만 존재하도록 직접 undefined를 할당하지 않을 것을 권장합니다.
<br>
추가로 null은 typeof null이 object이므로, 어떤 변수의 값이 null인지 undefined인지를 판별하기 위해서는 동등 연산자가 아닌 일치 연산자를 써야 정확히 판별할 수 있습니다.
</div></details>
<details data-node-type="hn-details-summary"><summary>lulla-by</summary><div data-type="detailsContent">
둘 다 데이터가 존재하지 않음을 위해 사용합니다. 다만 undefined는 사용자가 명시적으로 undefined라는 값을 할당할 수도 있지만 보통 값이 존재하지 않을 때 자바스크립트 엔진이 자동으로 부여하는 경우가 있습니다. 반면에 null은 개발자가 해당 데이터가 비어있음을 의도적으로 표기하기 위해 사용합니다.
<br>
<br>
비어있음을 명시적으로 사용하고 싶을 경우에는 null을 사용하는 것이 권장됩니다.
</div></details>
<details data-node-type="hn-details-summary"><summary>sryung1225</summary><div data-type="detailsContent">
<li>undefined : 사용자가 명시적으로 undefined라는 값을 할당할 수도 있지만 혼란을 방지하기 위해 어떤 변수에 값이 존재하지 않는 경우로 사용합니다.</li>
<li>null : 사용자가 명시적으로 '없음'을 표현하기 위해 대입한 값입니다.</li>
</div></details>
<details data-node-type="hn-details-summary"><summary>Stilllee</summary><div data-type="detailsContent">
<b>undefined</b>
<li>변수가 선언만 되고 값이 할당되지 않았거나, 존재하지 않는 객체 프로퍼티나 함수 반환값에 자동으로 할당됩니다.</li>
<li>'값이 아직 정의되지 않음'을 의미합니다.</li>
<b>null</b>
<li>개발자가 명시적으로 '값이 없음'을 표시할 때 사용합니다.</li>
<li>주로 참조해야 할 객체가 없음을 나타낼 때 사용되며, '값이 의도적으로 비어있음'을 의미합니다.</li>
</div></details>

**출제자 : chaehaeun**
> undefined의 사용과 의미
- **자동 할당**:변수를 선언했지만 값을 할당하지 않았을 때, 자동으로 undefined가 할당. 변수가 메모리에는 존재하지만, 아직 명확한 값을 갖지 않았음을 나타냄
- **함수 반환값**: 반환값 없이 종료된 함수의 결과는 undefined임. 함수에서 return 문을 생략하면, 자동으로 undefined를 반환.
- **존재하지 않는 속성**: 객체에서 정의되지 않은 속성에 접근하려고 할 때 undefined를 받음. 속성이 객체에 존재하지 않음을 의미.
>
null의 사용과 의미
- **의도적인 '값 없음'**: null은 개발자가 변수에 '값이 없음'을 명시적으로 할당하기 위해 사용. 이는 변수가 '아무 것도 가리키고 있지 않음'을 의도적으로 나타내고자 할 때 쓰임.
- **객체의 부재를 나타낼 때**: 함수가 객체를 반환할 것으로 예상되지만, 어떤 조건으로 인해 반환할 객체가 없을 때 null을 반환하여 객체의 부재를 나타냄.

<br>

---

<br>

### 3\. [변수와 식별자](https://github.com/Coding-Village-Protector/core-js/issues/3)

#### 변수와 식별자의 차이는 무엇인가요?
보통 변수와 식별자를 혼용하는 경우가 많습니다. 식별자라라고 해야 할 곳에 변수를, 변수라고 해야 할 곳에 식별자를 쓰는 식으로 말이죠. 혼용이 가능한 이유는 대부분의 경우에 문맥에 따라 무엇을 말하고자 하는지를 유추할 수 있기 때문이지만 둘의 차이를 모른다면 혼란스러울 수 있습니다.

이때, 변수와 식별자의 차이는 무엇일까요?

<details data-node-type="hn-details-summary"><summary>lulla-by</summary><div data-type="detailsContent">
변수: 변수는 '변할 수 있는 수'이지만 컴퓨터 용어로는 '변할 수 있는 무언가'를 뜻합니다. 여기서 무언가는 데이터를 뜻하며 결국 숫자, 문자열, 객체 , 배열 등 변할 수 있는 데이터를 말합니다.
<br>
<br>
식별자: 식별자는 어떠한 데이터를 식별하는 사용하는 이름으로, 즉 변수명을 뜻합니다.
</div></details>
<details data-node-type="hn-details-summary"><summary>chaehaeun</summary><div data-type="detailsContent">
변수 : 숫자, 문자열, 객체, 배열 등 변경 가능한 데이터가 담길 수 있는 공간을 뜻합니다.
<br>
식별자 : 데이터를 구분하기 위해 이용되는 이름을 말합니다. 변수의 경우 변수명에 해당합니다.
</div></details>
<details data-node-type="hn-details-summary"><summary>sryung1225</summary><div data-type="detailsContent">
변수(variable) 는 변할 수 있는 데이터를 말하고, 식별자(identifer) 는 어떤 데이터를 식별하는 데 사용하는 이름, 즉 변수명을 말합니다.
</div></details>
<details data-node-type="hn-details-summary"><summary>Stilllee</summary><div data-type="detailsContent">
변수 : 변할 수 있는 데이터를 뜻합니다.
<br>
식별자 : 어떤 데이터를 식별하는데 사용하는 이름, 즉 변수명을 뜻합니다.
</div></details>

**출제자 : eeeyooon**
> 변수는 “변할 수 있는 수”입니다. 여기서 수는 숫자를 의미하기도 하지만, 값이 반드시 숫자여야 하는 것은 아닙니다. 컴퓨터 용어로 쓸 때는 “변할 수 있는 무언가”라는 명사로 확장시켰습니다. 여기서 무언가는 데이터를 말합니다. 식별자는 어떤 데이터를 식별하는 데 사용하는 이름, 즉 변수명입니다.
>
자세히 말하자면, 변수는 어떤 값을 저장하기 위한 메모리 공간이나 그 공간을 식별하기 위한 이름을 의미합니다. 식별자는 변수나 함수, 클래스 이름과 같이 메모리 상의 어떤 값을 구별하여 식별할 수 있는 고유한 이름을 의미합니다. 식별자는 특정 값이 아닌 그 값이 존재하는 메모리 주소를 기억하고 있습니다. 자바스크립트에서 식별자는 문자, 숫자, 언더스코어, 달러 기호로 사용할 수 있습니다.
```tsx
var a;
```
주소 | 1002 | 1003
-- | -- | --
데이터 |   | 이름 : a
값 : |   |  
위와 같이 변수를 할당하면 컴퓨터는 메모리에서 비어있는 공간 하나를 확보합니다. 임의로 그 공간을 1003번으로 지정했을 때, 이 공간의 이름이자 식별자가 “a”가 됩니다. 여기까지가 변수 선언 과정입니다. 이후 사용자가 a에 접근하고자 하면 컴퓨터는 메모리에서 a 라는 이름을 가진 주소를 검색해 해당 공간에 담긴 데이터를 반환할 것입니다.

<br>

---

<br>

### 4\. [데이터 복사](https://github.com/Coding-Village-Protector/core-js/issues/5)

#### 참조형 데이터의 복사 이후 복사한 변수의 프로퍼티를 변경할 경우 발생할 수 있는 문제와 해결 방법을 설명해주세요.
기본형 및 참조형 데이터의 복사는 할당 과정 중에 생기는 차이가 있습니다. 이러한 차이로 기본형 데이터와 참조형 데이터는 복사 과정 이후 동작에서도 큰 차이가 발생하는데요.

만약 참조형 데이터의 복사 이후 복사한 변수의 프로퍼티를 변경할 경우 발생할 수 있는 문제와 해결 방법을 설명해주세요.
<details data-node-type="hn-details-summary"><summary>eeeyooon</summary><div data-type="detailsContent">
중첩된 객체에서 참조형 데이터가 저장된 프로퍼티를 복사할 때 그 주솟값만 복사가 되면 해당 프로퍼티에 대해 원본과 사본이 모두 동일한 참조형 데이터의 주소를 가리키게 된다. 이렇게 되어버리면 사본을 바꾸면 원본도 바뀌고, 원본을 바꾸면 사본도 바뀌는 문제가 발생할 수 있다. 이러한 문제가 생기지 않게 하기 위해선 참조형 데이터가 있을 때마다 그 내부의 프로퍼티 복사도 재귀적으로 수행하는 깊은 복사를 하는 것을 권장한다. 이 외에도 간단하게 객체를 JSON 문법으로 표현된 문자열로 전환했다가 다시 JSON 객체로 변경하는 방법이 존재한다.
</div></details>
<details data-node-type="hn-details-summary"><summary>chaehaeun</summary><div data-type="detailsContent">
할당으로 복사한 두 객체는 메모리 상으로 같은 주소값을 참조하고 있기 때문에 복사된 객체의 프로퍼티를 변경할 경우 원본 객체의 프로퍼티도 함께 변경되는 현상이 일어납니다.<br>
이 문제가 발생하지 않기 위해서는 객체의 얕은 복사 또는 깊은 복사를 통해 별도의 객체를 생성해주어야 됩니다.
</div></details>
<details data-node-type="hn-details-summary"><summary>sryung1225</summary><div data-type="detailsContent">
참조형 데이터의 복사 이후 복사한 변수의 프로퍼티를 변경하면,<br>
원본과 사본이 모두 동일한 참조형 데이터의 주소를 참고하고 있어 원본 변수의 프로퍼티도 같이 변경되는 문제가 발생한다.<br>
해결 방법으로 깊은 복사 적용이 있다. 내부의 프로퍼티를 직접 복사하는 식으로 깊은 복사를 적용해 위의 얕은 복사가 일으키는 문제를 해결할 수 있다.
</div></details>
<details data-node-type="hn-details-summary"><summary>Stilllee</summary><div data-type="detailsContent">
<h3>어떤 문제가 발생하는가?</h3>
<p>참조형 데이터를 복사할 때, 복사된 데이터는 원본 데이터와 같은 메모리 주소를 참조한다.</p>

<p>복사된 데이터의 프로퍼티를 변경하면, 그 변경사항이 동일한 메모리 주소를 참조하는 원본 데이터에도 반영되기 때문에 원본 데이터가 변경되거나 훼손될 수 있다.</p>

<h4>예제 2.</h4>
<pre><code class="language-tsx">
var user = {
  firstName: "Woodstock",
  lastName: "Lee"
};

var copyUser = function (user, newName) {
  var newUser = user;
  newUser.firstName = newName;
  return newUser;
}

var user2 = copyUser(user, "Esther")

console.log(user.firstName, user.lastName); // Esther Lee
console.log(user2.firstName, user2.lastName); // Esther Lee
</code></pre>

<h4>예제 2.</h4>
<pre><code class="language-tsx">
var user = {
  firstName: "Woodstock",
  lastName: "Lee",
  personalInfo: {
    mbti: "ISTJ",
    bloodType: "B"
  },
};

// 얕은 복사
var user2 = {...user};

// user2의 중첩된 객체를 변경
user2.personalInfo.mbti = "ESTJ";

console.log(user.personalInfo.mbti); // ESTJ
console.log(user2.personalInfo.mbti); // ESTJ
</code></pre>

<h3>해결방법</h3>
<h4>1. 새로운 객체를 반환하여 불변성을 보장한다.</h4>
<p>원본 객체를 변경하지 않고 새로운 프로퍼티 값을 가진 새 객체를 생성하여 원본 객체를 보호한다.</p>
<pre><code class="language-tsx">
var user = {
  firstName: "Woodstock",
  lastName: "Lee"
};

var changeFisrtName = function (user, newName) {
  return {
   firstName: newName,
   lastName: user.lastName,
  }
}

var user2 = changeFirstName(user, "Esther")

console.log(user.firstName, user.lastName); // Woodstock Lee
console.log(user2.firstName, user2.lastName); // Esther Lee
</code></pre>

<h4>2. 깊은 복사를 한다.</h4>
<p>객체의 모든 중첩된 프로퍼티까지 깊게 복사하여, 복사된 객체가 원본 객체와 완전히 독립적이게 만든다.</p>
<pre><code class="language-tsx">
var user = {
  firstName: "Woodstock",
  lastName: "Lee",
  personalInfo: {
    mbti: "ISTJ",
    bloodType: "B"
  },
};

var deepCopy = function (obj) {
  // obj가 기본형 데이터일 경우 깊은 복사가  필요 없음
  if (typeof obj !== 'object' || obj === null) {
    return obj; // obj를 그대로 반환
  }

  var copy = {};

  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }
  return copy;
}

var user2 = deepCopy(user);
user2.personalInfo.mbti = "ESTJ";

console.log(user.personalInfo.mbti); // ISTJ
console.log(user2.personalInfo.mbti); // ESTJ
</code></pre>
</div></details>

**출제자 : lulla-by**
> 데이터의 복사는 값 그 자체를 복사하는 것이 아닌 그 값을 가지고 있는 주솟값을 복사하기 때문에 자바스크립트의 모든 데이터 타입은 참조형 데이터입니다. 다만, 기본형 데이터의 복사는 주솟값을 복사하는 과정이 한번만 진행되는 반면 참조형은 한 단계를 더 거친다는 차이가 있습니다.
>
참조형 데이터의 복사는 프로퍼티를 복사할때 그 주솟값만 복사하게 되므로 해당 프로퍼티에 대하여 원본과 복사본 모두 같은 주소를 바라보게 됩니다. 이때 복사본의 프로퍼티를 변경하게 되면 동일한 주소값을 바라보기 때문에 원본이 훼손됩니다.
>
여기서 등장하는 개념이 얕은 복사와 깊은 복사입니다. 얕은 복사는 아래 단계의 값만 복사하는 방법이고 깊은 복사는 내부의 모든 값들을 하나하나 복사하는 방법입니다.
>
복사본을 사용하여 완전히 새로운 데이터를 생성하고 싶을 때 참조형에서는 그 내부의 프로퍼티들을 다시 복사하는 과정이 필요합니다. 이 과정에서 가장 유명한 것은 재귀 함수를 사용하여 깊은 복사를 수행하는 방법입니다.
```js
const copyObjectDeep= function (target){
const result = {}
>
if(typeof target === "object" && target !== null ){
>
for(const prop in target){
result[prop] = copyObjectDeep(target[prop]);
}
}else{
result = target;
}
>
return result;
};
```
target 이 객체인 경우에는 내부 프로퍼티를 순회하며 copyObjectDeep함수를 재귀적으로 호출합니다. 객체가 아닌경우에는 target을 그대로 지정하여 이 함수를 사용하여 복사한 사본은 원본과 사본이 서로 완전히 다른 객체를 참조하여 프로퍼티를 변경하는 경우에도 원본과 사본에 훼손이 발생하지 않습니다.
>
또한 깊은 복사를 매우 간단하게 수행하는 방법으로 JSON을 사용하는 방법이 있습니다. JSON.stringify()을 사용하여 JSON문법으로 표현된 문자열로 전환한 뒤 JSON.parse()를 사용하여 다시 JSON 객체로 바꾸는 방법입니다. 단순하면서 잘 동작한다는 큰 장점이 있지만 메서드나 숨겨진 프로퍼티등과 같이 JSON으로 변경할 수 없는 프로퍼티는 모두 무시한다는 단점이 있습니다. 따라서 httprequest를 통해 받은 데이터를 저장한 객체를 복사하거나 순수한 정보만 다룰 때 사용하기를 권장합니다.

<br>

## 추가 논의
### [스프레드 연산자와 깊은 복사](https://github.com/Coding-Village-Protector/core-js/issues/6)
교재에서는 다루지 않지만 스터디 과정에서 스프레드 연산자에 대한 이야기가 나왔다.

스프레드 연산자를 사용한 깊은 복사는 모든 참조형 데이터에 적용할 수 있는 것은 아니며, depth가 1단계인 참조형 데이터에서만 가능하다.

스프레드 연산자는 원본 객체와 새로운 객체 사이의 참조 관계를 생성하기 때문이다.

따라서, depth가 2단계 이상인 데이터를 복사할 때는 스프레드 연산자를 사용하지 않고, 다른 방법을 사용해야 한다.

#### 예제 1
```js
const obj1 = { a: 1, b: 2};
const obj2 = { ...obj1 };

obj2.a = "a";
```
![](https://velog.velcdn.com/images/orodae/post/75e479f2-765e-4c3e-9450-ca78bfdf6c29/image.png)

depth가 1단계인 경우에는 복사본의 데이터를 변경해도 데이터가 이미 완전히 다른 주소를 바라보기에 깊은 복사가 진행된 것을 확인할 수 있다.
<br>

#### 예제 2
```js
const objDeep1 = { a:1, data: { b: "b", c: "c"} };
const objDeep2 = { ...objDeep1 };

objDeep2.data.c = "changed!";
```
![](https://velog.velcdn.com/images/orodae/post/fcbd16d5-55fd-4174-babd-22bafd987669/image.png)

반면 위와 같이 depth가 2단계 이상인 객체의 복사본 내부의 참조 데이터의 값을 변경하면 원본도 같이 변경된다.
<br>

물론, 다음과 같이 내부 참조형 데이터를 한번 더 전개하는 로직을 추가해 깊은 복사를 구현하는 방법이 있지만, 그 이상의 depth에서 같은 방법을 사용하는 것은 권하지 않는다.
```js
const objDeep1 = { a:1, data: { b: "b", c: "c"} };
const objDeep2 = { ...objDeep1 };
objDeep2.data = { ...objDeep2.data };

objDeep2.data.c = "changed!";
```
![](https://velog.velcdn.com/images/orodae/post/d723486f-f3f5-42d8-832a-ea117a8e99e1/image.png)

객체의 복잡도가 높아질수록, 객체의 크기가 커질수록 성능 이슈와 메모리 문제가 발생할 수 있기 때문이다.

위와 같은 이유로 스프레드 연산자를 사용한 깊은 복사는 depth가 1단계인 참조형 데이터에서 사용하는 것이 좋다.
