코딩/자바스크립트

자바스크립트 변수

르네 루덴스 2021. 11. 16. 11:56

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

 

변수는 프로그래밍 언어에서 데이터를 관리하기 위한 핵심 개념입니다.

10+20 입니다

자바스크립트 엔진이 위 자바스크립트 코드를 계산하려면, 먼저 10, 20, + 라는 리터럴과 연산자(literal, operator)의 의미를 알고 있어야 하며, 10 + 20이라는 표현식(expression)의 의미도 해석(parsing)할 수 있어야 합니다.

자바스크ㅡ립트 엔진이 10+20이라는 식의 의미를 해석하면 + 연산을 수행하기 위해 먼저 +연산자의 왼쪽 숫자(10), 오른쪽 숫자(20)의 값을 기억합니다.

 

피연산자 10과 20은 2진수의 임의의 메모리 공간에 저장되고 CPU는 이 값을 읽어들여 연산을 수행합니다.

연산결과로 생성된 숫자값 30도  2진수의 임의의 메모리 공간에 저장됩니다.

 

성공적으로 연산이 끝나고 메모리에 저장되지만, CPU가 연산해서 저장된 숫자 값 30을 재사용 할 수 없다는 문제가 발생합니다. 

연산결과 30이 저장된 메모리 공간에 직접 접근하는 것 외에 방법이 없습니다. 하지만 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지는 않습니다.

 

직접적인 메모리 제어를 허용한다고 하더라도 값이 저장될 임의의 메모리 주소는 코드가 실행될 때 메모리 상황에따라 임의로 결정되기 때문에 코드가 실행되기 이전에는 값이 저장된 메모리 주소를 알 수 없으며, 알려주지도 않습니다. 따라서 직접적으로 접근하는 방식은 올바른 방법이 아닙니다.

 

변수(Variable)는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름을 말합니다. 따라서 변수를 사용하면 개발자가 직접 메모리 주소를 통해 값을 저장하고 참조할 필요가 없고 변수를 통해 안전하게 값에 접근 할 수 있습니다.

 

앞서 살펴본 코드를 변수를 사용해 다시 작성해보도록 하겠습니다.

 

var result = 10 + 20 ;

10 + 20은 연산을 통해 새로운 값 30을 생성합니다. 연산을 통해 생성된 값 30은 임의의 메모리 공간에 저장됩니다. 이 때 메모리 공간에 저장된 값 30을 다시 읽어들여 재사용 할 수 있도록 값이 저장된 메모리 공간의 주소에 result라는 이름을 붙인 것이 변수입니다.

 

메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름을 '변수'라고 합니다.

변수에 저장된 값을 '변수값'이라고 하며, 변수에 저장된 값을 읽어 들이는 행위를 참조(reference)라고 합니다. 

변수 이름을 사용해 참조(reference)를 요청하면 자바스크립트 엔진은 변수 이름과 매핑된 메모리 주소를 통해 메모리 공간에 접근해서 저장된 값을 반환합니다. 사람이 이해할 수 있는 언어로 명명한 변수 이름을 통해 저장된 값의 의미를 명확히 파악할 수 있습니다.

 

변수에 저장된 값의 의미를 파악 할 수 있는 변수 이름은 가독성을 높이는 부수적인 효과가 있기 때문에 변수 이름을 지으실 때 신중하게 이름을 지어야 합니다.

 

식별자

변수의 이름을 식별자(identifier)라고도 합니다. 식별자는 어떤 값을 구별해서 식별 할 수 있는 고유한 이름을 말합니다. 식별자는 메모리 공간에 저장되어 있는 어떤 값을 식별해낼 수 있어야 합니다. 식별자는 어떤 값이 저장되어 있는 메모리 주소를 기억(저장)해야 합니다.

위 코드에서 식별자 result는 값 30을 식별할 수 있어야 합니다. 이를 위해 식별자 result는 값이 30이 저장되어 있는 메모리 주소를 기억해야 합니다. 즉, 식별자는 값이 저장되어 있는 메모리 주소와 매핑관계를 맺으며 이 매핑 정보도 메모리에 저장되어야 합니다. 

 

