컴퓨터는 모든 데이터를 0또는 1
만으로 표현합니다. 0또는 1
만 표현할 수 있는 하나의 메모리 조각을 비트(bit)
라고 합니다. 메모리는 무수히 많은 비트들로 구성돼 있는데, 각 비트는 고유한 식별자를 통해 위치를 확인할 수 있습니다.
하지만 식별자를 통해 해당 비트가 0인지 1인지를 확인하는것은 매우 비효율적입니다. 그보다는 몇 개씩 묶어 하나의 단위
로 여긴다면 표현할 수 있는 값도 늘어나면서 동시에 검색 시간을 줄일 수도 있을 겁니다.
한편 묶는 단위가 너무 크면 검색 시간을 줄일 수 있는 동시에 낭비되는 비트가 생기기도 합니다. 자주 사용하지 않을 데이터를 표현하기 위해 빈 공간을 남겨놓기보다는 적절한 개수로 묶어 사용하는 편이 좋습니다. 이런 고민의 결과로 바이트(byte)
라는 단위가 생겼습니다.
1바이트는 8개의 비트로 구성돼 있습니다. 1비트마다 2가지 값을 표현할 수 있기때문에 1바이트는 총 256(2^8
)개의 값을 표현할 수 있고, 2바이트는 총 65536(2^16
)개의 값을 표현할 수 있습니다.
C/C++, 자바 등의 정적 타입 언어는 메모리의 낭비를 최소화하기 위해 데이터 타입별
로 할당할 메모리 영역을 2바이트, 4바이트 등으로 나누어 정해놓았습니다. 따라서 2바이트 크기의 정수형 타입(short)은 0을 포함해 -32768 ~ +32767의 숫자만 허용합니다.
때문에 범위 보다 큰 수나 적은 수를 입력하면 오류가 나거나 잘못된 값이 저장되고 맙니다. 이 문제에 대응하기 위해서는 사용자가 직접 4바이트 크기의 정수형 타입(int
)등으로 형변환해야 합니다. 메모리가 부족했던 시절
에는 이러한 선택이 불가피했다고 합니다.
자바스크립트는 타입을 따로 지정하지 않아도 할당된 값을 통해 동적으로 타입을 지정합니다. 이는 메모리 용량이 과거보다 월등히 커진 상황에서 자바스크립트가 등장했기 때문에 메모리 공간을 좀 더 넉넉하게 할당
하는 방식을 선택했기 때문입니다.
숫자의 경우 정수형인지 부동소수형인지 구분하지 않고 64비트(8바이트
)를 확보하기때문에 개발자 입장에서 형변환을 걱정을 덜어줬습니다.
앞서 비트는 고유한 식별자를 지닌다고 했었죠. 바이트 역시 시작하는 비트의 식별자로 위치를 파악할 수 있습니다. 모든 데이터는
바이트 단위의 식별자
, 더 정확하게는메모리 주솟값
을 통해 서로 구분하고 연결할 수 있습니다.
let a; // 변수 a 선언
a = "abc"; // a에 데이터 할당
------------------------------------
let a = "abc"; // 변수 선언과 할당을 한 문장으로 표현
위의 코드에서 선언과 할당을 나누든, 한번에 입력하든, 자바스크립트 엔진은 결국 같은 동작을 수행합니다. 메모리에서 빈 공간을 확보하고 그 공간의 이름(식별자
)를 a
로 하고 값을 "abc"
로 하면 될 것 같네요.
하지만 실제로는 해당 위치에 문자열 "abc"
를 직접 저장하지는 않습니다. 데이터를 저장하기 위한 별도의 메모리 공간을 다시 확보해서 문자열 "abc"
를 저장하고, 그 주소를 변수 영역에 저장하는 식으로 이뤄집니다.
왜 굳이 변수 영역과 데이터 영역을 나눈것일 까요? 이는 데이터 변환을 자유롭게 할 수 있게 함과 동시에 메모리를 더욱 효율적으로 관리하기 위한 고민의 결과입니다.
자바스크립트는 숫자형 데이터에 64비트(8바이트
)의 공간을 확보한다고 했습니다. 반면 문자열은 특별히 정해진 규격이 없습니다. 전체 글자 수
가 가변적이고, 한글은 2바이트
, 영어는 1바이트
등으로 각각 필요한 메모리 용량또한 가변적이기 때문입니다.
만약 변수명과 할당한 값을 한 메모리 영역에서 관리한다면 값이 현재 확보한 공간보다 크게 될 경우
필요한 크기만큼 늘리는 작업이 필요하겠습니다. 메모리상 가장 뒤쪽에 위치하고 있다면 상관없겠지만, 중간에 있는 데이터를 늘려야하는 상황
이라면 늘리기 위해 뒤에있는 데이터들을 모두 뒤로 이동시키고 새로운 주소값을 할당해야하는 작업을 진행해야 합니다.
결국 효율적으로 문자열 데이터의 변환을 처리하려면 변수와 데이터를 별도의 공간에 나누어 저장하는 것이 최적입니다.
가령 500개의 변수를 생성해서 모든 변수에 숫자 5를 할당하는 상황을 생각해봅시다. 각 변수를 모두 별개로 인식하려면 숫자형을 위한 8바이트
공간을 500개만큼 필요하기 때문에 총 4000바이트
를 써야 할 것입니다. 그 대신 5를 별도의 데이터 영역에 저장하고 변수 영역을 위한 크기가 2바이트
라고 한다면 1008(500*2+8)바이트
만 사용하면 됩니다. 이처럼 변수 영역과 데이터 영역을 분리하면 중복된 데이터에 대한 처리 효율이 높아집니다.
값을 변경하게 되면 앞서 저장했던 5004
주소에 새로운 값을 저장하는 것이 아니라 새로운 메모리 공간을 만들어 저장하고 그 주소를 변수 공간에 연결합니다.