모던 자바스크립트 Deep Dive 4: 변수

변수란 무엇이고, 왜 필요한가?

다음 코드가 있다.

10 + 20;

위 코드를 컴퓨터는 다음과 같은 과정을 거치게 된다.

  1. 10과 20을 메모리에 저장한다.
  2. CPU가 10과 20이란 값을 + 연산을 진행한다.
  3. 연산 결과값을 메모리에 저장한다.

위 과정을 끝나고 보니, 결과 값을 재사용할 방법이 없다는 문제가 발생했다.
이 값을 접근하려면 메모리 주소를 직접 접근해야하는데 자바스크립트는 직접적인 메모리 제어가 안된다.
이를 해결하기 위해 나타난 개념이 변수이다.
따라서 변수의 정의는 다음과 같다.

변수는 하나의 값을 저장하기 위해 확보한 메모리 공간을 식별하기 위해 붙인 이름이다.



식별자

  • 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말한다.
  • 식별자는 값이 아니라 메모리 주소를 기억하고 있다.
  • 식별자는 메모리 상에 존재하는 어떤 값을 식별할 수 있는 이름은 모두 식별자다.


변수 선언

  • 변수 선언은 값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것이다.
  • 변수를 선언할 때는 var, let, const 키워드를 사용
  • ES6 이전에는 var 키워드가 유일한 변수 선언 키워드 였고, ES6때 let, const 키워드가 도입됨


자바스크립트 엔진 변수 선언

자바스크립트 엔진은 변수 선언을 2단계에 거쳐 수행한다.

  • 선언 단계 : 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알림
  • 초기화 단계 : 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화함

초기화 단계를 거치는 이유

만약 초기화 단계를 거치지 않으면 확보된 메모리 공간에는 이전에 다른 애플리케이션이 사용했던 값이 남아있을 수 있다. 이러한 값을 쓰레기 값이라고 한다. 따라서 쓰레기 값이 나오는걸 막기 위해 변수 초기화 단계가 필요하다.



변수 선언의 실행 시점과 호이스팅

다음 코드를 보자

console.log(a); // undefined
var a;

변수 선언 전에 출력을 시도했는데 reference error가 안뜨고 undefined 값이 출력되었다.
그 이유는 변수 선언이 런타인 이전 단계에서 실행되기 때문이다.
이러한 단계 때문에 마치 변수 선언문이 코드 맨 위로 끌어 올려진 것처럼 동작한다.
이러한 특징을 변수 호이스팅이라고 한다.



값의 할당

var score;
score = 80;

위의 코드는 하나의 문으로 단축시킬 수 있다.

var score = 80;

두 코드는 똑같이 동작한다. 그 이유는 자바스크립트 엔진은 변수 선언과 값의 할당을 2단계로 나누어 실행하기 때문이다. 즉 런타임 이전에 변수 선언이 실행되어서 값을 저장할 메모리 공간을 확보하고, 변수 이름의 존재를 알린 뒤 암묵적으로 undefined 값으로 초기화 시킨 다음 80 이란 값을 변수에 재할당 하는 것이다.

근데 undefined에서 80으로 재할당하면 현재 변수가 참조하고있는 메모리 주소의 값을 바꾸는걸까?
그렇지 않다. 다시 새로운 메모리 공간에 80이란 값을 저장하고 변수 이름이 새로운 메모리 주소를 참조하는 것이다. 그러면 undefined를 저장하고있는 메모리는 가비지 컬렉션에 의해 메모리에서 자동 해제가 된다.
이러한 특징이 나중에 나오겠지만 왜 primitive 타입이 변경이 불가능한 값인지를 설명해 주는 근거이다.
다시 정리한다면 다음과 같다.

  • 자바스크립트 엔진은 변수 선언과 값의 할당은 다른 시점에서 실행된다.
  • 값을 재할당시 기존에 참조하고 있는 메모리 공간에 있는 값을 바꾸는게 아니라 새로운 메모리 공간에 값을 저장한 뒤 변수가 새 메모리 공간을 참조하는 것이다
  • 아무도 참조하고 있지 않는 메모리는 가비지 컬렉터에의해 자동 해제된다.


식별자 네이밍 규칙

식별자는 다음과 같은 네이밍 규칙을 준수해야한다.

  • 식별자는 특수문자를 제외한 문자, 숫자, 언더스코어(_), $ 를 포함할 수 있음
  • 식별자는 숫자로 시작하는 것은 허용하지 않음
  • 예약어는 사용할 수 없음

주요 네이밍 컨벤션은 다음과 같다.

  • 카멜 케이스 : camelCase
  • 스네이크 케이스 : snake_case
  • 파스칼 케이스 : PascalCase
  • 헝가리안 케이스 : TypeHungarianCases

일반적으로 자바스크립트에서는 변수나 함수 이름에는 카멜 케이스를 사용하고 생성자 함수, 클래스 이름에는 파스칼 케이스를 사용한다.