자바스크립트는 동적 타이핑 언어로, 변수 선언 시 타입이 정해지지 않고 변수에 할당된 값(원시 값 또는 객체 값)에 의해 타입이 결정된다. 또한 자바스크립트는 약타입 언어이므로, 타입 에러 대신 암묵적 타입 변환이 발생하게 된다.
이러한 특성은 자바스크립트를 유연한 언어로 만들어 주지만, 동시에 예상치 못한 버그를 초래할 수도 있다. 예를 들어, null과 undefined의 차이를 정확히 알지 못하면 조건문에서 의도치 않은 결과를 얻을 수 있다. 또한 객체를 복사할 때 참조가 공유된다는 사실을 모른다면 한 곳에서의 변경이 예상치 못한 사이드 이펙트를 일으킬 수 있다.
따라서 자바스크립트의 데이터 타입을 제대로 이해하면 변수에 저장되는 값의 특성을 명확히 파악할 수 있어 불필요한 버그를 예방하고, 효율적인 디버깅이 가능해진다. 그렇다면 자바스크립트의 데이터 타입은 어떤 것들이 있을까?
데이터 타입
개요
자바스크립트는 동적 타이핑 언어로, 변수 선언 시 타입이 미리 결정되지 않고, 할당된 값에 따라 자동으로 타입이 결정된다. 따라서 같은 변수라도 다른 타입의 값을 가질 수 있으며, 재할당을 통해 언제든지 타입이 변경될 수 있다.
또한 약타입 언어이므로, 서로 다른 타입 간의 연산이 가능하며, 타입 에러 대신 암묵적 타입 변환이 발생한다.
이러한 특성 때문에 변수 자체는 타입을 가지지 않지만, 변수에 저장된 값은 각각 고유한 타입을 가진다.
데이터 타입의 구분
자바스크립트에서 모든 값은 데이터 타입을 가지며, 크게 원시 타입(primitive type)과 객체 타입(object/reference type)으로 구분된다. 원시 타입에 속하는 값은 변경할 수 없는(immutable) 원시 값이며, 객체 타입에 속하는 값은 내부 상태를 변경할 수 있는 가변적(mutable) 객체값이다.
원시 타입에는 Number, String, Boolean, undefined, null, Symbol, BigInt가 포함되며, 이 중 null을 제외한 값들은 typeof 연산자로 타입을 확인할 수 있다. 다만 typeof null이 object를 반환하는 것은 자바스크립트 초기 설계상의 오류로 인해 발생한 예외적인 동작이다.
두 타입의 차이는 값의 저장방식과 불변성 여부에서 나타난다. 원시 값은 한 번 생성되면 변경할 수 없으며, 새로운 값을 만들 경우 기존 값은 그대로 유지된다. 반면 객체 값은 내부 상태를 변경할 수 있다. (따라서 객체 값을 복사할 때 얕은 복사와 깊은 복사의 개념을 고려해야 한다.)
원시 타입 | 객체 타입 | |
변경 가능 여부 | 변경 불가능한 값 | 변경 가능한 값 |
변수 할당 시 | 실제 값 저장 | 참조 값 저장 |
다른 변수에 할당 시 | 값에 의한 전달 (pass by value) | 참조에 의한 전달 (pass by reference) |
원시 타입
- Number: 정수와 부동소수점을 모두 표현한다.
- String: 문자열을 나타낸다.
- Boolean: 논리적 참(true)와 거짓(false)을 나타낸다.
- undefined: 값이 할당되지 않은 상태를 나타낸다.
- null: 의도적으로 값이 없음을 나타낸다.
- Symbol: ES6부터 도입된 유니크한 식별자 타입이다.
- BigInt: ES2020부터 지원되며, 매우 큰 정수를 다루기 위한 타입이다.
객체 타입
- Array, Function, Date, RegExp, Map, Set 등 다양한 내장 객체들을 포함한다.
- 객체는 키-값 형태로 데이터를 저장하며, 변수에 저장되는 값은 실제 객체가 아니라 참조(메모리 주소)이다.
데이터 할당 방식
원시 값의 할당
변수에 원시 값을 할당하면, 실제 값이 복사되어 저장된다.
객체 값의 할당
변수에 객체를 할당하면, 객체의 참조(메모리 주소)가 복사되어 저장된다. 엄밀히 말하면 자바스크립트는 모든 경우에 값에 의한 전달을 사용하지만, 객체의 경우 그 값이 참조이기 때문에 참조에 의한 전달처럼 동작한다.
자바스크립트의 데이터 타입은 단순한 개념이 아니라, 우리가 코드를 더 정확하고 안정적으로 작성할 수 있도록 돕는다. 변수에 저장된 값이 원시 값인지, 객체 값인지 구분하는 것만으로도 불필요한 버그를 줄이고, 예측 가능한 코드를 만들 수 있기 때문이다.
실무에서는 상태 관리, API 데이터 처리, 메모리 최적화 등에서 데이터 타입을 정확히 이해하고 활용하는 것이 중요하다. 특히, 객체를 다룰 때 불변성을 유지하는 방법, 얕은 복사와 깊은 복사 방식 등을 잘 알아두면 복잡한 상태 변화를 다룰 때 실수를 줄일 수 있다.