자바스크립트, 변수가 만들어지는 과정

잭슨·2023년 12월 16일
0

javascriprt

목록 보기
3/11

이번 포스팅에선 자바스크립트에서 변수가 어디에 어떤 방식으로 저장되는지 알아보고자 한다.

변수란 무엇인가?

변수란 하나의 값을 저장하기 위해 확보한 메모리 공간, 혹은 메모리 공간을 식별하기 위해 붙인 이름을 말한다.
단순히 말해서 '값의 위치를 가리키는 상징적인 이름'이라고 할 수 있다.

우리가 읽고 쓰는 데이터는 메모리(RAM)에 저장된다. 메모리는 1Byte 크기의 메모리 셀의 집합체이며 각 셀은 16진수로 되어 있는 메모리 주소를 갖는다. 예를 들어 4GB짜리 메모리가 있다고 했을때 이 메모리는4,294,967,296(232 = 168)개의 주소를 갖는다. 이렇게 많은 메모리 공간을 16진수로 구성된 메모리 주소를 사용하여 접근 하는 것은 불가능에 가깝고 만약 실수로 운영체제가 사용하고 있는 값을 변경할 경우 시스템이 멈출수도 있는 치명적인 오류가 발생할 수도 있다. 따라서 우리가 변수를 생성하면 변수는 컴파일러 혹은 인터프리터에 의해 값이 저장된 메모리 공간의 주소로 치환되어 실행되기 떄문에 변수를 통해 메모리에 안전하게 접근할 수 있다.

var result = 10 + 20;

아래 이미지는 result 변수가 생성되는 일련의 절차를 나타낸 그림이다.

변수의 이름처럼 어떤 값을 식별할 수 있는 고유한 이름을 '식별자' 라고 한다. 위 그림에서 result가 식별자에 해당한다.
식별자는 실제 값이 아니라 메모리의 주소를 기억하고 있다. 따라서 우리가 변수를 사용할 때, 식별자가 기억하고 있는 메모리 주소를 통해 메모리 공간에 있는 값에 접근하는 것이다.

그렇다면 변수는 어떻게 생성될까?
변수의 생성 과정을 단계별로 나눠서 살펴보자.

1. 변수 선언

우리는 var, let, const 키워드를 사용하여 변수를 선언할 수 있다. 각각의 키워드의 차이는 나중에 따로 정리하여 포스팅 하겠다. 우선 코드를 실행시키면 자바스크립트 엔진은 실제 소스코드가 실행되는 런타임 단계 이전에 모든 선언문들을 실행시킨다. 이를 호이스팅이라고 한다. 호이스팅이 실행된 뒤 값이 들어갈 메모리 공간을 확보하고 확보된 공간과 변수의 이름을 연결binding한다. 이렇게 변수 선언에 의해 확보된 공간은 확보가 해제release되기 전까지는 누구도 확보된 메모리 공간을 사용할 수 없도록 보호된다.

2. 초기화

값을 할당받지 못한 변수는 undefined라는 값이 암묵적으로 할당된다. 만약 이러한 초기화 단계를 거치지 않는다면 확보된 메모리 공간에는 이전에 다른 응용 프로그램에서 사용한 값이 남아 있을수도 있다. 이러한 값을 쓰레기 값garbage value라고 한다.

3. 값의 할당

변수에 값을 할당하는 방법은 등호('=')를 사용해서 할당할 수 있다.

var a;  // 변수 a 선언
a = 20; // 변수 a에 20이라는 값을 할당

위 코드는 변수 a에 20이라는 값을 할당시키는 작업을 하고있다.
아래 코드처럼 선언과 값의 할당을 동시에 해줘도 된다.

var a = 20; // 선언과 할당을 동시에 진행

값을 할당시켜주는 등호 기호를 '할당 연산자' 라고 부른다. 할당 연산자는 우변의 값을 좌변의 변수에 할당(대입) 한다.

여기서 주의해야될 점은 변수의 선언과 값의 할당이 실행되는 시점이 다르다는 것이다. 변수의 선언은 런타임 이전(호이스팅이 일어나는 시점)에 실행되지만 값의 할당은 실제로 코드가 순차적으로 실행되는 런타임에 실행된다.

그럼 변수의 선언과 값의 할당 시점이 다르다는 것이 왜 중요할까? 아래 코드를 보자

console.log(score); // undefined

var score;  // 변수 선언
score = 20; // 값의 할당

console.log(score) // 20

위 코드는 같은 score변수를 출력하고 있음에도 처음엔 undefined가 출력되고 마지막엔 20이 출력된다. 그 이유를 살펴보자.

우선 코드를 실행시키면 변수 호이스팅에 의해 선언문이 먼저 실행된다. 따라서 score변수가 선언되고 아직 값을 할당받지 않은 score변수는 undefined로 초기화될 것이다.

그런 다음 위에서부터 코드가 순차적으로 실행된다(런타임). 따라서 첫 줄에 console.log(score)은 값이 undefined로 초기화되어있는 score변수를 참조하기에 undefined가 출력되고 그 다음 score=20이 실행되어 score변수에 20이 값으로 할당된다. 그 다음 console.log(score)에서 값이 20으로 할당된 score변수를 참조하기에 20이 출력되는 것이다.

그렇다면 변수의 선언과 값의 할당을 하나의 문statement으로 단축하여 실행한다면 결과는 달라질까? 아래 코드를 보자.

console.log(score); // undefined

var score = 20;  // 변수 선언과 값의 할당을 동시에 실행

console.log(score) // 20

여전히 출력은 똑같이 나온다.
이전 포스팅에서 설명했듯이 자바스크립트 엔진은 변수의 선언 단계와 값의 할당 단계를 분리하여 2개의 문으로 각각 실행한다. 따라서 변수는 런타임 이전에 무조건 undefined로 초기화된다는 뜻이다.

또한 undefined로 초기화되어 있는 변수에 새로운 값을 할당하면 undefined가 저장되어 있는 메모리 공간을 지우고 그 메모리 공간에 새로운 값을 할당시키는 것이 아니라 아래 이미지처럼 새로운 메모리 공간을 확보하고 그곳에 값을 할당한다.

마찬가지로 var키워드로 생성된 변수는 값이 재할당 될 때도 기존에 있던 값을 그대로 두고 새로운 메모리 공간을 확보하여 그 위치에 값을 할당한다.

만약 이렇게 값이 재할당되지 않는다면 그건 변수가 아니라 상수constant라고 하며 이는 추후에 배울 const 키워드와 관련이 있다.

이처럼 값의 재할당이 이루어지고 나면 그 전에 사용했던 값은 쓰레기 값이 되므로 가비지 콜렉터garbage collector에 의해 메모리에서 자동으로 해제된다. 단, 가비지 콜렉터가 언제 동작할지는 예측할 수 없으므로 메모리에서 언제 해제될지 예측할 수 없다.

참고 자료: 모던 자바스크립트 Deep Dive 책

profile
지속적인 성장

0개의 댓글