# Chapter04. 변수
# 1. 변수(variable)
# (1) 변수 등장 배경
- 컴퓨터는 CPU를 사용해 연산하고, 메모리를 사용해 데이터를 기억한다.
- 메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체로 각 셀은 고유의 메모리 주소를 갖는다.
- 이 때 직접 메모리의 주소에 접근하는 방식은 치명적 오류를 발생시킬 가능성이 매우 높다.
- 값이 저장될 때마다 메모리 주소도 매번 달라진다.
- 그래서 이를 방지하기 위해 프로그래밍 언어는 기억하고 싶은 값을 메모리에 저장하고, 저장된 값을 읽어 들여 재사용하기 위해 변수라는 메커니즘을 제공한다.
# (2) 변수
- 사람을 위해 사람이 이해할 수 있는 언어로 값이 저장된 메모리 공간을 식별하기 위해 붙인 이름
- 값의 위치를 가리키는 상징적인 이름
var result = 10 + 20; // 30
- 예를 들어 위 코드에서 연산을 통해 생성된 값 30이 메모리 공간에 저장될 때 다시 읽어 들여 재사용할 수 있도록
result
라는 상징적인 이름을 붙인 것이다.
# (3) 주요 용어 정리
용어 | 의미 |
---|---|
변수 이름(변수명) | 메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름 |
변수 값 | 변수에 저장된 값 |
할당 | 변수에 값을 저장하는 것 |
참조 | 변수에 저장된 값을 읽어 들이는 것 |
# 2. 식별자(identifier)
- 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 식별자라고 한다.
- 식별자는 값 자체를 기억하는 것이 아니라 해당 값이 저장되어 있는 메모리 주소를 기억해야 한다.
- 즉, 식별자는 값이 저장되어 있는 메모리 주소와 매핑 관계를 맺으며, 이 매핑 정보도 메모리에 저장되어야 한다.
- 그래서 식별자는 메모리 주소에 붙인 이름이라고 할 수 있다.
# 3. 변수 선언(variable declaration)
# (1) 의미
- 값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것
- 변수 선언에 의해 확보된 메모리 공간은 확보와 해제되기 전까지는 누구도 확보된 메모리 공간을 사용할 수 없도록 보호되므로 안전하게 사용할 수 있다.
# (2) 변수 선언 키워드
ES5 이전까지는
var
(함수 레벨 스코프) 만 존재했지만 여러 단점이 존재하여 ES6 이후로let
,const
(블록 레벨 스코프)가 등장했다.이 둘은 추후 다시 살펴보기로하고 지금은
var
키워드를 중심으로 살펴보자.
- 선언 단계
- 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
- 참고로 변수 이름을 비롯한 모든 식별자는 실행 컨텍스트에 등록된다.
- 초기화 단계
- 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로
undefined
를 할당해 초기화한다.
- 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로
var result = 10;
var res;
와 동일하여 메모리 공간에undefined
라는 값이 암묵적으로 할당되어 초기화된다.- 그 후
res = 10;
미리 확보된 해당 메모리 공간에 10 이라는 값을 할당한다. - 참고로
var
키워드를 사용한 변수 선언은 선언 단계와 초기화 단계가 동시에 진행된다.
# 4. 변수 호이스팅 (variable hoisting)
- 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트의 고유의 특징을 변수 호이스팅이라고 한다.
console.log(a); // undefined
var a; // 변수 선언
- 위 코드에서 변수 선언이 참조하는 구문보다 아래에 위치하지만 실제로 console.log를 찍어보면
undefined
가 출력되는 것을 볼 수 있다.- 왜냐하면 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉, 런타임이 아니라 그 이전 단계에서 먼저 실행되기 때문이다.
- 자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하기에 앞서 먼저 소스코드의 평가 과정을 거치면서 변수 선언을 포함한 모든 선언문을 소스코드에서 찾아내 먼저 실행한다.
# 5. 값의 할당(assignment)
- 변수에 값을 할당(대입, 저장)할 때는 할당 연산자
=
를 사용한다. 할당 연산자는 우변의 값을 좌변의 변수에 할당한다. - 변수 선언과 값의 할당의 실행 시점이 다르다.
- 변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행된다.
- 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행된다.
console.log(res); // undefined (a)
var res;
res = 10;
console.log(res); // 10 (b)
- 위 그림 처럼 변수에 값을 할당할 때는 이전 값
undefined
가 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당 값 10을 새롭게 저장하는 것이 아니라 새로운 메모리 공간을 확보하고 그 곳에 할당 값 80을 저장한다는 점에 주의하자.- 참고로 값의 재할당도 값의 할당과 동일한 매커니즘으로 이해하면 된다.
- 또한 위 그림에서
res
변수의 이전 값인undefined
는 어떤 변수도 값으로 갖고 있지 않다.- 다시 말해, 어떤 식별자와도 연결되어 있지 않으며 더 이상 필요하지 않다는 의미와 일맥상통하다.
- 이러한 불필요한 값들은 가비지 콜렉터에 의해 메모리에서 자동 해제된다.
- 가비지 콜렉터는 더 이상 사용되지 않는 메모리를 해제하는 기능을 말하고 이 때 더 이상 사용되지 않는 메모리란 어떤 식별자로 참조하지 않는 메모리 공간을 의미한다.
# ➕ unmanaged language vs managed language
- unmanaged language
- 개발자가 명시적으로 메모리를 할당 및 해제해야한다.
- 메모리 제어를 개발자가 주도할 수 있으므로 개발자의 역량에 따라 최적의 성능을 확보할 수 있지만 그 반대의 경우 치명적 오류를 생산할 가능성도 있다.
- ex) C언어, C++
- managed language
- 메모리의 할당 및 해제를 위한 메모리 관리 기능을 언어 차원에서 담당하고 개발자의 직접적인 메모리 제어를 허용하지 않는다.
- 즉, 가비지 콜렉터가 메모리의 할당 및 해제를 알아서 해준다.
- 개발자의 역량에 의존하는 부분이 상대적으로 작아져 어느 정도 일정한 생산성을 확보할 수 있다는 장점이 있지만 성능 면에서 어느 정도의 손실은 감수할 수 밖에 없다.
- ex) Javascript
# 6. 식별자 네이밍 규칙
- 식별자는 특수문자를 제외한 문자, 숫자, 언더스코어, 달러 기호를 포함할 수 있다.
- 단, 식별자는 특수문자를 제외한 문자, 언더스코어, 달러 기호로 시작해야 한다. 숫자로 시작하는 것은 허용하지 않는다.
- 예약어 (opens new window)는 식별자로 사용할 수 없다.
- 또한 프로젝트를 수행하면서 네이밍 컨벤션을 잘 수립하여 코드의 일관성을 유지하는데도 신경을 쓰도록 하자.