해당 포스팅은 위키북스의 "모던 자바스크립트 Deep Dive"라는 책을 독학하며 기록하는 글입니다.


변수란 무엇인가? 왜 필요한가?

먼저, 자바스크립트에 다음과 같은 식을 사용하면 어떠한 일이 일어나는지 살펴보자.

10 + 20

자바스크립트 엔진은 10 + 20이라는 식의 의미를 해석과정 중에 +연산을 수행하기 위해 +양쪽의 피연산자를 기억한다. 여기서 사람과 다른 점은 사람은 기억과 연산을 모두 두뇌에서 하지만, 컴퓨터는 기억을 하는 부분과 연산을 하는 부분이 나눠져 있다.

CPU에서는 연산을, 메모리에서는 기억을 담당하고 있다.

메모리(memory)는 데이터를 저장할 수 있는 메모리 셀(memory cell)의 집합체로, 메모리 셀 하나의 크기는 1byte(8bit)이며, 컴퓨터는 메모리 셀의 크기 단위(1byte)로 데이터를 저장하거나 읽어들인다. 각 셀은 고유의 메모리 주소를 가지며, 이는 메모리 공간의 위치를 나타낸다. 또한 메모리에 저장되는 모든 값은 2진수로 변환되어 저장된다.
-> EX) 4GB메모리는 0부터 4,294,967,295까지의 메모리 주소를 가지며, 이는 컴퓨터에서 0x00000000~0xFFFFFFFF로 나타낸다.

그럼 이제 10과 20의 메모리 저장도 되었고, CPU를 통해서 계산된 30이라는 값도 메모리에 저장되었다. 근데 문제가 생겼다. 바로 우리가 30이라는 값을 다시 불러와 쓸 수가 없다는 것이다.

물론 30이라는 값이 저장된 메모리 주소에 직접 접근해서 가져오는 방법이 있지만, 이는 치명적인 오류를 발생시킬 가능성이 높은 위험한 일이기 때문에, 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다.

더불어 메모리의 직접 접근이 가능하다고 하더라도, 값이 저장될 메모리의 주소는 그때그때 상황에 맞게 임의로 정해지기 때문에, 매 연산마다 값이 저장되는 위치가 계속 바뀐다. 이는 코드가 실행되기 이전에는 값이 저장된 메모리의 주소를 알 수 없으며, 사용자가 사용할 수 없음을 의미한다.
-> 즉, 옳은 방법이 아니다.

따라서, 프로그래밍 언어는 저장된 값을 읽어 들여 재사용하기 위해 변수라는 메커니즘을 제공하며 그 정의는 다음과 같다.

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

간단하게 말하면 값의 위치를 가리키는 상징적인 이름으로 실행시 컴파일러나 인터프리터에 의해 값이 저장된 메모리 공간의 주소로 치환된다.

  1. 변수 명 - 메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름
  2. 변수 값 - 변수에 저장된 값
  3. 할당 - 변수에 값을 저장하는 것
  4. 참조 - 변수에 저장된 값을 읽어 들이는 것

식별자

변수 이름은 식별자(identifier)라고도 한다. 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말하며, 어떤 값이 저장되어 있는 메모리 주소를 기억하고 있다.

즉, 변수 이름(식별자)는 값을 기억하고 있는 것이 아니라 값이 저장된 메모리 주소를 기억하고 있고, 이 메모리 주소를 통해 메모리 공간에 저장된 값에 접근할 수 있다는 것이다.

식별자는 변수 이름에만 국한해서 사용하지 않고, 함수, 클래스 등의 이름들도 모두 식별자이다. 메모리 상에 존재하는 어떤 값을 식별할 수 있는 이름은 모두 식별자라고 부른다.

변수 이름을 비롯한 모든 식별자는 자바스크립트 엔진이 소스코드를 평가하고 실행하기 위해 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 실행 컨텍스트에 등록된다. 변수 이름과 변수 값은 실행 컨텍스트 내에 키/값형식인 객체로 등록되어 관리된다.


변수 선언

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

변수를 사용하기 위해서는 반드시 선언이 필요하고, 이를 위해서 var, const, let이라는 키워드를 사용한다. const와 let은 ES6이후에 나온 키워드로 var의 부족한 점을 보완하기 위해 나왔다. 지금은 var에 대해 설명하고, 이후에 const와 let에 대한 알아보도록 하자.

var키워드는 뒤에 오는 변수 이름으로 새로운 변수를 선언할 것을 지시하는 키워드이다.

var score;

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

변수를 선언한 뒤, 아직 값을 할당하지 않았기 때문에 해당 메모리 공간이 비워져 있을 거라고 생각할 수 있는데, 이는 undefined라는 값으로 초기화되어 있고, 이게 바로 자바스크립트의 독특한 특징이다. 일반적으로 초기화란 변수가 선언된 이후 최초로 값을 할당하는 것을 말하며, var키워드로 선언한 변수는 undefined로 암묵적인 초기화가 자동 수행된다.

undefined는 자바스크립트에서 제공하는 원시 타입의 값이다.

즉, 자바스크립트는 총 두 단계를 거쳐 이루어지는데, 선언 단계(자바스크립트 엔진에 변수의 존재를 알린다.)와 초기화 단계(메모리 공간을 확보하고, 암묵적으로 undefined를 할당한다.)이다.

선언되지 않은 식별자에 접근하면 ReferenceError(참조 에러)가 발생한다.


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

