코어 자바스크립트 | 1. 데이터 타입

🚀·2021년 8월 11일
0

코어자바스크립트

목록 보기
1/3
post-thumbnail

배워도 배워도 배울게 많은 자바스크립트..!!! ...^^
코어 자바스크립트 책을 읽으며 새로 정리해보기 !

시작은 우리가 자주 쓰는 변수, 그리고 변수에 할당하는 여러 데이터 타입에 대해 정리해보자!
(생각보다 뭐가 많다!!😇,,❤️‍🔥)

🌱 데이터 타입의 종류

자바스크립트의 데이터 타입엔 크게 두 가지가 있다. 기본형참조형!!
이 두 데이터 타입엔 각각 무엇이 있을까?

  • 기본형 => 숫자, 문자, 불리언, null, undefined, simbol(ES6추가)
  • 참조형 => 객체, 배열, 함수, 날짜, 정규표현식, Map, WeakMap, Set, WeakSet (ES6추가)등이 있다.

그러면 이 두 가지를 구분하는 기준은?

기본형은 값이 담긴 주솟값을 바로 복제한다.
하지만 참조형은 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복제!! (약간 헷갈리지만 뒤에서 더 봐보자)

또, 기본형은 불변성(immutability)를 띈다. 이 불변성이란 무엇일까???
개념을 정리하면서 알아보자!


🌱 데이터 타입에 들어가기 전 배경지식

메모리와 데이터

컴퓨터는 모든 데이터를 0또는 1로 바꿔 기억한다. 0 또는 1만 표현할 수 있는 하나의 메모리 조각을 비트라고 한다.
메모리는 매우 많은 비트들로 구성돼 있는데, 각 비트는 고유한 식별자를 통해 위치 확인 가능하다.

매우 많은 비트를 한 단위로 묶으면 검색 시간은 줄일 수도 있고 표현할 수 있는 데이터의 개수도 늘어나지만 낭비되는 비트도 생긴다. 자주 사용하지 않는 데이터를 표현하기 위해 빈 공간을 남겨놓기 보다는 표현 가능한 개수에 어느 정도 제약이 따르더라도 크게 문제가 되지 않을 적정한 공간을 묶는 것이 낫다!

이런 고민의 결과로 바이트라는 단위가 생김~🌟
1바이트는 8비트로 구성되어있다. 메모리 용량이 과거보다 월등히 커진 상황에서 등장한 자바스크립트는 상대적으로 메모리 관리에 대한 압박에서 자유로워졌다!
그래서 메모리 공간을 좀 더 넉넉하게 할당했고, 64비트를 확보한다.

모든 데이터는 바이트 단위의 식별자, 더 정확하게는 메모리 주솟값을 통해 서로 구분하고 연결이 가능하다.

식별자와 변수

변수'변할 수 있는 무언가'
식별자'어떤 데이터를 식별하는데 사용하는 이름, 즉 변수명'


🌱 변수 선언과 데이터 할당

변수 선언

var a;

=> 변할 수 있는 데이터를 만든다. 이 데이터의 식별자는 a로 한다

변수란 변경 가능한 데이터가 담길 수 있는 공간 또는 그릇이라 생각하면 편하다!

데이터 할당

let a;  // 변수 a선언
a = 'abc' // 변수 a에 데이터 할당
let a = 'abc' // 변수 선언과 할당을 한 문장으로 표현

어떻게 변수에 데이터를 할당할까?
우리가 생각하기엔 a이름을 갖는 저장소를 만든 뒤 그 값에 'abc'를 바로 할당해 줄거라 생각한다.

하지만 실제로는 해당 위치에 문자열 'abc'를 직접 저장하지는 않는다.
데이터를 저장하기 위한 별도의 메모리 공간을 다시 확보해서 문자열 'abc'를 저장하고 그 주소를 변수 영역에 저장하는 식으로 이뤄진다.

  1. 변수 영역에서 빈 공간(@1003)을 확보
  2. 확보한 공간의 식별자를 a로 지정
  3. 데이터 영역의 빈 공간(@5004)에 문자열 'abc'를 저장
  4. 변수 영역에서 a라는 식별자 검색(@1003)
  5. 앞서 저장한 문자열의 주소(@5004)를 @1003의 공간에 대입.

왜 변수 영역에 값을 직접 대입하지 않고 굳이 번거롭게 한 단계를 더 걸칠까?
이는 데이터 변환을 자유롭게 할 수 있게 함과 동시에 메모리를 더욱 효율적으로 관리하기 위한 고민의 결과이다.

만약 미리 확보한 공간 내에서만 데이터 변환을 할 수 있다면 변환한 데이터를 다시 저장하기 위해서는 '확보된 공간을 변환된 데이터의 크기에 맞게 늘리는 작업'이 선행돼야 할것이다 😣

