들어가며

개발하며 아티클을 읽다보면 한번 쯤은 보게되는 단어가 있다.
깊은 복사 (Deep Copy), 얕은 복사 (Shallow Copy) 가 그 주인공이다.

이거 이름만 봐도 궁금증이 생기지 않는가??
아니 복사면 복사지 대체 깊은 복사 는 뭐고 얕은 복사 는 뭘 뜻하는걸까?

이번에는 이 두개를 한번 알아보도록 하자.


사전지식

사전 지식.......?? 😩

깊은 복사얕은 복사를 알기 전에 우선 몇 가지 사전지식이 필요하다.
이걸 모르면 반 쪽 짜리 지식이라고 할 수 있다.

(그리고 모르면 자꾸 까먹으니 알아야 한다)


데이터의 저장

데이터 저장?? 이건 왜 알아야 하는거죠?? 🙄

자 한번 생각해보자.
어디에 어떻게 저장되는지도 모르는데, 그걸 어떻게 복사하는지 완벽히 이해할 수 있을까?

당연히 불가능하다. 그건 그냥 면접 답변 용으로 외우는 정도이지, 조금만 깊게 가면 알 수 없다.

때문에 Javascript에서 데이터가 어떻게 저장되었는지 부터 알아보도록 하자.
(굉장히 러프하게 작성한 내용이므로, 자세한 내용은 구글링을 통해 공부해보자)

메모리에 저장

Javascript 에서는 변수 을 할당하는 식으로 코드를 작성한다.

let newValue = 100;

근데 이 값은 어디에 어떻게 저장되는 걸까?
그건 바로 메모리 영역에 저장을 하게된다.

쉽게 그림으로 이해하자면 아래와 같다.

(실제로 메모리 주소가 이렇게 잡히지는 않는다. 참고용으로 이렇다~ 정도로 생각해주자)

메모리 주소 1000에 변수의 이름이 저장되었고, 그 변수의 데이터는 메모리 주소 4001에 있다고 되어있다.
이 때 메모리주소 4001에 가보면 아까 우리가 할당 한 데이터 100을 보게 된다.

그럼 객체(Object)의 저장 같은 경우는 어떻게 될까?

let newObject = {
  name:'himprover',
  money:0,
}

대략 이런식으로 저장이 된다.
여기서 핵심은 데이터는 메모리 상에 저장되고, 그 주소값을 저장 한다는 점이다.



이제 본론으로

여기까지 읽었다면 눈치 빠른 사람은 이제 느낌이 좀 올거다.

그럼 대충...머... 복사할때 주소값 머 그런거에 따라서... 깊고 얕은 그런건가...? 😏

이런 의문이 들었다면 같이 얕은복사, 깊은복사를 정복하러 가보자!


원시값, 참조값의 복사

엥??? 갑자기 원시값 참조값이요? 😫

Javascript에서 값은 원시값과 참조값으로 나누어 진다.

원시값 종류

  • Number (숫자)
  • String (문자)
  • Boolean (true/false)
  • NULL (비어있음)
  • undefined (정의안됨)
  • Symbol (심볼)

참조값 종류

  • Object (객체)

Symbol (심볼)

2022.12.05. 수정, Symbol은 원시값입니다! (feedback: gomiseki님 감사합니다.)

어려우면 그냥 간단하게 생각해서 Object 아니면 다 원시값이라고 생각해보자.

아무튼 원시값과 참조값의 경우 복사하는 과정에서 차이점이 나타난다.


원시값의 복사

원시값을 복사하면 주소값이 아닌 데이터 자체를 복사한다.
이게 무슨말인지 그림을 보며 이해해보자.

let first = 'hi'
let second = first;

그림을 보면 second가 바라보는 메모리 주소는 first4001이 아닌 4002에 새로 만들어주었다.

아니 당연한거 아닌가요? 이거 뭐 당연한 얘기 같은데... 😑

과연 그럴까? 이번엔 객체의 복사를 알아보자.


참조값의 복사

얕은 복사

참조값을 복사하면 기본적으로 얕은 복사로 진행이 된다.
여기서 얕은 복사데이터 자체가 아닌 메모리 주소 만 복사한다는 것이다.

이것도 그림을 통해 알아보자.

let student1 = {
  name:'himprover',
  money:0,
}
let student2 = student1;

어라???? 🤨

