[JS, 딥다이브] 변수

hobeom·2024년 1월 18일
0

Deep dive

목록 보기
1/2

변수란?

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

10 + 20

위 식을 계산할 때 자바스크립트 엔진은 먼저 10, 20, + 라는 기호(리터럴, 연산자)의 의미를 알고 있어야 하며, 10 + 20이라는 식(표현식)의 의미도 해석(파싱)할 수 있어야 한다.

값 10과 20은 메모리 상의 임의의 위치(주소)에 저장되고, cpu는 이 값을 읽어 연산을 수행한다.
결과 값인 30 또한 메모리에 저장된다.

하지만 30을 저장한 메모리 위치에 접근할 방법이 없으므로 재사용할 수 없다.
자바스크립트는 보안상의 이유로 개발자의 직접적인 메모리 제어를 허용하지 않는다.
따라서 자바스크립트에서는 '변수'에 값 30을 할당하여 값을 재사용한다.

할당과 참조

var result = 10 + 20;

위 코드처럼 변수에 값을 저장하는 것을 할당이라고 하고, 변수에 저장된 값을 읽는 것을 참조라고 한다.

식별자

식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말한다.
식별자는 값이 아니라 메모리 주소를 기억하고 있다.
변수, 함수, 클래스 등에 붙인 이름은 모두 식별자이다.

식별자 > 변수

변수 선언

ES5 문법인 var 키워드와 ES6 문법인 let, const를 비교해보자

var은 함수 레벨 스코프만 지원한다.
이 때문에 의도치 않게 전역 변수가 선언되어 심각한 부작용이 발생할 수 있다.

키워드?

자바스크립트 코드를 해석하는 자바스크립트 엔진이 수행할 동작을 규정한 명령어이다.
키워트를 만나면 자신이 수행해야할 약속된 동작을 수행한다.

var score;

위 변수 선언문은 다음과 같이 변수 이름을 등록하고 값을 저장할 메모리 공간을 확보한다.

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

  1. 선언 단계: 변수 이름을 등록해서 js엔진에게 변수의 존재를 알린다.
  2. 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.

자바스크립트 엔진은 변수 초기화 시에 값을 할당하지 않아도 undefined 라는 값을 암묵적으로 할당하여 초기화한다.

만약 초기화 단계를 거치지 않으면 score라는 변수의 값을 기억할 메모리 공간에
다른 애플리케이션이 사용했던 값이 남아 있을 수 있다. 이러한 값을 쓰레기 값이라고 한다.
자바스크립트의 var 키워드는 암묵적으로 초기화를 수행하므로 이러한 위험으로부터 안전하다.

실행 컨텍스트

변수에는 실제 값의 메모리 주소가 저장된다고 했는데, 변수의 이름은 어디에 저장될까?
변수 이름을 비롯한 모든 식별자는 실행 컨텍스트에 저장된다. 여기엔 js엔진이 소스코드를 평가하고 실행하기 위해 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다.

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

console.log(score); // undefined
var score; // 변수 선언문

자바스크립트 코드는 인터프리터에 의해 한 줄씩 순차적으로 실행된다.
따라서 위 예제에서는 console.log(score);가 먼저 실행되어 선언문이 있기 전에 먼저 참조부터 했으므로 참조에러가 발생할 것처럼 보인다.
하지만 에러가 발생하지 않고 undefined가 출력된다.

그 이유는 변수 선언이 소스코드가 순차적으로 실행되는 시점(런타임)이 아니라 그 이전 단계에서 실행되기 때문이다.
이처럼 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅이라고 한다.

값의 할당

변수 호이스팅에 의해서 변수 선언값의 할당

var score;
score = 80;

2개의 문으로 나누어 표현한 코드와

var score = 80;

하나의 문으로 표현한 코드는 정확히 동일하게 동작한다.

console.log(score);
score = 80;
var score;
console.log(score);

위 코드의 결과는 어떨까?
결과는

undefined
80

변수 호이스팅에 의해 score라는 변수가 실행 컨텍스트에 먼저 등록되고 순차적으로 소스코드를 실행하기 때문에 런타임 때 2번째 줄에서 score에 80이 할당되는 것이다.

값의 재할당 ,가비지 콜렉터

score = 90;

변수에 값을 재할당하면 score 변수의 값은 90으로 변경된다. 하지만 90이란 값은 새로운 메모리 공간을 확보하고 그 메모리 공간에 90을 저장한다.
이전 값인 undefined와 80은 더 이상 필요하지 않다. 다시 말해 어떤 식별자와 연결되어 있지 않다. 이러한 불필요한 값들은 가비지 콜렉터에 의해 자동 해제된다.
단, 가비지 콜렉터는 메모리 공간을 주기적으로 검사하기 때문에 언제 해제될지는 예측할 수 없다.

왜 번거롭게 새로운 메모리 공간에 값을 재할당할까?

값을 재할당할 때, 변수가 참조하는 메모리 공간이 충분하지 못할 수 있다.
값마다 데이터의 크기가 다를 수 있기 때문이다. 따라서 js엔진은 변수에 값을 할당할 때, 유동적으로 참조할 메모리의 주소를 바꿀 수 있다.
1. 메모리에 해당 값이 있다면 변수가 그 주소를 참조하게 한다.
2. 없다면 메모리에 값을 저장하고 그 주소를 참조하게 한다.

profile
서두르지 마라, 멈추지도 마라

0개의 댓글

관련 채용 정보