deep dive - 변수

CH_Hwang·2024년 5월 4일
0

deep-dive

목록 보기
2/6

변수

다음과 같은 자바스크립트 코드를 실행하면 컴퓨터에서 무슨일이 벌어질까?

10 + 20

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

의미를 해석하게 되면 + 연산을 수행하기 전 먼저 + 연산자의 피연산자를 기억한다. 이때 컴퓨터는 CPU를 사용해 연산하고, 메모리를 사용해 데이터를 기억한다.

메모리

  • 메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체다.
  • 셀 하나의 크기는 1byte(8bit)이며 컴퓨터는 1바이트 단위로 데이터를 저장하거나 읽어들인다.
  • 각 셀은 고유의 메모리 주소를 갖는다.
  • 메모리에 저장되는 데이터는 데이터의 종류와 상관없이 모두 2진수로 저장된다.

위 예제에서 10, 20은 메모리 상 임의의 메모리 주소에 저장되고 CPU가 이 값을 읽어서 연산하고, 연산된 결과 30도 메모리 상 임의의 주소에 저장된다.

하지만 이 값 30을 재사용 할 수 없다. -> 재사용 하고 싶다면 이 메모리 주소를 통해 직접 접근해야하는데, 이는 치명적 오류를 발생시킬 가능성이 매우 높다. 실수로 운영체제가 사용하고 있는 메모리 값을 변경하면 시스템 자체가 멈춰버리기때문에 자바스크립트에서는 직접적인 메모리 제어를 허용하지 않는다.

또하나의 치명적인 단점은 임의로 결정되기 때문에 실행할때마다 메모리 주소가 변경된다.

이를 해결하기위해 변수를 사용한다.
변수란, 하나의 값을 저장하기 위해 확보한 메모리 공간 자체, 또는 그 메모리 공간을 식별하기 위해 붙인 이름이다.

const ten = 10

위 코드에서 ten은 변수 이름(또는 변수명) 이고 변수에 저장된 값 10은 변수 값이라고 한다.

변수에 값을 저장하는 것을 할당(assignment)이라고 한다.

식별자

  • 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름
  • 값의 경우 중복될 수 있기 때문에 식별자는 이 아니라 메모리 주소를 기억하고 있다.
ten (변수명, 식별자) -> 0x0669f913(메모리주소) -> 10(메모리)

변수 선언

  • 값을 저장하기 위해 메모리 공간을 확보 후 변수 이름과 메모리 주소를 연결(name binding)하여 값을 저장할 수 있도록 한다.
  • var, let, const를 사용하고 ES6전에는 var가 유일한 변수선언 키워드였다.

var는 단점이 여러가지 있는데 대표적인 것이 블록 레벨 스코프가 아니라 함수 레벨 스코프를 지원한다. -> 의도치 않게 전역 변수 선언 가능

var score;

위 선언문은 변수 선언 후 아직 값을 할당하지 않았기 때문에 undefined 라는 값이 암묵적으로 할당되어 초기화한다.

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

  • 선언 단계: 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
  • 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 초기화한다.

변수이름을 모든 식별자는 실행 컨텍스트에 등록된다. -> 자바스크립트 엔진이 소스코드 평가, 실행하기 위한 환경 제공, 코드 실행 결과를 실제로 관리하는 영역 (key/value 형식인 객체로 등록되어 식별자, 스코프 관리)

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

console.log(score); // undefined

var score;

에러는 발생하지 않고 undefined가 출력된다.

이유: 변수 선언이 런타임이 아니라 그 이전 단계에서 먼저 실행되기 때문

자바스크립트 엔진이 소스코드를 한 줄씩 순차적으로 실행하기에 앞서 먼저 소스코드 평가과정을 거치며 소스코드를 실행하기 위한 준비를 한다.

이 소스코드 평가과정에서 변수 선언을 포함한 모든 선언문을먼저 실행한다.
즉, 변수선언이 소스코드 어디에 있든 무조건 먼저 실행한다.

var score;

console.log(score);

과 같이 된다는 뜻이다. 그렇기 때문에 console.log(score); 에서는 undefined가 출력된다.
이처럼 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 특징을 변수 호이스팅 이라한다.

값 할당

var score;
score = 80;

or

var score = 80;

변수 선언은 런타임 이전인 소스코드 평가 시점에 이루어 지지만 값 할당은 소스코드가 순차적으로 실행되는 런타임에 실행된다.

위와 같이 했을때
1. 변수 선언 시점에 메모리에 undefined가 저장되고 해당 메모리 주소를 score가 가리킨다.
2. 새로운 메모리 공간에 값 80이 저장되고 score가 가리키는 메모리 주소가 80이 저장되어있는 주소를 가리킨다.

값 재할당

var score = 80;
score = 90

값이 변경된다.

const, let

  • ES6부터 도입된 문법으로 let과 함께 변수선언 예약어로 추가되었다.
  • const는 값을 재할당할 수 없는 상수를 표현할 때 사용한다.
  • let은 변수를 표현할때 사용한다.

var의 경우 호이스팅이 일으킬 수 있는 사이드 이펙트 문제 때문에 요새는 거의 사용되지 않고 const와 let으로 사용된다.
필자는 기본적으로 변수를 선언할때 const로 선언하고 특별히 바꿔야할 때 (scope때문에 간섭을 해야할때 등..)만 let을 사용한다.

이 글 이후로는 꼭 필요한 경우가 아니면 변수선언은 const나 let으로 적겠다.

0개의 댓글