JavaScript

JavaScript | 변수는 왜 필요한가?, 어떻게 선언되고 할당되는지도 알아보자 (feat. 메모리)

sangchu 2024. 7. 31. 18:10

메모리

변수에 대해 알기 전, 먼저 메모리에 대해 간단히 짚고 넘어가겠다.

컴퓨터는 CPU를 사용해 연산하고, 메모리를 사용해 데이터를 기억한다.

 

메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체다. 메모리 셀 하나는 1Byte이며, 컴퓨터는 메모리 셀 단위로 데이터를 저장하거나 읽어들인다. 각 셀은 고유의 메모리 주소를 갖는다.

컴퓨터는 모든 데이터를 2진수로 처리한다(위 그림은 편의상 10진수로 표기했다). 숫자 값 10, 20은 임의의 메모리 주소에 저장되고 CPU는 이 값을 읽어 들여 연산을 수행한다. 연산 결과인 30도 메모리의 임의의 주소에 저장된다.

 

자, 이제 연산이 끝났고 나는 연산 결과인 숫자 30을 이용해 어떠한 작업을 하고 싶다.

하지만, 연산 결과가 메모리에 저장되었지만 재사용을 할 수가 없다.

 

메모리 주소를 통해 값에 직접 접근하는 방법이 있지만, 실수로 운영체제가 사용하고 있는 값을 변경하는 등 치명적 오류를 발생시킬 가능성이 높다. 또한 값이 저장될 메모리 주소는 코드가 실행될 때 메모리의 상황에 따라 임의로 결정된다.

즉, 코드가 실행될 때마다 값이 저장될 메모리 주소는 변경된다. 따라서 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다.

 

여기서 변수의 필요성이 대두된다.

 

변수

변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체, 또는 그 메모리 공간을 식별하기 위해 붙인 이름을 말한다. 이는 컴파일러 혹은 인터프리터에 의해 값이 저장된 메모리 공간의 주소로 치환되어 실행된다.

따라서 개발자가 직접 메모리 주소를 통해 값을 저장하고 참조할 필요 없이, 변수를 통해 안전하게 값에 접근할 수 있다.

관련 용어를 정리하자면 다음과 같다.

  • 변수 이름: 메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름
  • 변수 값: 변수에 저장된 값
  • 할당(= 대입, 저장): 변수에 값을 저장하는 것
  • 참조: 변수에 저장된 값을 읽어 들이는 것

 

변수 선언

변수 선언은 변수를 생성하는 것을 말한다. 변수를 사용하려면 반드시 선언이 필요하다.

var, let, const 키워드를 사용해서 선언할 수 있다.

 

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

  1. 선언 단계: 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
  2. 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다. (이는 호이스팅 개념과 관련이 있다. 추후 관련해서 포스팅하겠다.)

만약 초기화 단계를 거치지 않으면 확보된 메모리 공간에는 이전에 다른 애플리케이션이 사용했던 값이 남아있을 수 있는데, 이러한 값을 쓰레기 값(garbage value)이라 한다.

 

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

 

값의 할당과 재할당

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

 

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

따라서 위 코드처럼 변수 선언과 값의 할당을 하나의 문장으로 단축 표현해도 js 엔진은 2개의 문으로 나누어 각각 실행한다.

이때, 할당 할때는 이전 값 undefined가 저장되어 있던 메모리 공간이 아닌, 새로운 메모리 공간을 확보하고 그곳에 할당 값을 저장한다.

 

재할당이란 이미 값이 할당되어 있는 변수에 새로운 값을 또다시 할당하는 것을 말한다.

참고로 값을 재할당 할 수 없다면, 즉, 값을 한 번만 할당할 수 있는 것은 변수가 아니라 상수다.

재할당 후, score 변수의 이전 값인 undefined와 80은 어떤 식별자와도 연결되어 있지 않다. 이러한 불필요한 값들은 가비지 콜렉터에 의해 메모리에서 자동 해제된다. 단, 언제 해제될지는 예측할 수 없다.

 

💡 C언어 같은 저수준 언어에서는, 메모리 관리를 위해 malloc()과 free() 같은 제어 기능을 제공한다. 따라서 메모리 제어를 통해 최적의 성능을 확보할 수 있지만, 치명적 오류를 생산할 가능성도 있다. javascript 같은 고수준 언어에서는 개발자가 명시적으로 메모리를 제어할 수 없으며, 가비지 콜렉터가 자동으로 관리해준다.

 

참고

모던 자바스크립트 deep dive 책

 

+ javascript에서 메모리 성능을 관리하는 방법과 가비지 콜렉터의 원리를 파악하는데 참고하기 좋은 자료

https://velog.io/@sejinkim/자바스크립트의-메모리-관리-설명