본문 바로가기
Frontend/javascript

[js] 표현식과 문, 데이터 타입

by Lizzie Oh 2026. 3. 11.

1. 값(Value)

= 식(expression)이 평가(evaluate)되어 생성된 결과

10 + 20  // 이 식이 평가되면 → 값 30
'hello'  // 이것도 식 → 평가되면 문자열 값 'hello'

 

  • 모든 값은 데이터 타입을 가짐 — 변수가 타입을 가지는게 아닌, 변수의 값이 타입을 가지는 것 
  • 모든 값은 메모리에 비트(bit)의 나열로 저장 

같은 비트열이라도 타입에 따라 해석이 다름 → 데이터타입: 메모리에서 읽은 비트열의 해석을 결정 

0100 0001
→ 숫자 타입으로 해석하면: 65
→ 문자 타입으로 해석하면: 'A'

 


2. 변수(Variable) 

변수 = 값을 저장하기 위해 확보한 메모리 공간, 또는 그 공간을 가리키는 식별자(identifier)

var score = 100;

변수에는 을 할당하는 것. 식(expression)을 할당하는 게 아님.

 

var score = 10 + 20;이라고 쓰면, 10 + 20이라는 식이 먼저 평가되어 값 30이 되고, 그 값 30이 변수에 저장됨.

 

3. 문(Statement)과 표현식(Expression)

문(statement) = 프로그램을 구성하는 기본 단위이자 최소 실행 단위

var x = 5;      // 변수 선언문
if (x > 3) {}   // 조건문
for (;;) {}      // 반복문

 

표현식(expression) = 값으로 평가될 수 있는

5 + 3        // → 8
getName()    // → 반환값
x = 10       // 할당 자체도 10으로 평가되는 표현식!

 

표현식인 문 vs 표현식이 아닌 문

브라우저 콘솔에서 직접 확인 가능: 값으로 평가되면 표현식 (표현식이 아닌 문은 값을 생성하지 않으므로 undefined가 암묵적으로 반환)

> var x = 5;
← undefined     // 변수 선언문은 값을 생성하지 않음 → undefined

> x = 10;
← 10            // 할당 표현식은 값을 생성 → 10

> 1 + 2;
← 3             // 표현식이므로 평가 결과 출력

콘솔에서 undefined가 뜨느냐 마느냐의 차이 = 해당 문이 표현식인지 아닌지

ASI (Automatic Semicolon Insertion)

JS 기능 중  문의 끝이라고 예측되는 지점에 세미콜론을 자동 삽입 
'예측' 이기 때문에 틀리기도 함 

function foo() {
  return
    { name: 'bar' }
}
// ASI에 의해 return 뒤에 세미콜론 삽입!
// 실제로는 return; → undefined 반환

 

 

4. 데이터 타입

숫자 타입 — 모든 수는 실수

자바스크립트에는 하나의 숫자 타입(number)만 존재하고, 이는 IEEE 754 배정밀도 64비트 부동소수점 형식, 즉 모든 수는 '실수'

 

 

 

null과 undefined — 닮았지만 다름

둘 다 "값이 없음"을 나타내지만 의미가 다름:

  undefined null
의미 초기화되지 않음 (시스템적) 의도적으로 비어있음 (개발자 의사)
누가 쓰나 JS 엔진이 자동으로 부여 개발자가 명시적으로 할당
typeof 'undefined' 'object' (버그!)

 

### typeof null은 왜 'object' 일까?

이는 JS 초창기(1995년)의 구현 버그.  수정 제안이 여러 번 있었지만, 이미 너무 많은 웹사이트가 이 동작에 의존 → 하위 호환성 때문에 영원히 수정 불가.

 

컨벤션: 변수에 "값이 없음"을 표현하고 싶다면 undefined가 아닌 null 사용하는게 좋다 

-> 없는 값을 표현하고자 할때 이유를 알고 쓰는 것에서 개발자의 효능감이 높아진다고 생각 🙃

 

