자바스크립트 변수 아세요?

CCONAC·2024년 1월 29일
0
post-thumbnail

이 글은 모던 자바스크립트 Deep Dive: 자바스크립트 기본 개념과 동작 원리 책을 기반으로 정리한 글입니다.

🚀 변수란?

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

개념적 정의만 보면 이게 뭐라는 건가 싶다. 실생활 속 예시를 하나 들어 보자면 집 내부에 있는 방 정도가 되지 않을까 싶다. 여러 방들 중 변기를 위치시킨 공간을 화장실이라고 하는 것처럼 값의 위치를 가리키는 상징적인 이름을 정해 주는 게 변수라는 거다.

컴퓨터는 사람과 달리 CPU를 사용해 연산하고, 메모리를 사용해 데이터를 기억한다. 여기서 메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체를 이야기한다. 메모리 셀 하나의 크기는 1바이트이기 때문에 컴퓨터는 1바이트 단위로 데이터를 저장하거나 읽어 들인다. 그리고 이 셀들은 이 방대한 메모리 내에서 어느 위치에 있는지 거주 카드를 가진다. 이 거주 카드가 바로 셀 고유의 메모리 주소이다.

아니 그래서 변수는 왜 써야 하는 건데요?

아주 잘 열심히 계산을 해서 10 + 20을 메모리에 저장까지 여차저차 시켰다고 해 보자. 계산을 컴퓨터한테 시킨 건 다 이유가 있어서일 텐데 치명적인 문제는 자바스크립트는 개발자가 메모리 주소를 통해 값에 직접 접근하는 것을 허용하지 않는다.

얼마나 치명적이냐면, 우리가 벌집에 있는 한 칸의 집을 떼어내서 벌이 열심히 가지고 온 꿀을 버려 버리고 물로 채워 버리려고 하는 거다. 그러면 벌집 전체가 초토화가 될 수 있고 최악의 상황에는 집 하나가 망해 버릴 수도 있다. 🐝 불쌍해.... (극단적 예시일 뿐 실제가 아닙니다.)

무튼 재사용은 하고 싶은데 직접 접근은 하지 말라고 하니까 변수를 사용해 값을 저장하는 것이다. 이러면 벌이 안 슬픈지는 모르겠으나 적어도 직접적으로 건드는 건 아니라 벌집이 망할 일은 없다. 기쁜 일이다. 👏

이때 변수에 값을 저장하는 것을 할당이라고 하고, 변수에 저장된 값을 읽어 들이는 것을 참조라고 한다.

🤔 변수 이름은 어디에 등록될까?

변수 이름을 비롯한 모든 식별자는 값과 함께 실행 컨텍스트 내에 키/값 형식인 객체로 등록되어 관리된다.

여기서 실행 컨텍스트는 자바스크립트 엔진이 소스 코드를 평가하고 실행하기 위해 필요한 환경을 제공하고, 코드의 실행 결과를 실제로 관리하는 영역이다.

🔎 변수 선언

값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것을 말한다.

이렇게 확보된 메모리 공간은 확보가 해제되기 전까지 아무도 해당 공간을 사용할 수 없도록 보호된다. 변수를 사용하기 위해서는 반드시 선언이 필요한데, 변수를 선언할 때 사용하는 키워드에는 var, let, const가 있다.

여기서 var 키워드는 블록 레벨 스코프를 지원하지 않고 함수 레벨 스코프를 지원한다. 이로 인해 의도치 않게 전역 변수가 선언되어 심각한 부작용이 발생할 수 있다는 치명적인 단점이 존재한다.

이를 보완하기 위해 ES6부터 야생의 letconst 키워드가 나타났다! 🦖

🔎 변수 선언 단계

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

초기화는 변수가 선언된 이후 최초로 값을 할당하는 것을 말하는데, var 키워드로 변수를 선언하게 되면 얌묵적으로 초기화(undefined)가 자동 수행된다. 초기화 단계를 거치지 않고 선언된 변수를 바로 참조하려고 하면 메모리 공간에는 이전에 다른 애플리케이션이 사용했던 쓰레기 값이 남을 수 있다. 하지만 var 키워드는 암묵적으로 초기화를 자동 수행하므로 이런 위험으로부터 안전하다!

만일 변수를 선언하지 않고 참조하게 되면 등록된 식별자를 찾을 수 없다는 참조 에러(Reference Error)를 발생시킨다.

🔎 변수 선언 실행 시점

변수 선언은 소스 코드가 한 줄씩 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행된다.

자바스크립트 엔진은 소스 코드를 한 줄씩 순차적으로 실행하기 전, 소스 코드의 평가 과정을 거친다. 이때 변수 선언을 포함한 모든 선언문을 찾아 먼저 실행한 뒤 평가 과정이 끝나면 모든 선언문을 제외한 소스 코드를 한 줄씩 출력한다.