자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하기에 앞서 먼저 소스코드의 평가 과정을 거치면서 소스코드를 실행하기 위한 준비를 한다. 이때, 변수 선언을 포함한 모든 선언문을 소스코드에서 찾아내 먼저 실행한다. 즉, 변수 선언은 소스코드가 한 줄씩 순차적으로 실행되는 런타임이 아니라 그 이전 단계에서 먼저 실행된다는 얘기이다.

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


값의 할당

변수에 값을 할당할 때는 할당 연산자 =를 사용한다.

var people = 10;  //우변의 값을 좌변의 변수명에 할당

물론 변수의 선언과 할당은 따로 이루어 질 수도, 함께 이루어 질 수도 있지만, 내부적으로는 나누어서 이루어진다. 즉 위의 코드는 아래의 코드와 동일하게 작동한다.

var people;
people = 10;

또한 변수의 선언과 할당은 이루어지는 시점이 다르다. 변수의 선언은 위에도 말했듯이 호이스팅에 의해 런타임 이전에 이루어지지만, 할당은 코드를 읽어 내려가는 런타임에 실행된다. 다음의 코드를 보고 확실하게 이해하자.

console.log(people);  //undefined 출력

var people = 10;

console.log(people);  //10출력

첫 번째 줄은 people이라는 변수의 값을 콘솔창에 출력하라는 뜻이다.
코드 상으로는 people이라는 변수의 선언이 다음 줄에 적혀 있어 ReferenceError가 나올 것 같지만, 변수 호이스팅에 의해 선언이 런타임 이전에 되어서 초기값인 undefined가 출력된다.
그 다음으로 people에 10이라는 값을 할당했고, 다시 console.log(people)을 통해 출력을 하면 이제 10이 나오게 된다. 이렇게 변수의 선언은 런타임 이전에, 값의 할당은 런타임에 이루어 진다는 점에 유의해야 한다.


값의 재할당

재할당이란 이미 값이 할당되어 있는 변수에 새로운 값을 또다시 할당하는 것을 말한다.
사실 엄밀히 말하면 var로 선언한 변수는 선언과 동시에 undefined로 초기화되기 때문에 처음 우리가 원하는 값을 넣을 때도 재할당이다.

만약 값을 재할당할 수 없너서 변수에 저장된 값을 변경할 수 없다면 변수가 아니라 상수라 한다. (나중에 배우겠지만, 상수를 선언하는 키워드는 const이다.)

값의 재할당에서 주의깊게 봐야 할 점은 이전에 있던 값을 지우고 새로운 값을 넣는 것이 아니라 새로운 메모리 공간을 확보하고 그 메모리 공간에 새로운 값을 넣어 변수명을 해당 메모리공간과 연결시키는 것이다. 즉, 이전의 값은 없어지는 것이 아니라 아무 식별자와도 연결되지 않은 메모리 공간, 더 이상 사용되지 않는 메모리로 변하며 "가비지"라 부른다.
값의 재할당 이해를 돕기 위한 그림 이미지 출처: https://publizm.github.io/posts/javascript/Primitive_Reference

가비지 콜렉터는 애플리케이션이 할당한 메모리 공간을 주기적으로 검사하여 더 이상 사용되지 않는 메모리(가비지)를 해제하는 기능을 말한다. 자바스크립트는 가비지 콜렉터를내장하고 있는 매니지드 언어로서 해당 기능을 통해 메모리 누수(memory leak)를 방지한다.

프로그래밍 언어는 메모리 관리 방식에 따라 언매니지드 언어매니지드 언어로 분류할 수 있다. C언어 같은 언매니지드 언어는 개발자가 명시적으로 메모리를 할당하고 해제하기 위해 malloc()free()같은 저수준 메모리 제어 기능을 제공한다. 자바스크립트 같은 매니지드 언어는 메모리의 할당 및 해제를 위한 메모리 관리 기능을 언어 차원에서 담당하고 개발자의 직접적인 메모리 제어를 허용하지 않는다.


식별자 네이밍 규칙

식별자는 다음과 같은 네이밍 규칙을 준수해야 한다. (프로그램을 위해, 같이 일하는 동료를 위해, 코드를 해석하는 다른 이들을 위해)

  1. 특수문자를 제외한 문자, 숫자, _, $를 포함할 수 있다.
  2. 숫자로 시작할 수 없다. EX) 1var = 10 (X)
  3. 예약어를 식별자로 사용할 수 없다. 자바스크립트의 키워드와 예약어 목록

또한 식별자의 네이밍에 있어서 몇 가지 암묵적인 룰이 있다.

  1. 영문을 제외한 한글이나 다른 언어도 사용할 수 있지만, 권장하지 않는다.
  2. 대소문자를 구분한다.
  3. 해당 변수의 존재 목적을 알 수 있게 작성한다.

네이밍 컨벤션은 하나 이상의 영어 단어로 구성된 식별자를 만들 때 가독성이 좋게 하기 위해 규정한 명명 규칙으로 많이 쓰이는 두 가지만 소개하겠다.

  1. 카멜 케이스: 모든 단어를 이어 쓰나, 첫 단어는 소문자로 시작하고 다음 단어부터 대문자로 시작한다.
  2. 파스칼 케이스: 모든 단어를 이어쓰고, 모든 단어의 첫 글자는 대문자이다.

자바스크립트에서는 일반적으로 변수나 함수의 이름에는 카멜케이스를 사용하고, 생성자와 클래스 이름에는 파스칼 케이스를 사용한다.

profile
I Will be Relaxed Person

0개의 댓글