식별자는 값이 아니라 메모리 주소를 기억하고 있습니다.

 

식별자로 값을 구별해서 식별한다는 것은 식별자가 기억하고 있는 메모리 주소를 통해 메모리 공간에 저장된 값에 접근 할 수 있다는 의미이며 식별자는 메모리 주소에 붙인 이름이라고 할 수 있습니다.

 

식별자라는 용어는 변수 이름에만 국한되는 것이 아니라 변수, 함수, 클래스 등의 이름역시 모두 식별자입니다. (메모리 상에 존재하는 어떤 값을 식별 할수 있는 이름은 모두 식별자입니다.)

 

변수, 함수, 클래스 등의 이름과 같은 식별자는 네이밍 규칙을 준수해야하며 선언(declaration)에 의해 자바스크립트 엔진에 식별자의 존재를 알립니다.

 

변수 선언

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

 

변수 선언에 의해 확보된 메모리 공간은 확보가 해제 되기 전까지는 누구도 확보된 메모리 공간을 사용할 수 없도록 보호되므로 안전하게 사용할 수 없습니다.

 

변수를 사용하려면 반드시 선언이 필요합니다. 변수를 선언할 때는 var, let, const 키워드를 사용합니다.

 

var score;

변수 이름(score)를 등록하고 값을 저장할 메모리 공간을 확보합니다.

아직 변수에 값을 할당하지 않았습니다. 따라서 식별자 score가 가리키는 메모리 공간에는 undefined라는 값이 암묵적으로 할당되어 초기화 됩니다.

 

자바스크립트 엔진은 변수 선언을 다음과 같은 2단계에 거쳐 수행합니다.

 

1. 선언단계 : 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알립니다.

2. 초기화 단계 : 값을 지정하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당합니다.

 

일반적으로 초기화란 변수가 선언된 이후 최초로 값을 할당하는 것을 말합니다. var키워드로 선언한 변수는 어떠한 값도 할당하지 않아도 undefined라는 값을 갖습니다. 

 

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

 

변수나 식별자를 사용하려면 선언이 필요합니다. 만약 선언한지 않은 식별자에 접근하면 참조에러(ReferenceError)가 발생합니다. 식별자를 통해 값을 참조하려 했지만 자바스크립트 엔진이 등록된 식별자를 찾을 수 없을 때 발생하는 에러입니다.

 

 

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

console.log(score); var score;

console.log가 실행될 시점에서는 아직 score 변수의 선언이 실행되지 않으므로 참조에러가 발생한 것 처럼 보일 수 있지만, 그렇지 않습니다. 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점(런타임)이 아니라 그 이전 단계에서 먼저 실행되기 때문입니다.

 

자바스크립트 엔진은 소스코드를 한 줄 씩 순차적으로 실행하기에 앞서 먼저 소스코드의 평가과정을 거치면서 소스코드를 실행하기 위한 준비를 합니다. 이 때 자바스크립트 엔진은 변수 선언을 포함한 모든 선언문 (변수 선언문, 함수 선언문 등)을 소스코드에서 찾아내 먼저 실행합니다. 

 

평가과정이 끝나면 변수 선언을 포함한 모든 선언문을 제외하고 소스코드를 한 줄씩 순차적으로 실행합니다. 변수 선언이 소스코드가 어디에  위치하는지와 상관없이 어디서든지 변수를 참조 할 수 있습니다.

 

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

 

사실 변수 선언뿐만 아니라 var, let, const, function, class 키워드를 사용해서 선언하는 모든 식별자(변수, 함수, 클래스)는 호이스팅 된다. 모든 선언문은 런타임 이전 단계(평가과정)에서 실행되기 때문입니다.

 

값의 할당

변수에 값을 할당(assignment)할 때는 할당 연산자 = 를 사용합니다.

할당 연산자는 우변의 값을 좌변의 변수에 할당합니다.

var score; score=80;

변수 선언과 값의 할당을 하나의 문(statement)으로 단축 표현 할 수 있습니다.

var score = 80;

