원시 타입 7가지 — JavaScript의 기본 데이터
JavaScript의 7가지 원시 타입(number, string, boolean, null, undefined, Symbol, BigInt)의 특징과 typeof 동작, 원시 타입과 참조 타입의 차이를 설명합니다.
지난 글에서 let과 const의 Temporal Dead Zone이 왜 존재하는지, 그리고 어떤 상황에서 ReferenceError가 발생하는지 살펴봤습니다. 이번 글에서는 JavaScript의 자료형 체계의 기초인 **원시 타입(primitive type)**을 정리합니다.
원시 타입이란
JavaScript에서 모든 값은 원시 타입이거나 **참조 타입(객체)**입니다. 원시 타입은 가장 기본적인 데이터 형태로, **불변(immutable)**합니다. 값 자체를 직접 변경할 수 없고, 변수에 새 값을 할당할 뿐입니다.
let str = "hello";
str.toUpperCase(); // "HELLO" — 원본을 바꾸지 않음
console.log(str); // "hello" — 그대로
str = str.toUpperCase(); // 새 문자열을 변수에 재할당
console.log(str); // "HELLO"
1. number
JavaScript에는 정수와 실수를 구분하는 타입이 없습니다. 모두 IEEE 754 배정밀도 부동소수점 형식으로 저장됩니다.
typeof 42; // "number"
typeof 3.14; // "number"
typeof -0; // "number"
typeof NaN; // "number" — Not a Number도 number 타입!
typeof Infinity; // "number"
// 정수 범위
Number.MAX_SAFE_INTEGER; // 9007199254740991 (2^53 - 1)
Number.MIN_SAFE_INTEGER; // -9007199254740991
// 특수 값
isNaN(NaN); // true
isFinite(Infinity); // false
NaN은 “숫자가 아니다”라는 의미지만 typeof NaN === "number"라는 역설적 결과를 줍니다. 또 NaN !== NaN이 true이므로 ===로는 NaN을 검사할 수 없습니다. Number.isNaN() 또는 Object.is(x, NaN)을 사용하세요.
2. string
문자열은 UTF-16 코드 유닛의 시퀀스입니다. 작은 따옴표, 큰 따옴표, 백틱(템플릿 리터럴) 세 가지로 만들 수 있습니다.
const s1 = 'single';
const s2 = "double";
const s3 = `template ${1 + 1}`; // "template 2"
// 문자열은 불변
const str = "hello";
str[0] = "H"; // 조용히 무시됨 (strict: TypeError)
console.log(str); // "hello" — 바뀌지 않음
// 연결은 새 문자열 생성
const result = str + " world"; // "hello world"
3. boolean
true와 false 두 값만 갖습니다. 조건문, 논리 연산자, 비교 연산자의 결과로 자주 등장합니다.
typeof true; // "boolean"
typeof false; // "boolean"
// falsy 값들 — boolean 변환 시 false가 되는 값
Boolean(0); // false
Boolean(""); // false
Boolean(null); // false
Boolean(undefined); // false
Boolean(NaN); // false
Boolean(false); // false
// 위 6개 외의 모든 값은 truthy
4. null
null은 의도적으로 값이 없음을 나타냅니다. 프로그래머가 명시적으로 “여기에는 아무것도 없다”고 선언할 때 사용합니다.
let user = null; // 아직 사용자가 없음
typeof null; // "object" ← 유명한 버그!
typeof null === "object"는 JavaScript 초기 구현의 버그입니다. 비트 표현에서 null의 태그가 객체와 같았던 것이 원인인데, 기존 코드 호환성 때문에 수정할 수 없습니다. null 체크는 항상 === null로 해야 합니다.
5. undefined
undefined는 값이 할당되지 않음을 나타내는 JavaScript가 자동으로 부여하는 값입니다.
let x; // undefined — 선언만, 초기화 안 됨
function fn() {}
fn(); // undefined — 반환값 없는 함수
const obj = {};
obj.missing; // undefined — 존재하지 않는 프로퍼티
// null vs undefined
null === undefined; // false
null == undefined; // true (느슨한 동등)
실용적 구분:
null: 개발자가 의도적으로 비움undefined: JavaScript가 “아직 값 없음” 표시
6. Symbol (ES2015)
Symbol은 유일하고 변경 불가한 식별자를 만드는 데 사용합니다. 설명 인자는 디버깅용일 뿐, 유일성에 영향을 주지 않습니다.
const id1 = Symbol("id");
const id2 = Symbol("id");
id1 === id2; // false — 항상 다름!
// 객체 키로 사용 — 충돌 방지
const KEY = Symbol("secret");
const obj = {
[KEY]: "private data",
name: "public"
};
obj[KEY]; // "private data"
Object.keys(obj); // ["name"] — Symbol 키는 열거되지 않음
// Well-known Symbols — 언어 내장 동작 커스터마이즈
class MyCollection {
[Symbol.iterator]() { /* ... */ }
}
7. BigInt (ES2020)
number 타입은 2^53 - 1보다 큰 정수를 정확하게 표현하지 못합니다. BigInt는 임의 크기의 정수를 처리합니다.
// number의 한계
9007199254740992 === 9007199254740993; // true! (잘못된 결과)
// BigInt는 정확하게
9007199254740992n === 9007199254740993n; // false (정확함)
const huge = 9007199254740993n;
typeof huge; // "bigint"
// 주의: number와 혼용 불가
1n + 1; // TypeError
1n + 1n; // 2n (OK)
Number(1n); // 1 (변환)
typeof로 원시 타입 판별
// null을 제외한 원시 타입은 typeof로 정확히 판별
typeof 42; // "number"
typeof "hello"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof Symbol(); // "symbol"
typeof 42n; // "bigint"
// 함수는 별도
typeof function(){}; // "function"
// 객체, 배열, null은 모두 "object"
typeof {}; // "object"
typeof []; // "object"
typeof null; // "object" ← 버그
// null 정확한 체크
const isNull = (x) => x === null;
// 또는
const isObject = (x) => typeof x === "object" && x !== null;
원시 타입 vs 참조 타입
원시 타입은 값(value) 복사, 객체·배열 같은 참조 타입은 참조(reference) 복사입니다:
// 원시 타입 — 값 복사
let a = 42;
let b = a;
b = 100;
console.log(a); // 42 — 영향 없음
// 참조 타입 — 주소 복사
let obj1 = { x: 1 };
let obj2 = obj1; // 같은 객체를 가리킴
obj2.x = 99;
console.log(obj1.x); // 99 — 같은 객체!
이 차이는 함수에 인자를 넘길 때도 동일하게 적용됩니다. 원시 타입은 복사본이 전달되고, 객체는 참조가 전달됩니다.
지난 글: TDZ (Temporal Dead Zone)
다음 글: number의 IEEE 754 정밀도와 함정
읽어주셔서 감사합니다. 😊