원시값의 복사와 달리 데이터를 새로 저장하지 않고 student1의 메모리 주소 4001을 그대로 가져와 사용했다.

얕은 복사란 데이터를 복사하는 것이 아닌, 데이터의 메모리 주소 복사하는 것을 뜻한다.


깊은 복사

얕은 복사가 메모리 주소를 복사하는 거니까, 깊은 복사는 데이터를 복사하는 거겠네요 😆

맞다. 깊은 복사는 메모리를 복사하는 것이 아닌 원시값 복사 처럼 데이터를 복사하는 것이다.



근데 이 두개 왜 나눠짐?

이쯤 되면 이런 의문이 들 것이다.
원시값 처럼 데이터를 복사하면 되는데 굳이 얕은 복사를 만들어 기본 설정으로 해 둔 이유는 뭘까?
(왜 굳이 우리 하나 더 공부하게 했을까)

핵심만 말하자면 때문이다.


생각해보자, 실제 서비스의 코드에서 객체는 아까 그 예제처럼 크기가 작지 않다.
만약 큰 객체를 원시값처럼 복사하면 속도, 저장소 크기 두 가지의 문제가 생긴다.

속도 - 데이터가 많으니 복사하는 데 시간이 오래걸릴 거고,
저장소 크기 - 데이터를 다 다시 저장하니 저장소를 더 쓰게된다.

그럼 결국 장비의 성능을 올려야 하고 그건 돈이 더 들게 된다.
(깊은 복사 때문에 램 사고 CPU 사면 좀 억울할거다)

이 때문에 최대한 최적화해서 사용하기 위해 얕은 복사를 만들어 낸 것이다.


얕은 복사의 문제점

조금 전 얕은 복사의 탄생 이유에 대해 설명을 했다.
그럼 그 다음은 뭘까?

당연히 깊은 복사의 탄생 이유이다.
얕은 복사가 완벽하면 깊은 복사라는 것 자체가 나올리가 없지 않은가?

지금까지 공부한 내용으로 얕은 복사의 문제점이 뭘지 한번 생각해보자.

문제점은 바로 같은 주소를 공유한다는 점

같은 주소를 사용하게 되면, 어느 한 객체에서 값을 수정했을 때 다른 객체도 같이 수정되게 된다.

왜냐? 같은 주소를 사용하고 있으니까.

예를들어 학생1의 형식만 가져와서 학생2를 만든 다음에, 학생2의 이름에 맞게 값을 변경해주면 학생1의 값도 변경되게 된다.

let student1 = {
  name:'himprover'
}
let student2 = student1;
student2.name = 'joohyun';

(궁금하면 한번 개발자도구 console에 똑같이 쳐보자)


깊은 복사 하는 법

아하 깊은 복사는 그래서 있군요... 그럼 어떻게 하나요? 😀

링크참고 :)



정리

이제 얕은 복사, 깊은 복사 얘기가 나왔을 때 헷갈리지 말고 당당하게 말할 수 있다!
얕은 복사는 주소만 깔짝 복사하는 거고 깊은 복사는 데이터 자체를 복사하는 거다.

이 내용에서 핵심은 데이터가 어떻게 저장되는지, 왜 얕은복사, 깊은복사가 나누어졌는지 이 두가지라고 할 수 있다.

한번 직접 Javascript로 만들어보며 완벽히 이해해보자!


  • Javascript에서 데이터는 메모리 상에 저장되고, 주소로써 표현함
  • 얕은 복사는 데이터의 메모리 주소만 복사함
  • 깊은 복사는 데이터 자체를 복사해서 새로 저장함
  • 객체를 복사할때는 얕은 복사가 기본적으로 진행 됨
  • 얕은 복사, 깊은 복사 는 각각 필요한 곳에 맞게 잘 사용해야 함

+ 읽어주셔서 감사합니다.
+ 오타, 내용 지적, 피드백을 환영합니다. 많이 해주실 수록 제 성장의 밑거름이 됩니다.
profile
반갑습니다. 프론트엔드 개발자 황주현 입니다. 🤗

2개의 댓글

comment-user-thumbnail
2022년 12월 2일

안녕하세요, 원시 값 자료를 찾다가 보게되었는데 혹시 symbol을 참조형으로 소개하는 레퍼런스가 있나요?
MDN에서는 원시값으로 소개하고있어서요! 글 잘 봤습니다~

1개의 답글