자바스크립트 엔진은 변수 선언과 값의 할당을 하나의 문으로 단축표현해도 변수 선언과 값의 할당을 2개의 문으로 나누어 각각 실행합니다. 이때 변수 선언과 값의 할당의 실행시점이 다르다는 점을 주의해야 합니다. 변수 선언은 소스코드가 순차적으로 실행되는 시점 런타임 이전에 실행되지만 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행됩니다.

 

score 변수에 값을 할당하는 시점에는 이미 변수 선언이 완료된 상태이며 이미 undefined로 초기화 되어 있습니다. 따라서 score 변수에 값을 할당하면 score변수의 값은 undefined에서 새롭게 할당한 숫자 값 80으로 변경(재할당)됩니다.

 

변수 선언과 값의 할당을 하나의 문으로 단축 표한 할수도 있으므로 이전 코드와 다음코드는 동일하게 동작합니다.

 

변수의 선언과 값의 할당을 하나의 문장으로 단축 표현해도 자바스크립트 엔진은 변수의 선언과 값의 할당을 2개의 문으로 나누어 각각 실행됩니다. 따라서 변수에 undefined가 할당되어 초기화되는 것은 변함이 없습니다. 

주의할 점은 변수에 값을 할당할 때는 이전값 undefined가 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당 값 80을 새롭게 저장하는 것이 아니라 새로운 메모리 공간을 확보하고 해당 메모리 공간에 할당 값 80을 저장합니다.

 

 

값의 재할당

score 변수에 새로운 값을 재할당 해보자, 재할당이란 이미 값이 할당되어 있는 변수에 새로운 값을 또 다시 할당하는 것을 의미합니다.

var 키워드로 선언한 변수는 값을 재할당할 수 있습니다.

var 키워드로 선언한 변수는 선언과 동시에 undefined로 초기화 되기 때문에 엄밀히 말하자면 변수에 처음으로 값을 할당하는 것도 사실상 재할당입니다.  재할당은 변수에 저장된 값을 다른 값으로 변경합니다. 그래서 변수라고 하는 것입니다. 만약 값을 재할당할 수 없어서 변수에 저장된 값을 변경할수 없다면 변수가 아니라 상수(constant)라고 합니다.

 

변수게 값을 재할당하면 score 변수의 값은 이전값 80에서 재할당한 90으로 변경됩니다. 처음 값을 할당했을 때와 마찬가지로 이전 값 80이 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 재할당 값 90을 저장하는 것이 아니라 새로운 메모리 공간을 확보하고 그 메모리 공간에 숫자 값 90을 지정합니다. 

 

현재 변수의 값은 90입니다. score 변수의 이전 값인 undefined와 80은 어떤 식별자와도 연결되어 있지 않습니다. 이러한 불필요한 값들은 가비지 콜렉터에 의해 메모레에서 자동으로 해제됩니다. 단, 언제 해제될지 예측할 수 없습니다.

 

 

식별자 네이밍 규칙

식별자는 어떤 값을 구별해서 식별해낼 수 있는 고유의 이름을 말합니다.

• 식별자는 특수문자를 제외한 문자, 숫자, _, $를 포함할 수 있습니다.

• 숫자로 시작하는 것을 허용하지 않습니다.

• 예약어는 식별자로 사용할 수 없습니다. ( 예약어 종류: await, break, case, class, defaul 등등... )

 

자바스크립트는 대소문자를 구별하므로 다음 변수는 각각 별개의 변수입니다.

 

각각 별개의 변수 입니다.

 

변수 이름은 변수의 존재 목적을 쉽게 이해할 수 있도록 의미를 명확히 표현해야합니다.

 

변수 선언에 별도의 주석이 필요하다면 변수의 존재 목적을 명확히 드러내지 못하는 것입니다. 네이밍 컨벤션은 하나 이상의 영어 단어로 구성된 식별자를 만들 때 가독성 좋게 단어를 한눈에 구분하기 위해 규정한 명명 규칙입니다.

 

• 변수나 함수의 이름에는 주로 camelCase 방식을 사용합니다

• 생성자 함수, 클래스의 이름에는 PascalCase 방식을 주로 사용합니다.