자바스크립트변수 var! 값을 재사용하기 위해 저장해두는 메모리 공간 변수호이스팅?

2021. 7. 18. 20:36컴퓨터언어/Node.js

728x90
반응형

 

변수 = 메모리 공간 자체

변수는 값이 아닙니다. 그 값을 담고 있는 공간입니다.

그리고 그 변수의 이름은 공간을 가리키는 주소입니다.

 

 

프로그램은 인간이 문제를 해결하는 과정을 컴퓨터로 고대로 옮겨놓은 것 뿐이야.

기계이기 때문에 더 빠르게 반복할 수 있고 천문학적인 숫자를 쉽게 다룰 수 있다는 장점이 있지!

하지만 컴퓨터는 사람의 두뇌 연산과 살짝 차이가 있어.

 

사람 컴퓨터
두뇌라는 하나의 시스템에서 연산과 기억을 모두 수행
(물론 뇌 안에서도 영역이 있다만 여기서 그것까지 다루지 말자)
[연산을 위한 CPU]와 [기억을 위한 메모리]로 나뉨

 

프로그램이 동작하는 원리는 매우 단순해.

매번 발생하는 새로운 정보를 기존 정보와 융합하는 거야.

사람이랑 똑같지 않아?


우리도 원래 알던 거에 새로운 정보를 추가하기도 하고,


잘못 알고 있던 것은 지워버리잖아.


사람에게 기억을 담당하는 해마가 있다면,


컴퓨터에게는 프로그램이 실행될 때 CPU에 명령어를 한줄씩 보내기 위한 기억장치로서 RAM(메모리)이 존재해.


하나의 프로그램 안에는 여러가지 기능이 있잖아.


그리고 각 기능은 결국 복잡한 연산이 혼합되어 있지.


그렇다면 프로그램 개발자는 그때그때 발생되는 새로운 값들이 잘 저장되도록 코딩해야겠지?

 

이때 코드 안에서 값의 저장을 담당하는 것이 바로 변수야!


우리는 웹개발의 Pro가 될 거잖아?


그럼 자바스크립트는 호흡과 같이 기본이어야 돼.

 

모르면 죽는거야.

 

자바스크립트에서의 변수에 대해 공부해보자!

 

자바스크립트로 코딩 -> 자바스크립트 엔진의 해석 -> CPU 연산 및 실행

 

컴퓨터로 프로그램을 만들어서 실행하는 이유는,

인간이 하기에 버거운 연산들을 대신 시키기 위해서야.

아무리 복잡한 기능도 쪼개고 쪼개다 보면 결국 더하기의 집합이야.

즉 사람이 1+1은 2라고 계산을 하는 것과 마찬가지로,

컴퓨터도 연산을 똑같이 한다는 거야.

그럼 우리가 1+1은 2라고 할 때를 한번 생각해보자.

위 계산을 하기 위해서는 "사전 지식"으로서 다음 사실을 이미 알고 있어야 해.

① 1은 "1개"를 나타내는 숫자라고 배운 사실을 기억하고 있다.
② +는 양 옆의 두 숫자를 더해서 새로운 값으로 만드는 연산자라는 사실을 기억하고 있다.

 

그래서 2라는 결과를 만들 수 있지.

여기까지는 기본이지?


그런데, 위에서 말했듯이 프로그램이란 기존 정보와 새로운 정보의 융합,

즉 계속된 덧셈과 누적으로 인류의 삶을 더 윤택하게 만드는 거거든?

그러려면 직전에 계산한 값을 기억하고 있어야 할 것 아니야.

그럼 위 예에서 만들어진 2를 다시 사용하고 싶다면 어떻게 해야 할까?

잠깐 어딘가에 기억을 해놓아야겠지?

우리도 물건을 살 때 잠깐 단기기억으로 하나, 둘, 셋… 이렇게 숫자를 세잖아. 금방 까먹더라도 말이야.

마찬가지로 컴퓨터도 좀전에 끝낸 연산을 어딘가에 잠깐 담아 놓아야 그 다음 연산에서 사용될 수 있어.

이때 잠깐 담아 놓는 곳을 변수라고 해.

