자바스크립트의 7가지 원시 타입과 참조 타입을 구분하고, 암묵적/명시적 형 변환의 규칙을 이해한다. typeof 연산자와 타입 체크 패턴을 익힌다.
자바스크립트의 타입 시스템
자바스크립트는 동적 타입(Dynamic Typing) 언어입니다. 변수에 어떤 타입의 값도 담을 수 있고, 타입은 값에 따라 결정됩니다. 이것은 유연성을 주지만 예상치 못한 동작을 만들기도 합니다. 타입을 정확히 이해하면 이 함정을 피할 수 있습니다.
원시 타입 7가지
원시 타입은 단 하나의 값을 가지며, 변경 불가능(immutable)합니다.
// 1. Number — 정수와 소수를 구분 없이 처리
const integer = 42;
const float = 3.14;
const negative = -7;
const big = 1e6; // 1,000,000
console.log(0.1 + 0.2); // 0.30000000000000004 (부동소수점 주의!)
// 2. String — 텍스트
const single = "Hello";
const double = "World";
const template = `${single} ${double}!`; // 템플릿 리터럴
// 3. Boolean
const isTrue = true;
const isFalse = false;
// 4. undefined — 값이 할당되지 않은 상태
let notAssigned;
console.log(notAssigned); // undefined
// 5. null — 의도적으로 비어있음을 표현
const empty = null;
// 6. Symbol — 고유하고 변경 불가한 식별자 (ES6)
const id1 = Symbol("id");
const id2 = Symbol("id");
console.log(id1 === id2); // false — 항상 고유
// 7. BigInt — 매우 큰 정수 (ES2020)
const huge = 9007199254740991n;
const bigger = huge + 1n;
참조 타입
원시 타입 외 모든 것은 참조 타입(Object)입니다.
const obj = { name: "Kim" }; // 객체
const arr = [1, 2, 3]; // 배열 (특수한 객체)
const fn = function() {}; // 함수 (특수한 객체)
const date = new Date(); // 내장 객체
원시 vs 참조 — 핵심 차이
// 원시 타입: 값 자체를 복사
let a = 10;
let b = a;
b = 20;
console.log(a); // 10 — 영향 없음
// 참조 타입: 주소(참조)를 복사
let obj1 = { value: 10 };
let obj2 = obj1; // 같은 객체를 가리킴
obj2.value = 20;
console.log(obj1.value); // 20 — 같은 객체이므로 영향받음!
typeof 연산자
typeof 42 // "number"
typeof "hello" // "string"
typeof true // "boolean"
typeof undefined // "undefined"
typeof null // "object" ← 유명한 버그! null인데 object
typeof Symbol() // "symbol"
typeof 42n // "bigint"
typeof {} // "object"
typeof [] // "object" ← 배열도 object
typeof function(){} // "function"
// 배열 체크는 Array.isArray() 사용
Array.isArray([]) // true
Array.isArray({}) // false
// null 체크
const x = null;
x === null // true (올바른 null 체크)
암묵적 형 변환 (Type Coercion)
자바스크립트가 자동으로 타입을 바꾸는 동작입니다. 예상치 못한 버그의 원천입니다.
// 문자열 + 숫자 → 문자열 연결
"5" + 3 // "53" (숫자가 문자열로 변환됨)
"5" - 3 // 2 (뺄셈은 숫자로 변환)
"5" * "3" // 15
"abc" * 2 // NaN
// Boolean 변환 (falsy 값들)
false, 0, -0, "", null, undefined, NaN // 모두 false
// 나머지는 모두 true (truthy)
// 예상치 못한 결과들
[] + [] // "" (빈 문자열)
[] + {} // "[object Object]"
!!"false" // true (비어있지 않은 문자열)
!!"0" // true (마찬가지)
Boolean(0) // false
Boolean("") // false
Boolean([]) // true — 빈 배열은 truthy!
명시적 형 변환 (Type Conversion)
// 숫자로 변환
Number("42") // 42
Number("3.14") // 3.14
Number("") // 0
Number("abc") // NaN
Number(true) // 1
Number(false) // 0
Number(null) // 0
Number(undefined) // NaN
parseInt("42px") // 42 (앞부분까지만 파싱)
parseFloat("3.14m") // 3.14
+"42" // 42 (단항 플러스 연산자)
// 문자열로 변환
String(42) // "42"
String(true) // "true"
String(null) // "null"
(42).toString() // "42"
(255).toString(16) // "ff" (16진수로 변환)
// 불리언으로 변환
Boolean(1) // true
Boolean(0) // false
!!1 // true (이중 부정)
!!"hello" // true
NaN — Not a Number
const result = "hello" * 2;
console.log(result); // NaN
console.log(typeof NaN); // "number" (NaN은 number 타입!)
// NaN 체크 — 절대 == 사용 금지
NaN === NaN // false (자기 자신과도 같지 않음!)
isNaN("hello") // true (형 변환 후 체크)
Number.isNaN("hello") // false (엄격하게 NaN인지만 체크)
Number.isNaN(NaN) // true
동등(==) vs 일치(===) 연산자
// == (느슨한 비교) — 타입 변환 후 비교
"5" == 5 // true (위험!)
0 == false // true
null == undefined // true
[] == false // true
// === (엄격한 비교) — 타입까지 일치해야 함 (항상 이걸 쓰세요)
"5" === 5 // false
0 === false // false
null === undefined // false
실무 규칙: 항상 ===을 사용하세요. ==는 null/undefined 비교 단 한 가지 케이스를 제외하면 쓸 이유가 없습니다. ESLint 설정에서 eqeqeq 규칙을 켜두면 ==를 쓸 때 경고를 받을 수 있습니다.
관련 검색어 · 자바스크립트 자료형, typeof 연산자, 암묵적 형 변환, NaN이란, == vs === 차이, 원시 타입 참조 타입