Skip to Content

4장 변수

4-1. 변수의 개념과 필요성

변수의 본질을 이해하기 위해 컴퓨터가 연산을 수행하는 과정을 살펴보자.

다음 자바스크립트 코드를 실행한다고 가정하자.

10 + 20;

인간의 연산 과정:

  1. 10, 20, +의 의미를 인지하고 해석
  2. 두 피연산자를 단기 기억에 보관
  3. 덧셈 수행 후 결과값 30을 기억

컴퓨터의 연산 과정:

컴퓨터는 CPU와 메모리의 협업으로 연산을 수행한다.

  1. 메모리 구조

    메모리는 데이터를 저장할 수 있는 메모리 셀들의 집합체

    image.png

    • 각 메모리 셀의 크기: 1바이트(8비트)
    • 모든 데이터는 2진수 형태로 저장
    • 각 셀은 고유한 메모리 주소 보유
    • 모든 접근(저장/읽기)은 셀 단위로 수행
  2. 연산 수행

    • 10과 20을 메모리에 저장
    • CPU가 저장된 값들을 읽어와 덧셈 수행
    • 연산 결과 30을 새로운 메모리 공간에 저장

    또다른 메모리 셀에 30이 저장된다

자바스크립트의 메모리 접근 제약

JS는 연산 결과를 재사용하기 위해 메모리 주소에 직접 접근할 수 없다.

→ C, C++과 달리 포인터를 통한 직접 접근 불가

이유:

  • 동일한 코드 실행 시 메모리 주소는 매번 변경될 수 있음
  • 직접 접근은 시스템 안정성과 보안에 위협
  • 메모리 관리 복잡성으로부터 개발자를 보호

변수를 통해 값에 간접적으로 접근

4-1-1. 변수의 정의

변수(Variable): 하나의 값을 저장하기 위해 확보한 메모리 공간, 또는 그 공간을 식별하기 위해 붙인 이름

→ 본질적으로 값의 위치를 가리키는 식별자

변수를 활용한 코드 작성:

var result = 10 + 20;

변수의 구성 요소:

  • 변수명(Variable Name): 메모리 공간에 붙인 이름
    ex) result
  • 변수값(Variable Value): 변수에 저장된 값
    ex) 30
  • 할당(Assignment): 변수에 값을 저장 (메모리 쓰기, Write)
    ex) result에 30 저장
  • 참조(Reference): 변수에 저장된 값을 읽기 (메모리 읽기, Read)
    ex) result에 저장된 30 읽기

image.png

⇒ 변수를 통해 메모리 주소를 직접 다루지 않고도 값을 안전하게 저장하고 참조 가능

4-2. 식별자의 개념

식별자(Identifier): 어떤 값이 저장된 메모리 주소를 가리키는 이름

핵심: 식별자는 값 자체가 아닌 메모리 주소를 기억

값은 구별하지 못 하고 메모리 주소를 구별한다.

식별자의 범위

  • 변수명
  • 함수명
  • 클래스명
  • 메모리 상에 존재하는 모든 값의 이름

식별자의 특성:

  • 네이밍 규칙 준수 필수
  • 선언(Declaration)을 통해 JS 엔진에 존재 알림
  • 이름만으로 값의 의미 파악 가능해야 함

⇒ 변수명은 클린 코드의 시작점 - 신중한 명명 필요

4-3. 변수 선언

변수 선언(Variable Declaration): 변수 생성

→ 값을 저장할 메모리 공간 확보 + 변수 이름과 메모리 주소 연결

4-3-1. 변수 선언 키워드

JS의 변수 선언 키워드: var, let, const

(let, const는 ES6 추가 - 뒤에서 자세히 다룸)

var로 변수 선언하기

var 키워드는 선언과 초기화 단계가 동시에 진행

  1. 선언 단계: 변수 이름 등록 → 메모리 공간 확보

    var score;
  2. 초기화 단계: JS 엔진이 암묵적으로 undefined 할당

    image.png

→ 쓰레기 값(Garbage Value)으로 인한 에러 방지

4-3-2. 선언되지 않은 식별자 참조

선언되지 않은 식별자 접근 시 → ReferenceError 발생

→ 해당 이름으로 등록된 식별자를 찾을 수 없다는 의미

console.log(undeclaredVariable); // ReferenceError: undeclaredVariable is not defined

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

변수 호이스팅(Variable Hoisting): 변수 선언문이 코드 선두로 끌어올려진 것처럼 동작하는 JS 고유 특징

예제 1) 선언 전 참조

console.log(score); // undefined var score;

일반 언어라면 에러 발생 예상 → 하지만 JS는 undefined 출력

호이스팅 발생 이유:

JS 엔진은 코드 실행 전 소스코드 평가 과정을 거침

→ 평가 과정에서 모든 선언문을 찾아 먼저 실행

→ 변수 선언이 코드 어디에 있든 다른 코드보다 먼저 실행

예제 2) 선언 전후 참조

console.log(x); // undefined (선언됨, 할당 안됨) var x = 100; console.log(x); // 100 (할당 후)

위 코드는 JS 엔진에 의해 다음과 같이 해석:

var x; // 선언 및 초기화 (호이스팅) console.log(x); // undefined x = 100; // 할당 console.log(x); // 100

var 키워드: 선언과 초기화 동시 진행 → 호이스팅 시점에 undefined 값 보유

4-4-1. let과 const의 호이스팅

let, const도 호이스팅 발생 → 하지만 var와 다른 방식으로 동작

console.log(b); // ReferenceError: Cannot access 'b' before initialization let b = 20; console.log(c); // ReferenceError: Cannot access 'c' before initialization const c = 30;

let과 const의 특징:

  • 선언은 호이스팅 O, 초기화는 호이스팅 X
  • 선언부터 초기화까지 = 일시적 사각지대(Temporal Dead Zone, TDZ)
  • TDZ 구간에서 접근 시 ReferenceError 발생
  • 블록 레벨 스코프 적용 - 블록 내에서만 접근 가능

var의 문제점 개선을 위해 설계됨

4-5. 값의 할당

변수에 값 할당: 할당 연산자 = 사용

→ 우변의 값을 좌변의 변수에 할당

var score = 80;

변수 선언과 값 할당의 실행 시점:

  • 변수 선언: 소스코드 평가 과정에서 실행 (호이스팅)
  • 값 할당: 런타임(Runtime)에 순차적으로 실행

실행 예제:

console.log(score); // undefined (선언은 호이스팅됨) var score; // 선언 score = 80; // 할당 (런타임에 실행) console.log(score); // 80

주목할 예제:

console.log(score); // undefined score = 80; // 할당이 먼저 작성됨 var score; // 선언이 나중에 작성됨 console.log(score); // 80

image.png

선언과 할당의 순서가 코드상에서 바뀌어도 결과는 동일

→ 선언은 항상 호이스팅되어 먼저 실행되기 때문

4-6. 값의 재할당

4-6-1. 재할당의 개념

재할당(Reassignment): 이미 값이 할당된 변수에 새로운 값을 할당

→ 기존 값을 버리고 새 값으로 교체

재할당 가능 여부:

  • var, let: 재할당 가능 (변수, Variable)
  • const: 재할당 불가능 (상수, Constant)
let mutableValue = 10; mutableValue = 20; // 재할당 가능 const immutableValue = 10; immutableValue = 20; // TypeError: Assignment to constant variable

4-6-2. 재할당의 내부 동작 원리

image.png

재할당 과정:

  1. 변수 score: 처음 undefined로 초기화된 메모리 공간 가리킴
  2. score = 80 할당: 새 메모리 공간 확보 → 80 저장 → score가 새 공간 가리킴
  3. score = 90 재할당: 또 다른 메모리 공간 확보 → 90 저장 → score가 이 공간 가리킴

핵심:

  • 재할당 = 변수가 가리키는 메모리 주소 변경
  • 이전 값의 메모리 공간 → 더 이상 참조 안 됨
  • 참조 안 되는 메모리 → 가비지 컬렉터(Garbage Collector)가 자동 해제
  • 메모리 해제 시점은 예측 불가, 개발자가 직접 제어 불가

가비지 컬렉션(Garbage Collection)

애플리케이션이 할당한 메모리 공간을 주기적으로 검사

→ 더 이상 사용되지 않는 메모리 자동 해제

→ 메모리 누수 방지 + 효율적 메모리 관리

4-7. 식별자 네이밍 규칙

좋은 변수명 = 코드 의도 명확 전달 + 유지보수성 향상

네이밍 규칙 (Naming Rules):

  1. 식별자는 문자, 숫자, 언더스코어(_), 달러($)만 포함 가능
  2. 숫자로 시작 불가 (첫 문자: 문자, _, $ 중 하나)
  3. 예약어(Reserved Word)  사용 불가

올바른 예:

var firstName; var _privateVar; var $jquery; var value1;

잘못된 예:

var 1stPlace; // 숫자로 시작 var my-var; // 하이픈 사용 불가 var for; // 예약어 사용 불가

4-7-1. 네이밍 컨벤션

네이밍 컨벤션(Naming Convention): 일관된 코딩 스타일 유지를 위한 명명 규약