이처럼 컴퓨터가 처리해야 할 연산이 많아지는 것을 방지하기 위해 변수와 데이터를 별도의 공간에 나누는 것이라 보면된다!

만약 문자열 'abc'의 마지막에 'def'를 추가하라고 하면 컴퓨터는 'abc'가 저장된 공간에 'abcdef'를 할당하는 대산 'abcdef'라는 문자열을 새로 만들어 별도의 공간에 저장하고 그 주소를 변수 공간에 연결한다. 반대로 'abc'의 마지막 'c'를 제거하라고 해도 새로 만든다!
기존 문자열에 어떤 변환을 가하든 상관 없이 🌟무조건 새로 만들어 별도의 공간에 저장🌟한다!


🌱 기본형 데이터와 참조형 데이터

불변값

변수와 상수를 구분하는 성질은 '변경 가능성'이다. 바꿀 수 있으면 변수, 바꿀 수 없으면 상수이다.
변수와 상수를 구분 짓는 변경 가능성의 대상은 변수 영역 메모리이다. 이게 무슨말일까?

우리가 흔히 아는 상수 const는 불변값이라고 생각하는 경우가 많다.
하지만 var, let vs const를 결정짓는 변경 가능성 여부란, 한번 데이터 할당이 이뤄진 변수 영역에 다른 데이터를 재할당할 수 있는지 여부를 말한다.

반면! 불변성 여부를 구분할 때의 변경 가능성의 대상은 🌟데이터 영역 메모리🌟이다.
기본형 데이터 타입은 모두 불변값이다!

let a = 10;
let b = a;
a= a + 5;

순서대로 보면 , a라는 변수에 숫자 10을 할당한다.
컴퓨터는 데이터 영역을 확인하고 , 10이라는 숫자가 없다면 새로운 공간에 10을 저장하고 그 주솟값을 a라는 변수의 값에 할당한다.

그 후, b라는 변수에 a 변수의 값을 할당한다. 즉 a변수의 값인 10의 주솟값을 할당한다.
마지막에 a의 값을 a+5로 변경한다.

console.log(a); // 15
console.log(b);  // 10

분명 a = a + 5로 a의 값을 바꿨기 때문에, a 자체가 15로 변경되고, 그로 인해 b의 값까지 바뀔것 같다!
하지만 그렇지 않다.

처음 10이라는 데이터에 해당하는 @5003의 주소를 @1002@1003에 똑같이 할당한다.
그 후 a = a + 5로 변수의 값을 변경한다.

컴퓨터는 연산을 한 후 15라는 값이 데이터영역에 없기 때문에 새로운 공간에 15를 저장하고 그 주솟값 @5004를 a라는 변수의 값에 재할당한다.

즉 10(@5003)과 15(@5004)는 완전히 별개의 데이터이다.
기존 저장된 10 자체를 15로 바꾸는게 아니라, 15를 찾아서 있으면 재활용하고 없으면 새로 만든다.
마치 값이 변경되는 것처럼 보이지만 한번 만든 값은 가비지컬렉팅을 당하지 않는 한 절대 바뀌지 않는다.
이것이 불변값이며, 기본형 데이터 타입은 모두 불변값이다.

가변값

참조형 데이터의 할당을 먼저 보자!

var obj1 = {
  a:1,
  b:'bbb'
}

  1. 컴퓨터는 우선 변수 영역의 빈 공간(@1002)를 확보하고, 그 주소의 이름을 obj1로 지정한다.
  2. 임의의 데이터 저장 공간(@5001)에 데이터를 저장하려고 보니 여러 개의 프로퍼티로 이뤄진 데이터 그룹이다. 이 그룹 내부의 프로퍼티들을 저장하기 위해 별도의 변수 영역을 마련하고, 그 영역의 주소(@7103~?)를 @5001에 저장한다.
  3. @7103@7104에 각각 a와 b라는 프로퍼티 이름을 지정한다.
  4. 데이터 영역에서 숫자 1을 검색한다. 검색 결과가 없으므로 임의로 @5003에 저장하고, 이 주소를 @7103에 저장한다. 문자열 'bbb'역시 임의로 @5004에 저장하고 이 주소를 @7104에 저장한다.

기본형 데이터와의 차이는 '객체의 변수 영역'이 별도로 존재한다는 점이다. 그림을 보면 객체가 별도로 할애한 영역은 변수 영역일 뿐 '데이터 영역' 은 기존의 메모리 공간을 그대로 활용하고 있다. 데이터 영역에 저장된 값은 모두 불변값이다. 그러나 변수에는 다른 값을 얼마든지 대입할 수 있다. 바로 이 부분 때문에 흔히 참조형 데이터는 불변하지 않다(가변적이다)라고 하는것 !

예제로 다시 한번 살펴보자 !