요약하자면 변수 선언이 어디에 있든 자바스크립트 엔진은 얘를 가장 먼저 실행해서 어디에서든지 변수를 참조할 수 있다. ✨

🔎 변수 호이스팅

변수 선언문이 코드의 선두로 끌여 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 말한다.

console.log(score); // undefined

var score;

🔎 값의 할당

변수에 값을 저장하는 과정이다. 변수에 값을 할당할 때는 할당 연산자인 =를 사용하는데, 연산자의 오른쪽에 있는 값을 왼쪽에 있는 변수에 저장해 준다.

var score; // 변수 선언
score = 80; // 값의 할당

var score = 80; // 변수 선언과 값의 할당

🚨 주의할 점

변수 선언과 값의 할당은 실행 시점이 다르다. 변수 선언은 소스 코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행되지만, 값의 할당런타임에 실행된다. 잘 모르겠다면 에제를 보고 이해해 보자!

console.log(score); // undefined

var score; // ① 변수 선언 - 런타임 이전에 실행
score = 80; // ② 값의 할당 - 런타임에 실행

console.log(score); // 80

🤔 score가 선언되기도 전인데 왜 console.log(score)의 출력 결과가 참조 에러가 아닌 undefined일까?

바로 코드를 순차적으로 읽어 내려가는 과정(런타임) 전에 먼저 실행이 되었기 때문이다! 그래서 값을 할당할 때는 이미 scoreundefined라는 값을 가지고 있는 상태이고, 이걸 런타임 과정에서 80으로 변경(재할당)해 주는 것이다.

변경해 준다고 해서 undefined가 존재하던 공간까지 삭제해 버리는 것은 아니다. 새로운 메모리 공간을 확보해서 여기에 80을 저장해 주는 것이니 혼동하지 않도록 주의하자!

console.log(score); // undefined

var score = 80; // 변수 선언과 값의 할당

console.log(score); // 80

변수 선언과 값의 할당을 단축해서 표현해 주면 어떨까? 자바스크립트 엔진은 둘을 두 개의 문(statement)로 나누어 각각 실행해 주기 때문에 같은 결과가 나타나는 것을 확인할 수 있다!

👀 이런 것도 생각해 봐요!

console.log(score);

score = 80;
var score;

console.log(score);
출력 결과는 무엇일까? 🤔

undefined
80

차근차근 생각해 보면 정말 간단하다. 겉으로 보이는 순서 말고, 진짜 실행 순서를 생각해 보자! 변수 선언은 런타임 이전에, 값의 할당은 런타임에 실행된다. 명심 또 명심하자! ⭐️

🔎 값의 재할당

이미 값이 할당되어 있는 변수에 새로운 값을 또다시 할당해 주는 것을 말한다. 쉽게 말하자면 변수에 저장된 값을 다른 값으로 변경해 주는 것이다. 관련 예제 하나를 보자!

var score = 80; // 변수 선언과 값의 할당
score = 90; // 값의 재할당

이쯤에서 다시 변수라는 이름이 왜 붙었는지에 대해 생각해 보면, 정말 직관적이다. 언제든지 재할당이 가능하기 때문에 변수라는 이름이 붙여진 것이다. 🤩 그런데 만약 값을 재할당할 수 없다면? 이미 저장된 값을 변경할 수 없다면 그건 뭐라고 불러야 좋을까?

우리는 이런 걸 상수(constant)라고 부르기로 했어요!

상수값을 단 한 번만 할당할 수 있는 변수라고 생각하면 된다. 상수인 변수를 선언하고 싶다면 const 키워드를 이용해 선언해 주면 된다.

🤔 값의 재할당은 어떻게 이루어질까?

앞서 말했던 것처럼, 값을 변경해 준다고 해서 80이 존재하던 공간까지 삭제해 버리는 것은 아니다. 새로운 메모리 공간을 확보해서 여기에 90을 저장해 주는 것이다. 그런데 이렇게 되면 undefined80은 어떻게 되는 걸까?

undefined80은 이제 더 이상 아무도 사용하지 않으니 메모리만 덩그러니 차지하고 있는 백수 1과 2다. 그러니 아무도 필요로 하지 않는 이 둘을 누구도 내버려 둘 리가 없는데, 이걸 가비지 콜렉터가 내쫓아 준다. 즉, 자동으로 메모리에서 해제해 주는 역할을 수행한다! 🙀 이로써 메모리 누수를 방지할 수 있게 된다.

참고로 자바스크립트는 언어가 메모리 관리 기능을 담당하고 있는 매니지드 언어이기 때문에 개발자가 메모리 제어에 관여할 수 없다는 사실 또한 알아 두자!

👀 REFERNECE

모던 자바스크립트 Deep Dive 04장 변수

profile
기록의 습관화 📝

0개의 댓글