원시 타입은 변경 불가능(Immutable)

원시 타입(string, number, boolean, null, undefined, symbol, bigint)의 값 = 한번 생성되면 변경 불가 (immutable)

 

"변수의 값이 바뀐 것"과 "값 자체가 변경된 것"은 전혀 다른 이야기. 변수는 새로운 값을 가리킬 수 있지만, 메모리에 있던 'hello'라는 값 자체는 불변. 기존 'hello'는 어떤 변수도 참조하지 않게 되면 가비지 컬렉터가 회수.

 

이게 저번 주에 공부한 '변수' 에서 재할당 할때 다른 메모리 셀에 값을 저장하고 참조를 바꾸는 것과 일치하는 것 같다. 그러면 객체도 재할당 할때는 새로운 값에 하려나..? 이건 뒤에를 공부 해봐야 알겠다. ..

 

 

============================================================================

 

5.  JS는 값을 어떻게 읽을까?

변수에 접근하면 JS 엔진은 값이 저장된 메모리 공간의 선두 셀을 찾아감. 그런데 몇 바이트를 읽어야 하는지 어떻게 알까?

심볼 테이블(Symbol Table)

엔진이 코드를 파싱/컴파일하는 단계에서 생성하는 식별자 관리 테이블:

식별자 이름  |  스코프  |  선언 키워드  |  저장 위치
────────────────────────────────────────────
a           |  전역    |  let         |  슬롯 0번
b           |  함수1   |  const       |  슬롯 1번

변수 이름 → 실제 저장 위치를 매핑하는 사전 같은 것. JS만의 개념이 아니라 거의 모든 언어의 컴파일러/인터프리터가 사용하는 범용 개념.

변수 슬롯(Variable Slot)

심볼 테이블이 가리키는 실제 값이 저장되는 고정 크기(64비트) 공간:

심볼 테이블                    변수 슬롯 (메모리)
┌──────────┐                 ┌─────────────────┐
│ a → 슬롯0 │  ──────────▶   │ 슬롯0: 64비트 값  │
│ b → 슬롯1 │  ──────────▶   │ 슬롯1: 64비트 값  │
└──────────┘                 └─────────────────┘

태그드 포인터(Tagged Pointer) — V8 엔진의 트릭

V8(Chrome, Node.js)은 슬롯에 담긴 64비트 값의 마지막 1비트로 타입 판별:

  • 마지막 비트 0Smi(Small Integer): 나머지 63비트가 곧 정수 값. 힙 할당 없이 슬롯 안에 직접 저장.
  • 마지막 비트 1힙 객체 포인터: 나머지 63비트는 힙 메모리 주소. 그 주소의 객체 헤더에 상세 타입 정보 존재.
슬롯 값: ...0  →  Smi (정수값이 슬롯에 직접 저장)
슬롯 값: ...1  →  힙 포인터 (문자열, 객체 등은 힙에서 관리)

이 1비트 트릭 덕분에 정수 연산은 힙 할당 없이 빠르게, 복잡한 객체는 힙에서 유연하게 관리. 성능과 유연성의 균형을 맞추는 영리한 설계.

 

참고: 태그드 포인터는 V8의 구현 방식. JS 스펙에 정의된 것이 아니므로, SpiderMonkey(Firefox)나 JavaScriptCore(Safari) 등은 다른 방식을 쓸 수 있음.


6. 동적 타이핑(Dynamic Typing)

자바스크립트의 변수는 선언 시점이 아니라 할당 시점에 타입 결정


7. 기타 — 줄바꿈 문자의 차이

텍스트 파일에서 "새로운 줄"을 나타내는 방식이 OS마다 다름:

OS 줄바꿈 문자 ASCII 코드
Windows CR+LF (\r\n) 13 + 10
Unix/Linux/macOS LF (\n) 10

 

Git이 warning: LF will be replaced by CRLF 경고를 내는 이유가 바로 이것. 협업 시 git config core.autocrlf 설정으로 통일 권장.

댓글