변수 = 하나의 값을 재사용하고자 저장해 두는 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름

 

우리에게 "기억력"이 있다면,

컴퓨터에게는 RAM(메모리)이 있어.

메모리는 엄청 많은 방이 다닥다닥 붙어 있는 물리적인 반도체 부품이야.

각 방은 다시 연속된 전기 신호 8개를 담을 수 있는데,

전기 신호가 있냐 없냐를 8가지로 조합해서 각 방에 딱 하나의 값만 넣어서 저장하는 거야!

즉, 메모리 내의 각 공간 안에는 문자 하나, 숫자 하나, null 하나, undefined 하나, true 하나 요런 식으로 들어있어!

이렇게 프로그래밍 세계에서는 변수라는 메커니즘이 있기에,

우리는 게임, AI 등 복잡한 응용 프로그램을 만들 수 있게 되었어.


자, 변수가 왜 필요한지 파악했지?

그럼 자바스크립트에서 변수를 사용하는 법을 알아보자구.

잠깐! 변수의 정의를 다시 한번 말해 봐.

 

하나의 값을 재사용하기 위해 저장해 두는 메모리 공간 자체 또는 그 공간을 식별하기 위해 붙인 이름

 

우리가 변수를 사용하는 목적은 값을 저장해 두기 위함이지?

그럼 그 저장 공간을 우선 확보해야 하잖아.

그것은 다음 3가지 예약어로 구현해.

 

var let const

 

참고로, var는 2015년에 발표된 새로운 자바스크립트 표준인 ES6 이후로 사용하지 않도록 권장되고 있어.

그래서 최근 코드는 모두 var 대신 let과 const로 대체해야 하지.

하지만 대다수 기존 코드는 여전히 var로 쓰여 있는 문제가 있고,

어쨌든 새로 등장한 let과 const가 왜 쓰여야만 하는지를 "제대로" 이해하려면,

var 부터 확실히 알아야 해.

따라서 우리는 let과 const는 잠시 뒤로 미루고,

오늘은 var로 변수를 만드는 방법만 알아볼거야!


vscode 같은 에디터 안에서 자바스크립트 언어로 코딩을 하여 "*.js" 파일을 저장한 후,

node.js 또는 브라우저에 내장된 자바스크립트 엔진이 그 *.js 소스 코드를 실행하거든.

이때, 자바스크립트 엔진은 소스코드 전체를 쓱 훑으면서

var / let / const 를 만날 때마다, 메모리 공간을 하나씩 확보하고 그 공간의 주소를 기억하는(=참조하는/가리키는) 변수를 만들어 주는거야.

자바스크립트 엔진이 변수 선언문을 발견하면, 다른 응용 프로그램들은 그 새로 생긴 메모리 공간을 침범할 수 없게 돼.

자바스크립트만의 공간이 되는거야.

C언어에서는 malloc() 함수로 개발자가 직접 메모리 공간을 확보하지만,

자바스크립트는 엔진이 스스로 해주기 때문에 편해~

메모리 공간을 확보하려면 다음과 같이 쓰면 돼.

var 예약어 바로 옆에 그 공간을 가리킬 "유일한" 이름을 지어주어야 해.

그래야 내가 필요한 값을 정확하게 찾아낼 수 있기 때문이지.

변수명을 가지고 데이터를 유일하게 식별할 수 있다고 해서 "식별자"라고 해.

 

var : 예약어
score : 식별자
var score;

 

그런데 지금은 메모리 공간만 만들었을 뿐, 아직 거기에 어떠한 값도 넣지 않았잖아.

자바스크립트 엔진은 이때 아직 어떠한 값도 정의되지 않았다는 의미에서 자동으로 "undefined"라는 값을 넣어버려.

선언만 해도, 자바스크립트 엔진은 암묵적으로 undefined라는 값을 넣는거야.

즉, 위 코드는 아래와 정확히 같아.

var score = undefined;

이렇게 선언과 동시에 할당하는 것을 "초기화" 했다고 해.

그리고 위 코드는 다시 아래와 정확히 같아.

 

var score;
score = undefined;

그런데 우리는 undefined가 아니라, 실제 값을 다룰 거잖아.

그렇다면 새로운 값을 재할당 하게 될거야.

