💡 아래 내용은 모던 자바스크립트 딥다이브를 공부하며 이해했던 내용을 다루고 있습니다. 혹시 틀렸거나 잘못된 정보가 있다면 알려주세요!
변수는 데이터를 저장할 수 있는 메모리 공간에 붙여진 이름입니다. 식별자라고 불리는 이름을 사용해서 해당 메모리 공간에 접근할 수 있습니다. 데이터에 이름을 붙여 재사용하기 쉽게 만듦으로써, 코드의 효율성과 가독성을 높여주기 때문에 꼭 필요하다고 할 수 있습니다.
식별자는 값이 있는 메모리의 "주소"와 연결되어 있는 값입니다. 메모리에서 식별자와 메모리의 주소 값을 key-value 쌍으로 저장하고 있고, value에 있는 메모리 공간의 주소를 찾아가면 식별자의 값이 저장되어 있는 메모리를 참조할 수 있습니다. js엔진에서 값을 직접 저장하지 않고, 메모리 공간의 주소를 저장하는 이유는 다음과 같습니다.
메모리 절약: 값이 매우 크거나 복잡한 경우, 해당 값을 모든 변수에 복사하는 것은 메모리 낭비가 될 수 있습니다. 대신, 주소를 저장하고 여러 변수가 동일한 값을 참조하도록 함으로써 메모리를 절약할 수 있습니다.
가변성 및 가용성: 값이 변경되는 경우, 해당 값을 참조하는 모든 변수에 대해 값을 변경해야 하는 번거로움이 있습니다. 그러나 주소를 저장하는 것은 여러 변수가 동일한 값을 참조하기 때문에 값의 변경이 한 곳에서 이루어져도 모든 변수에 영향을 미칩니다.
참조 관리: 참조 타입인 객체나 배열은 메모리에 저장되는 크기가 가변적입니다. 따라서 주소를 저장하는 것은 객체나 배열의 크기가 동적으로 변경될 수 있기 때문에 더 효율적입니다. 값이 직접 저장되는 경우, 크기가 변경될 때마다 모든 변수에 대한 조정이 필요하게 되어 성능 저하를 가져올 수 있습니다.
크게 소스 코드 평가, 컴파일 및 최적화, 런타임 과정으로 나눌 수 있습니다.
1. 소스코드 평가: 자바스크립트 엔진은 먼저 소스코드를 분석합니다. 자바스크립트 엔진은 코드를 한 줄씩 읽어 내려가며, 이때 함수 선언과 변수 선언을 메모리에 저장하게 됩니다. 해당 과정에서, 모든 선언문을 먼저 실행한다.(호이스팅)
2. 컴파일 및 최적화: 이 과정에서 자주 사용되는 코드는 '최적화된 코드'로 재컴파일되고, 이는 프로그램의 실행 속도를 빠르게 만듭니다.
3. 런타임: 최적화된 코드는 실행 단계, 즉 런타임에 도달하게 됩니다. 런타임은 코드가 실제로 실행되는 단계를 말합니다. 이 단계에서 함수 호출, 변수 할당 등 실제 코드의 실행이 이루어지게 됩니다.
- 선언 단계: 변수 이름, 즉 식별자를 실행 컨텍스트에 등록해서 자바스크립트 엔진에 변수의 존재를 알립니다. 이 과정에서 호이스팅이 발생합니다.
- 초기화 단계: 초기화란, 값을 저장하기 위한 메모리 공간을 확보하고, 암묵적으로 undefined를 할당해 초기화하는 과정을 뜻한다. var의 경우 선언만 하고 할당을 하지 않을 수 있기 때문에, 선언 후 할당 직전에 초기화가 이루어진다. 반면, let과 const는 선언과 할당을 같이 해야하기 때문에, 선언과 동시에 초기화가 이루어진다.
- 할당 단계: 할당 단계는 변수에 값을 대입하는 과정을 의미합니다. 변수 선언이 공간을 확보하는 과정이라면, 할당은 그 공간에 특정 값을 집어넣는 과정입니다.
식별자는 변수, 함수, 클래스 등의 이름을 의미합니다. 즉 코드 안의 변수나 함수 등의 요소를 구별하고, 식별할 수 있게 하는 이름입니다.
식별자 없이 직접적으로 값인 32나 "name"을 사용하게 되면, 이 값들은 리터럴(literal)이라고 부릅니다. 리터럴은 코드 내에서 직접 사용되는 값을 말합니다. 이러한 리터럴들은 해당 타입에 따라 메모리에 저장되며, 코드가 실행될 때 바로 해석됩니다. 예를 들어,
console.log(32);
에서 32는 숫자 리터럴로,console.log("name");
에서 "name"은 문자열 리터럴입니다. 이러한 리터럴은 변수에 할당되지 않았기 때문에, 식별자를 통한 참조 없이 바로 값이 사용됩니다.
변수의 선언은 데이터를 저장할 수 있는 메모리 공간에 식별자에 해당하는 공간을 확보하는 과정이고, 할당은 해당 값의 식별자에 해당하는 공간에 실제 값을 key-value의 형태로 저장하는 과정입니다. 이 때, 선언된 변수가 아직 값을 할당받지 않은 상태라면
undefined
로 처리합니다.
변수 선언은 소스 코드 평가 단계에서 다른 코드들보다 먼저 실행되며,
이렇게 선언부만 따로 실행되어 해당 코드들이 위로 끌어올려진 것처럼 보이는 현상을 호이스팅이라고 합니다.
변수의 의미는 그것이 속한 실행 문맥(Execution Context)과 어휘적(Lexical) 문맥에 따라 결정되며, 이 때 동일 범위(실행 문맥)의 모든 선언을 참조(호이스팅)하여 그 의미를 정의합니다. 그렇기 때문에 JS에서는 모든 선언을 끌어올려 의미를 정하기 위해 호이스팅이라는 개념을 도입하게 되었습니다.
자바스크립트에서 값의 할당은 등호(=) 연산자를 사용하여 이루어집니다. 변수에 값이 할당되는 경우, 그 값은 변수의 이름과 메모리 주소 사이에 연결됩니다.
var
와let
을 통한 선언의 경우, 선언과 할당을 분리해서 할 수 있지만,const
의 경우, 선언과 할당을 한 번에 해야합니다.
값의 할당은 소스 코드 평가, 컴파일 및 최적화, 런타임 과정 중 런타임 과정에서 코드가 실행되고 할당이 이루어집니다.
재할당은 식별자가 가리키는 메모리 공간에 새로운 값을 저장하는 작업을 의미합니다. 이 과정에서 변수가 가리키는 메모리 공간의 값이 갱신되므로, 이후에는 새로운 값이 사용됩니다.
변수가 이전 값에서 새로운 값으로 변경되지만, 이전 값이 어떻게 처리되는지는 자바스크립트 엔진의 내부 동작에 따라 달라집니다. 이전 값이 자동으로 메모리에서 해제되지 않을 수도 있고, 가비지 컬렉션에 의해 메모리에서 해제될 수도 있습니다. 핵심은, 자바스크립트 엔진의 내부 로직에 의해 "자동으로 처리된다."는 것입니다.
식별자 네이밍 규칙은 변수, 함수, 객체 등에 사용되는 식별자(이름)를 지정할 때 따라야 하는 규칙입니다. 주요한 식별자 네이밍 규칙은 다음과 같습니다:
- 의미 전달: 식별자는 해당하는 개념이나 역할을 명확하게 전달해야 합니다.
- 일관성: 코드베이스 전체에서 일관된 네이밍 스타일과 규칙을 유지해야 합니다. 같은 종류의 개념이라면 유사한 네이밍 패턴을 사용하는 것이 좋습니다.
- 길이와 가독성: 식별자는 충분히 의미를 전달하면서도 간결하게 작성되어야 합니다. 너무 긴 식별자는 가독성을 저하시킬 수 있으므로 적절한 길이를 유지해야 합니다.
- 피해야 할 약어와 축약형: 약어나 축약형은 가독성을 저하시킬 수 있으므로 피하는 것이 좋습니다. 가능한한 명확하고 의미를 전달하는 단어를 선택해야 합니다.
- 올바른 철자와 문법: 식별자의 철자와 문법은 정확해야 합니다. 오타나 잘못된 문법은 코드를 해석하는 데 혼동을 줄 수 있습니다.
- 의미 있는 구분: 비슷한 기능이나 의미를 가지는 식별자들은 구분할 수 있도록 네이밍을 해야 합니다. 임의로 숫자나 문자를 붙이는 것보다 의미 있는 접두사나 접미사를 사용하는 것이 좋습니다.
- 주석과 함께 사용: 식별자의 목적이나 의미를 추가적으로 설명할 필요가 있다면 주석을 활용하는 것이 좋습니다. 식별자 자체로도 이해가 쉽도록 노력해야 하지만, 주석을 통해 명확하게 설명할 수 있습니다.
참고 자료
자바스크립트는 왜 프로토타입을 선택했을까