오늘은 어제 하던 개인과제를 일단락하고 다시금 자바스크립트 집중 학습을 시작했다. 꼭 알아야해서 배우고 있는 것이겠지만 이제 슬슬 학습이 버거워지는 시점이다.
데이터 타입(심화)
먼저 데이터 타입(심화)를 정리해보자. 데이터 타입(심화)는 데이터의 타입이 기본형/참조형으로 갈린다는 것을 명시했다. 이러한 데이터 타입은 저장 방식과 불변성 여부로 갈리는데, 표로 정리하면 아래와 같다.
데이터 타입 | 기본형 | 참조형 |
예시 | 숫자, 문자, 불리언 등 | 배열, 객체 등 |
저장 방식 | 값이 담긴 => 주소값을 저장 |
값이 담긴 => 주소값을 저장한 묶음을 => 가리키는 주소값을 저장 |
불변성 여부 | 불변성 O | 불변성 X |
이러한 구조를 다시금 표로 정리하자면 이렇게 된다.
데이터 저장 공간 | 저장 공간 1 | 저장 공간 2(불변성O) | 저장 공간 3(불변성X) (변조 가능) |
기본형 | [변수명, 저장 공간 2의 주소] | 데이터 | X |
참조형 | [변수명, 저장 공간 3의 주소] | 데이터1, 데이터2, 데이터3, 데이터4 | [0, 데이터 1의 주소],[1, 데이터 2의 주소], [2, 데이터 3의 주소], [3, 데이터 4의 주소] |
위 표를 보면 기본형은 불변성을 가진 저장 공간에만 데이터를 저장했기 때문에 불변성을 가지고 있지만, 참조형은 불변성을 가지지 않은 저장 공간에도 데이터를 저장했기 때문에 불변성을 가지지 않았다는 것을 알 수 있다.
이러한 데이터 저장 구조는 자유로운 데이터 변환과 메모리의 효율적 관리를 위한 것인데,
먼저 자유로운 데이터 변환을 살피자면, 만약 저장 공간을 하나만 가지고 있을 경우,
데이터를 변환할 때마다
=> 해당 데이터가 가지는 메모리 값이 바뀌면서
=> 다른 데이터들과 저장 공간을 두고 충돌하는 경우가 있을 수 있다.
하지만 이와 같이 저장 공간을 여러 개 두고 주소를 불러오면,
데이터를 변환하지 않고 새로운 데이터를 생성함
=>새로운 데이터의 주소를 가져옴 으로써 데이터들 간의 충돌을 줄일 수 있다.
다음으로 메모리의 효율적 관리 측면에서 보자면, 이렇게 데이터를 직접 저장하지 않고 주소로 데이터를 저장하는 경우 같은 값을 여러 번 사용해야 할 때 이득을 볼 수 있다.
실질적으로 데이터를 저장하는 저장공간2는 변조가 불가능하므로 부담없이 몇 번이고 값을 가져다 쓸 수 있는데,
하나의 데이터를 저장하는 데에 필요한 메모리가 저장공간1=2byte, 저장공간2=8byte일 때,
같은 데이터 값을 1000번 저장하는 데에 필요한 메모리는 (2byte*1000)+8byte로
저장공간2의 메모리 부담량이 없어져서 실질적으로 필요한 메모리 양이 줄어든다.
표를 보면 이렇다.
하나 저장 | 1000개 저장 | 차(아낄 수 있는 메모리 양) | |
저장공간이 1개 | 10btye | 10000byte | 7992byte |
저장공간이 2개 | 2+8byte | (2000+8)byte |
또 이러한 데이터들은 byte를 단위로 가진 메모리로 구성되어 있고, 이러한 각 데이터 형태마다 필요한 메모리 규격의 크기는 차이가 있다(문자:1,2byte, 숫자:8byte). 자바스크립트에서는 데이터 주소의 형태로 값을 저장하면서 각 데이터의 메모리 규격 차이로 인해 발생할 수 있는 문제를 줄인 것이다.
얕은 복사/깊은 복사
다음은 복사이다. 처음 복사라는 개념을 알게 되었을 때 복사가 복사지 왜 이렇게 나뉘어 있는지 모르겠다는 생각을 했다. 하지만 데이터에 대해 공부하고 난 뒤 이것이 코딩에서 굉장히 중요한 영역 중 하나라는 것을 알게 되었다. 특히 참조 데이터 형태에서 어떤 복사를 사용했나로 고려해야 하는 것들이 달라진다.
먼저 간단한 일반 복사를 살펴보자. 일반 복사는 변수명 = 변수명1 의 형태로 데이터를 복사한다. 이 경우 변수명과 변수명1은 같은 주소값 묶음을 가지고 있으므로 어느 한 쪽에서 주소값 묶음에 접근해서 주소(데이터)를 바꾸어버리면 다른 한 쪽의 주소(데이터)도 바뀌어 버린다. 표로 정리하자면 이렇다.
일반 복사 | 저장공간1 | 저장공간2 | 저장공간3 | 변수명 1에서 저장공간3에 접근해서 2의 데이터 주소 변조 |
저장공간1 | 저장공간2 | 저장공간3 |
변조 여부 | X | O | X | O | |||
변수명 | 변수명 3의 주소 |
데이터 | 3 주소 2의 데이터 주소 |
변수명 3의 주소 |
데이터, 데이터1 | 3 주소 2의 데이터1 주소 |
|
변수명1 | 변수명1 3의 주소 |
변수명1 3의 주소 |
즉 일반 복사란 변수명과 변수명1이 같은 데이터를 공유하고 있는 상태를 뜻한다.
얕은/깊은 복사는 이러한 문제가 일어나는 것을 막을 수 있는 복사 방식으로, 저장공간3에 새로운 데이터 주소를 생성하도록 한다.
얕은/깊은 복사 |
저장공간1 | 저장공간2 | 저장공간3 | 변수명 1에서 저장공간3에 접근해서 2의 데이터 주소 변조 |
저장공간1 | 저장공간2 | 저장공간3 |
변조 여부 | X | O | X | O | |||
변수명 | 변수명 3의 주소 |
데이터 | 3 주소 2의 데이터 주소 |
변수명 3의 주소 |
데이터, 데이터1 | 3 주소 2의 데이터 주소 |
|
변수명1 | 변수명1 3의 주소1 |
3 주소1 2의 데이터 주소 |
변수명1 3의 주소1 |
3 주소1 2의 데이터1 주소 |
이렇게 이전에 일반 복사에서 변조 결과가 공유되던 것과 다르게 변수명1이 따로 가진 저장공간3의 데이터만 변조된 것을 확인할 수 있다.
다만 이렇게 얕은/깊은 복사를 하려면 조금 번거로운 과정을 거쳐야한다.
먼저 얕은 복사를 살펴보자. 아래는 객체를 복사하는 함수이다.
이렇게 빈 객체 선언 => for문을 통해 새 객체 생성 => 새 객체 반환
의 과정을 거치는 함수를 사용하면 쉽게 얕은 복사를 할 수 있다.
다만 이러한 얕은 복사는 복사하려는 참조 데이터가 다시 내부에 참조 데이터를 가지고 있는 것을 복사할 수 없다.
때문에 이러한 복잡한 형태의 데이터를 복사하기 위해서는 깊은 복사를 해야한다.
아래가 재귀적 수행을 통해 깊은 복사를 한 것이다.
먼저 빈 객체 result를 선언하고
for문을 이용하여 새 객체를 생성하는 동시에
이전에 얕은 복사에서는 없었던 재귀적 수행
result[prop] = copyObjectDeep(target[prop]);
과 함께 if else문을 사용하여 재귀적 수행이 언제 끝날지 결정하고 돌려서
객체를 모두 복사한 뒤
새 객체가 된 result를 반환했다.
즉
는 위의 이미지의 구조를 갖게 된다.
'til' 카테고리의 다른 글
개인 과제 2일 차(+1일 차) @코드 정리 (0) | 2024.07.29 |
---|---|
개인 과제 2일 차(完) @데이터 형태와 활용 (0) | 2024.07.26 |
개인 과제 1일 차 @grid, for of, fetch (1) | 2024.07.24 |
자바스크립트 집중 학습 2일 차 @MAP, SET (0) | 2024.07.23 |
자바 스크립트 집중 학습 2일 차 @구조 분해 할당, 객체 함수 (1) | 2024.07.23 |