그러면 앞으로 다른걸 다시 대입한다고 하면, 그 메모리 공간 그대로 사용되고, 안에 값만 싹 바뀌는 걸까?

이건 그 공간에 들어있는 값의 Type에 따라 결정돼.

문자열, 숫자, 불린, null, undefined 이렇게 5가지를 원시값이라고 해.

원시값은 변경 불가능한 값이야.

자, 그럼 선언만 해도 undefined가 자동으로 들어 있다고 했지?

undefined는 변경 불가능한 값이기 때문에,

그 공간에 있던 기존 값을 지우고 업데이트 할 수 없어.

대신, 아예 새로운 공간을 확보하고 거기에 값도 새로 넣고, 기존 변수명에 새로운 공간에 대한 주소를 다시 연결해야 해.

즉, 새로운 값이 생기면 값을 갈아끼는 게 아니라, 공간과 함께 주소를 아예 바꾸는 거야.

이사를 아예 간다고.

그러니까 호텔이라고 생각해 봐.

너가 404호에서 하룻밤을 보냈어.

그리고 다음날 다른 사람이 그 호텔에서 하룻밤을 보낼 거야.

그러면 404호에서 너랑 그 사람이 바꿔치기하는게 아니라,

새로운 사람을 위한 새로운 방을 또 만들어서 그 사람을 넣어주는 거야.

단, 기존에 있던 너가 원시값인 경우에 한해서 말이야.

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

위에서 var score = 20; 이라고 한번에 쓴 거 보여?

자바스크립트 엔진은 위처럼 써도, 사실 아래처럼 풀어서 해석해.

 

console.log(score);
var score; // ① [변수 선언] : 먼저 메모리 공간을 확보하고 -> 그 메모리 공간의 주소를 score라는 이름에 연결하고 -> undefined 할당
score = 20; // ② [값의 할당] : 20이라는 값을 score가 가리키는 메모리 공간에 할당(대입/저장)

var 예약어의 특징 : 변수 호이스팅이 일어난다

그.리.고!!!

여기서 자바스크립트의 엄청난 특징이 펼쳐져.

자바스크립트는 소스 코드가 실행되는 순간, 코드 내에 있는 모든 var 변수 선언문을 맨 위로 올려버려!

자바스크립트는 코드를 위에서부터 차례로 한 줄씩 읽어나가거든?

그런데, 이렇게 한 줄씩 읽기 전에 일단 소스 코드를 쫘악 다 훑으면서,

var 변수 선언문들이 보이면 모두 위로 다 끌어올리는(hoist) 것부터 한다는 거야!

그럼 위 코드는 아래와 같이 정확히 일치하게 동작한다구!

var score;
console.log(score); // undefined
score = 20;

이렇게 위로 끌어올려지는 것을 변수 호이스팅이라고 해.

실제로 이렇게 코드 자체를 바꾸는게 아니라, 실행만 먼저 해두고 나중에 다시 저 코드를 읽을 차례에는 스킵해버리는거야.

이건 var 만의 특징이고, let과 const는 그렇지 않아.

그런데 한번 생각해봐.

애초에 선언부터 하고 사용하는 게 상식적인 순서 아니야?

변수 선언 -> 거기에 값 할당 -> 변수 참조(=값 읽기)

 

선언을 하지 않으면 Reference Error, 즉 참조 에러부터 나는 것이 정상이야.

여기서의 "참조"란, 메모리 공간에 저장된 값을 읽기 위해, 그 공간의 주소부터 읽는 것을 말하거든.

선언이 뭐라고 했지? 선언이란, "앞으로 이 메모리 주소에다가 값을 넣을 거에요" 라고 공간을 확보하는 거랬지?

하지만 var 키워드를 사용해서 변수를 선언하면, 이러한 상식을 지키지 않아도 변수 호이스팅이 도와주는 셈이야.

딱 봐도 불안정한 느낌이 오지.

그래서 2015년에 발표된 자바스크립트 표준, ES6 버전부터는 var를 권장하지 않아.

여기까지 자바스크립트의 변수와 호이스팅에 대해 잘 이해했지?

다음에 또 보자구.

728x90
반응형