본 글은 정재남님의 저서 '코어 자바스크립트'를 읽고 공부한 내용을 바탕으로 작성하였습니다.
아래에 나오는 메모리 이미지들은 이해를 돕기 위해 메모리 구조를 아주 간략화 시킨 예입니다.
자바스크립트의 데이터 타입에는 기본형(primitive type)과 참조형 (reference type) 크게 두 가지가 있다.
다음 코드 예제를 보며 변수 선언시 메모리에서 어떤 일이 벌어지는지 알아보자.
var a;
위 코드를 말로 풀어쓰면 "변할 수 있는 데이터를 만든다. 이 데이터의 식별자는 a로 한다." 가 된다. 이렇게 보면 변수란 결국 변경 가능한 데이터가 담길 수 있는 공간 또는 그릇 이라고 생각할 수 있다. 이 공간에 숫자를 담았다가 문자열을 담는 등의 다양한 명령을 내릴 수 있다.
실제 메모리에서는 아래와 같은 일이 벌어진다.
- 위 예제코드의 명령을 받은 컴퓨터는 메모리에서 비어있는 공간 하나를 확보
(여기서는 임의로 1003번으로 정함)- 이 공간의 이름 (식별자)를 a라고 지정
- 이후에 사용자가 a에 접근하고자 하면 컴퓨터는 메모리에서 a라는 이름을 가진 주소를 검색해 해당 공간에 담긴 데이터를 반환
var a;
a = 'abc';
var a = 'abc';
위 코드 예제에서 변수의 선언과 할당을 나눠서 하든, 한 문장으로 하든 자바스크립트 엔진은 결국 같은 동작을 수행한다.
아래의 그림을 보면서 데이터 할당시 메모리 영역이 어떻게 변하는지 알아보자.
- 변수 영역에서 빈 공간(@1003)을 확보한다.
- 확보한 공간의 식별자를 a로 지정한다.
- 데이터 영역의 빈 공간 (@5004)에 문자열 'abc'를 저장한다.
- 변수 영역에서 a라는 식별자를 검색한다(@1003).
- 앞서 저장한 문자열의 주소(@5004)를 @1003의 공간에 대입한다.
이는 데이터 변환을 자유롭게 할 수 있게 함과 동시에 메모리를 더욱 효율적으로 관리하기 위해서이다.
문자열 데이터를 예를 들어 생각해 보자. 미리 확보된 공간 내에서만 데이터 변환을 할 수 있고, 변환할 데이터가 확보된 공간보다 더 많은 공간을 필요로 한다고 가정을 하면 값을 저장하기 전에 공간을 늘리는 작업을 선행해야 할 것이다. 만약 이 공간이 메모리상의 가장 마지막에 있다면 뒤쪽으로 늘리기만 하면 되지만, 중간에 위치하고 있다면 해당 데이터보다 뒤에 있는 데이터들을 모두 뒤로 옮기고 이동시킨 주소를 각 식별자에 다시 연결하는 작업을 해야 한다. 컴퓨터가 처리해야 할 연산이 많아질 수 밖에 없다.
결국 효율적으로 데이터 변환을 처리하려면 변수와 데이터를 별도의 공간으로 나누어 저장하는것이 최적이다.
문자열 'abc'의 마지막에 'def'를 추가하려고 한다면?
위와 같이 앞서 'abc'가 저장된 공간에 'abcdef'를 할당하는 대신, 'abcdef'라는 문자열을 새로 만들어 별도의 공간에 저장하고, 그 주소를 변수의 공간에 연결한다.
다른 예로 500개의 변수를 생성해서 모든 변수에 숫자 5를 할당하는 경우, 데이터 영역에 5를 한 번 저장하고 이 주소를 변수의 공간에 연결한다. 자바스크립트의 경우 숫자형을 저장하기위해서는 8바이트가 필요한데, 예를 들어 주소 영역의 크기가 2바이트라고 한다면 (2 * 500 + 8), 8바이트를 500개 할당하는 것보다 메모리를 크게 절약할 수 있을 것이다.
이처럼 변수 영역과 데이터 영역을 분리하면 중복된 데이터에 대한 효율또한 높아진다.