주요 유형:

  1. 카멜 케이스(camelCase) - 변수, 함수명

    let userName; let getUserInfo;
  2. 파스칼 케이스(PascalCase) - 생성자 함수, 클래스명

    class UserAccount; function Person() {}
  3. 스네이크 케이스(snake_case) - 주로 DB 필드명

    let user_name;
  4. 헝가리언 케이스(Hungarian Case) - 타입 접두사 (현대 개발에서 비권장)

    let strUserName; // str: string 타입

권장 사항:

  • JS: 변수/함수 → 카멜 케이스, 생성자/클래스 → 파스칼 케이스
  • 일관성 유지가 가장 중요
  • 변수명으로 용도와 의미 명확히 전달

학습 점검 문제

문제 1: 호이스팅의 이해

다음 코드의 실행 결과를 예측하고, 그 이유를 설명하시오.

console.log(a); console.log(b); console.log(c); var a = 1; let b = 2; const c = 3;

해답 보기

실행 결과:

  • console.log(a): undefined 출력
  • console.log(b): ReferenceError 발생
  • console.log(c)는 실행되지 않음 (이전 라인에서 에러 발생)

이유:

  • var a는 호이스팅되며 undefined로 초기화됨
  • let bconst c도 호이스팅되지만 TDZ에 있어 초기화 전 접근 시 에러 발생

문제 2: 재할당과 메모리

다음 코드가 실행될 때 메모리에서 일어나는 일을 설명하시오.

let value = 10; value = 20; value = 30;

해답 보기

  1. let value 선언 시 메모리 공간 확보
  2. value = 10 할당 시 첫 번째 메모리 공간에 10 저장
  3. value = 20 재할당 시 새로운 메모리 공간 확보 후 20 저장, value는 새 공간 참조
  4. value = 30 재할당 시 또 다른 메모리 공간 확보 후 30 저장, value는 이 공간 참조
  5. 10과 20이 저장된 메모리 공간은 더 이상 참조되지 않아 가비지 컬렉션 대상이 됨

문제 3: 식별자와 값

다음 중 올바른 설명을 모두 고르시오.

A. 식별자는 값 자체를 저장한다. B. 식별자는 메모리 주소를 기억한다. C. 변수명은 식별자의 한 종류이다. D. 함수명은 식별자가 아니다.

해답 보기

정답: B, C

  • A (X): 식별자는 값이 아닌 메모리 주소를 저장함
  • B (O): 식별자의 핵심 개념
  • C (O): 변수명, 함수명, 클래스명 모두 식별자
  • D (X): 함수명도 식별자에 해당함

문제 4: const의 특성

다음 코드에서 에러가 발생하는 라인과 그 이유를 설명하시오.

const obj = { value: 10 }; obj.value = 20; obj = { value: 30 };

해답 보기

에러 발생 라인: 3번째 줄

이유:

  • const는 재할당을 금지함
  • 2번째 줄은 객체의 프로퍼티를 변경하는 것이므로 허용됨 (재할당이 아님)
  • 3번째 줄은 obj 자체에 새로운 객체를 재할당하려 하므로 TypeError 발생

문제 5: 실무 시나리오

다음 중 가장 적절한 변수 선언 방법과 그 이유를 설명하시오.

// 시나리오 1: 사용자의 나이를 저장 (값이 변경될 수 있음) // 시나리오 2: 원주율 파이(π) 값 저장 // 시나리오 3: 반복문의 카운터 변수

해답 보기

시나리오 1: let age = 25;

  • 나이는 변경될 수 있으므로 재할당 가능한 let 사용

시나리오 2: const PI = 3.14159;

  • 상수 값이므로 재할당 불가능한 const 사용
  • 상수는 대문자와 언더스코어로 표기하는 것이 관례

시나리오 3: for (let i = 0; i < 10; i++)

  • 블록 스코프가 필요한 반복문에서는 let 사용
  • var는 함수 스코프이므로 예상치 못한 동작을 유발할 수 있음

심화 학습: 실행 컨텍스트와 변수

변수가 어떻게 관리되는지 더 깊이 이해하기 위해서는 **실행 컨텍스트(Execution Context)**의 개념을 알아야 한다.

실행 컨텍스트는 코드의 실행 환경을 나타내는 추상적인 개념으로, 다음 정보를 포함한다:

  • 변수 환경(Variable Environment): 변수와 함수 선언 정보
  • 렉시컬 환경(Lexical Environment): 식별자와 값의 매핑 관계
  • this 바인딩: this 값의 결정

자바스크립트 엔진은 실행 컨텍스트를 통해 변수의 생명주기, 스코프, 호이스팅 등을 관리한다. 이는 23장에서 더 자세히 다루게 될 것이다.

Last updated on