지금까지 프로그래밍 언어를 공부하면서 변수라는 것은 내가 생성한 값에 대한 이름을 부여하는 것뿐이라고 생각하였다. 하지만 이번에 Javascript Deep dive라는 책을 통해서 변수가 왜 필요한 것인지에 대해서 조금 더 깊은 이해를 할 수 있었다.
먼저, 컴퓨터가 연산과 기억을 어떻게 하는지에 대해서 알아야지 아래의 내용을 이해할 수 있다.
컴퓨터는 연산과 기억을 수행하는 부품이 나누어져 있다. CPU를 사용하여 연산하고, 메모리를 사용하여 데이터를 기억한다. 메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체이다. 메모리 셀 하나의 크기는 1바이트이고, 컴퓨터는 메모리 셀의 크기를 1바이트 단위로 저장하거나 읽어들이는 것이다.
만약 아래 값을 계산한다고 해 보자.
10 + 20
우리는 30이라는 결과를 얻게 된다. 그런데 이 30이라는 값을 메모리의 임의의 위치에 기억될 것이다.(코드가 실행될 때마다 값이 저장되는 메모리 주소가 바뀌기 때문에 어디에 저장될 지 잘 모름) 그런데 이렇게 임의로 저장된 메모리에 컴퓨터가 30을 사용할 때마다 직접 접근하는 것은, 운영체제에 영향을 끼칠 수도 있고 시스템 내에 치명적인 오류를 만들 수 있다.
이러한 문제점을 해결하기 위하여 변수가 필요한 것이고, 변수의 정의를 다음과 같이 이야기할 수 있다.
하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위하여 붙인 이름
변수는 프로그래밍 언어에서 값을 저장하고, 참조하는 역할을 하며, 그 값의 주소 위치를 가리키는 상징적인 이름을 가지고 있는 것이다. 우리가 그 변수를 사용할 때마다 컴파일러나 인터프리터를 통하여, 값이 저장된 메모리 공간의 주소로 치환되어 실행된다. 개발자가 이제 직접 주소에 접근할 필요가 없고, 변수를 통하여 안전하게 접근 가능하게 된 것이며 재사용도 언제든지 할 수 있다!
그리고 추가적으로, 내가 직접 변수 이름을 지정함으로써 그 의미를 명확히 할 수 있으니, 가독성을 높이는 효과도 가지고 있다고 판단할 수 있다! :) 이러한 장점이~~
식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 이야기한다. 식별자는 값이 아니라 메모리 주소를 기억하고 있다. 식별자로 값을 구별하여 식별한다는 것은 식별자가 기억하고 있는 메모리 주소를 통하여, 저장된 값에 접근할 수 있다는 의미를 가지고 있다. 즉, 식별자는 메모리 주소에 붙인 이름이다.
나는 지금까지 식별자라는 것이 변수 이름에만 국한하여 사용하는 줄 알았다. 그런데 함수, 클래스 등 모두 식별자로 사용될 수 있다는 사실! 메모리 상에 존재하는 어떤 값을 식별할 수 있는 이름은 모두 식별자라고 하는 것이다.
변수 선언은, 변수를 생성하는 것으로써 값을 저장하기 위한 메모리 공간을 확보하고, 그 변수 이름과 확보된 메모리 공간의 주소를 연결하는 것이다. 변수를 사용하려면 반드시 선언이 필요한데, 변수를 선언할 때는 var, let, const
키워드를 사용한다.
ES6 전에는 var을 많이 사용하였는데, 요즘에는 var을 많이 사용하지 않는다. 그 이유에 대해서는 나중에 알아봅시다!
var score;
해당 코드를 작성하게 되면 이에 해당하는 메모리 공간이 새로 확보된다. 아직, 우리는 변수에 값을 할당하지 않았으므로, 메모리 공간에는 undefined
라는 값이 할당되어 초기화되어있다. 이것은 자바스크립트만의 독특한 특징이다. 쓰레기 값이 혹시나 남아 있을 수 있으니까, 이를 방지하기 위하여 초기화를 하는 것이다.
console.log(score);
var score;
자바스크립트는 인터프리터에 의하여 한 줄씩 순차적으로 실행된다. 가장 먼저 실행되는 코드는 console.log(score);
이고, 다음 줄에 있는 코드를 실행한다. 이 때 아직 score 변수의 선언이 실행되지 않았으므로 참조 에러가 발생할 것처럼 보인다.
그러나 참조 에러가 발생하지 않고, undefined가 출력된다. 그 이유는 변수 선언이 소스코드가 한 줄씩 실행되는 시점, 즉 런타임이 아니라 그 이전 단계에서 먼저 실행되기 때문이다.
자바스크립트 엔진은 소스코드를 한 줄 씩 순차적으로 실행하기 앞서 먼저 소스코드의 평가 과정을 거치면서, 소스코드를 실행하기 위한 준비를 한다. 이 평가 과정에서 자바스크립트 엔진은 변수 선언을 포함한 모든 선언문을 소스코드에서 찾아내 먼저 실행하는 것이다. 이 평가 과정이 끝나게 되면 변수 선언을 포함한 모든 선언문을 제외하고, 소스코드를 한 줄 씩 실행한다.
즉 변수 선언이 어디에 있든!! 어디서든지 변수를 참조할 수 있다.
이처럼 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅이라고 한다. 변수 선언 뿐 아니라, var, let, const, function, function*, class
키워드를 사용하는 모든 식별자는 호이스팅된다.
var scroe = 80
이렇게 변수의 선언과 할당을 동시에 해도, 자바스크립트는 선언과 할당을 2개의 문으로 나누어 각각 수행한다. 주의할 점은, 변수 선언과 값의 할당의 실행 시점이 다르다.
변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 실행되지만, 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행된다.
console.log(score); //javascript
var score = 80; // 변수 선언, 값의 할당
console.log(score); //80
이렇게 선언 후에 변수에 값을 할당할 때는 이전 값인 undefined
가 저장되어 있던 메모리 공간을 지우고, 그 메모리 공간에 할당 값 80을 새롭게 저장하는 것이 아니라, 새로운 메모리 공간을 확보하고, 그곳에 80을 저장하는 것이다. 재할당시에도 마찬가지이다. 새로운 메모리 공간을 확보하고, 그 공간에 새로운 숫자를 저장한다.