var obf1 = {
  a:1,
  b:'bbb
};
obj1.a = 2;

obj1의 a프로퍼티에 숫자 2를 할당하려고 한다. 먼저 데이터 영역에서 숫자2를 검색한다. 검색 결과가 없으므로 빈 공간인 @5005에 저장하고, 이 주소를 @7103에 저장한다.
변수 obj1이 바라보고 있는 주소는@5001로 변하지 않았다. 즉 '새로운 객체'가 만들어진 것이 아니라 기존의 객체 내부의 값만 바뀐 것이다.

변수 obj1이 바라보고 있는 주소는 @5001로 변하지 않았다. 즉 '새로운 객체'가 만들어진 것이 아니라 기존의 객체 내부의 값만 바뀐것!!

변수 복사 비교

기본형 데이터와 참조형 데이터를 복사할 때의 차이를 살펴보자

var a = 10;
var b = a;
var obj1 = {c: 10, d:'ddd'}
var obj2 = obj1;

우선 기본형 데이터부터 보자.
1번째 줄에서는 변수 영역의 빈 공간 @1001을 확보하고 식별자를 a로 지정한다. 숫자 10일 데이터 영역에서 검색하고 없으므로 빈 공간 @5001에 저장한 다음, 이 주소를 @1001에 넣었다. 이로써 기본형 데이터에 대한 변수 선언 및 할당이 종료된다.

이제 복사를 해보자.
변수 영역의 빈 공간 @1002을 확보하고 식별자를 b로 지정한다. 이제 식별자 a를 검색해 그 값을 찾아와야 한다. @1001에 저장된 값이 @5001을 들고 좀 전에 확보해둔 @1002에 값으로 대입한다.

참조형 데이터를 보자!
변수 영역에 @1003을 확보해 식별자 obj1로 지정한다. 데이터 영역의 빈 공간 @5002을 확보하고, 데이터 그룹이 담겨야 하기 때문에 별도의 변수 영역 @7103~을 확보해 그 주소를 저장한다. @7103에는 식별자 c를, @7104에는 식별자 d를 입력한 다음, c에 대입할 값 10을 데이터 영역에서 검색한다. @5001에 이미저장돼 있으므로 이 주소를 @7103에 연결하고 문자열인 'ddd'는 데이터 영역의 빈 공간에 새로 만들어서 @7104에 연결한다.

다음으로 복사를 해볼 것인데 변수 영역의 빈 공간 @1004를 확보하고 식별자를 obj2로 지정한다. 이제 식별자 obj1을 검색해 그 값인 @5002를 들고, @1004에 값으로 대입한다.

변수를 복사하는 과정은 기본형 데이터와 참조형 데이터 모두 같은 주소를 바라보게 되는 점에서 동일!
@1001, @1002는 모두 값이 @5001이 됐고, @1003@1004에는 모두 값이 @5002가 되었다. 복사 과정은 동일하지만 데이터 할당 과정에서 이미 차이가 있기 때문에 변수 복사 이후의 동작에도 큰 차이가 발생한다.

  • 변수 복사 이후 값 변경 결과를 봐보자!
var a = 10;
var b = a;
var obj1 = {c:10, d:'ddd'}
var obj2 = obj1;
b = 15;
obj2.c = 20;

var a = 10;
var b = a;
var obj1 = {c:10, d:'ddd'}
var obj2 = obj1;
b = 15;
obj2.c = 20;
//
console.log(obj1) // {c:20, d:'ddd'}
console.log(obj2) // {c:20, d:'ddd'}
console.log(a) // 10
console.log(b) // 15

기본형 데이터를 복사한 변수 b의 값을 바꿨더니 @1002의 값이 달라진 반면, 참조형 데이터를 복사한 변수 obj2의 프로퍼티의 값을 바꾸었더니 @1004의 값은 달라지지 않았다.
즉 변수 a와 b는 서로 다른 주소를 바라보게 됐으나, 변수 obj1과 obj2는 여전히 같은 객체를 바라보고 있는 상태이다.

a !== b
obj1 === obj2

이 결과가 바로 기본형과 참조형 데이터의 가장 큰 차이점이다.

대부분의 자바스크립트 책에서 '기본형은 값을 복사하고 참조형은 주솟값을 복사한다'고 설명하고 있지만, 사실은 어떤 데이터 타입이든 변수에 할당하기 위해서는 주솟값을 복사해야 하기 때문에, 엄밀히 따지면 자바스크립트의 모든 데이터 타입은 참조형 데이터일 수밖에 없다. 다만 기본형은 주솟값을 복사하는 과정이 한 번만 이뤄지고, 참조형은 한 단계를 더 거치게 된다는 차이가 있는 것이다.

2개의 댓글

comment-user-thumbnail
2021년 8월 12일

😄👍👍👍

1개의 답글