데이터 타입이란?
기본적으로 변수에 저장되는 값(데이터)의 종류(type)를 나타낸다.
자바스크립트에는 크게 원시 타입(Primitive Type)과 참조 타입(Reference Type) 두 가지 종류의 데이터 타입이 있다.
1. 원시 타입(Primitive Type)
원시 타입은 프로그래밍 언어에서 가장 기본적인 데이터 타입을 의미하며, 더 이상 분해할 수 없는 값을 나타낸다.
원시 타입 종류
- 숫자형 (Number) : 정수와 부동 소수점 숫자를 모두 포함한다.
- 10, 3.14, -5
- 문자열 (String) : 텍스트 데이터를 나타낸다. 작은따옴표('...'), 큰따옴표("..."), 또는 백틱(...)으로 묶어서 표현한다.
- '안녕하세요', "JavaScript", Hello, ${name}
- 불리언 (Boolean) : 참(true) 또는 거짓(false) 값을 나타낸다.
- true, false
- Undefined : 값이 할당되지 않은 변수의 기본값이다.
- let x; console.log(x); // undefined
- Null : 값이 없음을 명시적으로 나타내는 값이다.
- let y = null;
- 심볼 (Symbol) : ES6에서 추가된 타입으로, 고유하고 변경 불가능한 값을 생성한다. 객체의 속성 키로 사용될 수 있다.
- Symbol('description')
- BigInt : 아주 큰 정수를 안전하게 표현할 수 있는 타입이다.
- 9007199254740991n
원시 타입 특징
- 불변성(Immutability)
- 원시 타입의 값은 생성된 후에는 변경할 수 없다.
- 즉, 변수에 새로운 값을 할당하면 기존 값이 변경되는 것이 아니라 완전히 새로운 값이 메모리에 생성된다.
- 예를 들어 문자열 "Hello"를 생성한 후 "Hello World"로 변경하는 것은 기존 문자열을 수정하는 것이 아니라 새로운 문자열을 생성하는 것이다.
- 값 자체의 저장
- 원시 타입의 값은 변수에 직접 저장된다.
- 즉, 변수는 값의 메모리 주소가 아닌 값 자체를 가지고 있다.
- 이는 참조 타입과 대조되는 특징으로, 참조 타입은 값의 메모리 주소를 변수에 저장한다.
- 값에 의한 전달(Pass by Value)
- 원시 타입 변수를 다른 변수에 할당하거나 함수에 인자로 전달할 때, 실제 값이 복사되어 전달된다.
- 따라서, 복사된 변수의 값을 변경해도 원본 변수의 값에는 영향을 주지 않는다.
2. 참조 타입 (Reference Type)
- 객체 (Object)
- 가장 기본적인 참조 타입으로, 속성(property)과 값(value)의 쌍으로 이루어진 데이터 구조이다.
- 중괄호({})를 사용하여 생성하며, 다양한 형태의 데이터를 담을 수 있다.
- { name: 'John', age: 30 }
- 배열 (Array)
- 순서가 있는 데이터의 집합을 나타내는 객체이다.
- 대괄호([])를 사용하여 생성하며, 다양한 타입의 데이터를 순서대로 저장할 수 있다.
- [1, 2, 3, 'apple']
- 함수 (Function)
- 실행 가능한 코드 블록을 나타내는 객체이다.
- function 키워드를 사용하여 정의하며, 특정 작업을 수행하는 데 사용된다.
- function greet(name) { console.log('Hello, ' + name); }
- 날짜 (Date)
- 날짜와 시간을 나타내는 객체이다.
- Date 생성자를 사용하여 생성하며, 날짜 및 시간 관련 작업을 수행하는 데 사용된다.
- new Date()
- 정규 표현식 (RegExp)
- 문자열에서 특정 패턴을 검색하고 일치시키는 데 사용되는 객체이다.
- 정규 표현식 리터럴(/.../) 또는 RegExp 생성자를 사용하여 생성한다.
- /abc/
- Map, Set, WeakMap, WeakSet
- ES6에서 도입된 새로운 데이터 구조로, 각각 키-값 쌍의 컬렉션, 고유한 값의 컬렉션, 약한 참조를 사용하는 키-값 쌍의 컬렉션, 약한 참조를 사용하는 고유한 값의 컬렉션을 나타낸다.
참조 타입 특징
- 메모리 주소 저장
- 참조 타입의 값은 힙(Heap)이라는 메모리 영역에 저장된다.
- 변수에는 힙에 저장된 객체의 실제 데이터가 아닌, 해당 데이터의 메모리 주소(참조)가 저장된다.
- 가변성(Mutability)
- 참조 타입의 데이터는 생성 후에도 그 값을 변경할 수 있다.
- 객체의 속성 값을 변경하거나 배열에 요소를 추가/삭제하는 것이 가능하다.
- 참조에 의한 전달(Pass by Reference)
- 참조 타입 변수를 다른 변수에 할당하거나 함수에 인자로 전달할 때, 실제 값이 복사되는 것이 아니라 메모리 주소(참조)가 복사되어 전달된다.
- 따라서, 복사된 변수를 통해 데이터를 변경하면 원본 데이터도 함께 변경된다.
- 동적 메모리 할당
- 참조 타입은 데이터의 크기를 미리 알 수 없는 경우가 많으므로, 프로그램 실행 중에 필요한 만큼 메모리를 동적으로 할당한다.
- 객체 기반:
- 자바스크립트의 참조 타입은 객체(Object)를 기반으로 한다.
- 배열과 함수도 객체의 특별한 형태이다.
데이터 저장 방식
1. 콜 스택 (Call Stack)
- 메모리 할당 방식
- 콜 스택은 함수의 호출과 함께 메모리가 할당되고, 함수의 실행이 종료되면 자동으로 메모리가 해제되는 정적 메모리 할당 방식을 사용한다.
- 원시 타입 데이터의 저장 방식
2. 힙 (Heap)
- 메모리 할당 방식
- 힙은 객체, 배열, 함수 등 동적으로 크기가 변하는 데이터를 저장하는 동적 메모리 할당 영역이다.
- 프로그램 실행 중에 필요한 만큼 메모리를 할당하고 해제할 수 있다.
- 참조 타입 데이터의 저장 방식
3. 데이터 타입을 나누는 이유
데이터 타입을 원시 타입과 참조 타입으로 나누는 이유는 메모리 관리, 오류 방지, 코드 가독성 향상 등 프로그램의 효율성과 안정성을 높이기 위함이다.
1. 메모리 관리 효율성
- 원시 타입
- 고정된 크기의 데이터를 저장한다.
- 스택 메모리에 직접 값을 저장하여 접근 속도가 빠르다.
- 메모리 사용량을 예측하고 관리하기 쉽다.
- 참조 타입
- 크기가 변할 수 있는 데이터를 저장한다.
- 힙 메모리에 데이터를 저장하고, 스택 메모리에는 데이터의 주소만 저장한다.
- 동적 메모리 할당 및 해제를 통해 유연한 메모리 관리가 가능하다.
2. 오류 방지 및 안정성 확보
- 원시 타입
- 값 자체를 복사하여 전달하므로 데이터 변경 시 원본 데이터에 영향을 주지 않는다.
- 예측 가능한 동작으로 오류 발생 가능성을 줄인다.
- 참조 타입
- 주소를 통해 데이터를 참조하므로 여러 변수가 동일한 데이터를 공유할 수 있다.
- 데이터 변경 시 모든 참조 변수에 영향을 주므로 주의가 필요하지만, 필요에 따라 효율적인 데이터 공유가 가능하다.
3. 코드 가독성 및 유지보수성 향상
- 데이터의 특성에 따라 적절한 타입을 사용하여 코드의 의미를 명확하게 전달할 수 있다.
- 원시 타입과 참조 타입의 차이를 명확히 이해하고 사용하면 코드의 동작을 예측하고 오류를 수정하기 쉬워진다.
4. 성능 향상
- 원시 타입
- 스택 메모리에 직접 접근하여 연산 속도가 빠르다.
- 참조 타입
- 메모리 주소를 통해 데이터에 접근하므로 원시 타입보다 연산 속도가 느릴 수 있다.
- 하지만 대량의 데이터를 효율적으로 처리하거나 복잡한 데이터 구조를 표현하는 데 유용하다.
코드 상 데이터 타입 예시
// 1. 숫자형 (Number)
let num1 = 10; // 정수
let num2 = 3.14; // 부동 소수점
let num3 = Infinity; // 무한대
let num4 = NaN; // 숫자가 아님
// 2. 문자열 (String)
let str1 = "Hello"; // 큰따옴표
let str2 = 'World'; // 작은따옴표
let str3 = `Template literals: ${num1}`; // 백틱 (템플릿 리터럴)
// 3. 불리언 (Boolean)
let bool1 = true;
let bool2 = false;
// 4. Undefined
let undef; // 선언만 하고 초기화하지 않음
// 5. Null
let nullVal = null;
// 6. 심볼 (Symbol)
let sym1 = Symbol("description");
let sym2 = Symbol("description"); // sym1과 sym2는 서로 다름
// 7. BigInt
let bigIntVal = 9007199254740991n;
// 8. 객체 (Object)
let obj = {
name: "John",
age: 30,
isStudent: false,
address: {
city: "Seoul",
zipCode: "123-456",
},
hobbies: ["reading", "coding"],
};
// 9. 배열 (Array)
let arr = [1, "two", true, obj];
// 10. 함수 (Function)
function add(a, b) {
return a + b;
}
// 11. 날짜 (Date)
let now = new Date();
// 12. 정규 표현식 (RegExp)
let regex = /abc+/g;
// 13. Map
let map = new Map();
map.set("name", "John");
map.set("age", 30);
// 14. Set
let set = new Set();
set.add(1);
set.add(2);
set.add(2); // 중복된 값은 추가되지 않음
// 15. WeakMap
let weakMap = new WeakMap();
let weakMapObj = { id: 1 };
weakMap.set(weakMapObj, "data");
// 16. WeakSet
let weakSet = new WeakSet();
let weakSetObj = { id: 2 };
weakSet.add(weakSetObj);
// 클래스 (Class)
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
let person1 = new Person("Alice", 25);
데이터 타입 검사 방법
데이터를 넣다보면 가끔 타입이 헷갈릴 수가 있다. 그럴 때 정확히 타입이 들어갔나 확인할 수 있는 방법이 있다.
자바스크립트에서 데이터 타입 확인 방법은 다음과 같은 방법이 있다.
- typeof 연산자 : 피연산자의 타입을 문자열로 반환한다.
- Array.isArray() 메서드 : 배열인지 여부를 정확하게 검사한다.
- Object.prototype.toString.call() 메서드 : 객체의 내부 [[Class]] 속성을 문자열로 반환한다.
- instanceof 연산자 : 객체의 프로토타입 체인을 검사한다.
- Number.isNaN() 메서드 : NaN인지 여부를 정확하게 검사한다.
- 사용자 정의 타입 가드 함수 : 특정 조건을 만족하는지 검사하여 타입을 좁힌다.
1. typeof 연산자
- 가장 기본적인 타입 검사 방법이다.
- 피연산자의 타입을 문자열로 반환한다.
- 원시 타입(숫자, 문자열, 불리언, undefined, 심볼, BigInt)과 함수를 비교적 정확하게 검사할 수 있다.
- 하지만 null과 객체(배열, 객체 리터럴 등)를 구분하지 못하고 모두 "object"를 반환하는 문제가 있다.
// 숫자형 (Number)
console.log(typeof 10);
// 문자열 (String)
console.log(typeof "hello");
// 불리언 (Boolean)
console.log(typeof true);
// Undefined
console.log(typeof undefined);
// 심볼 (Symbol)
console.log(typeof Symbol());
// BigInt
console.log(typeof 10n);
// 함수 (Function)
console.log(typeof function () {});
// Null
console.log(typeof null); // "object" (주의!)
// 객체 (Object)
console.log(typeof {});
// 배열 (Array)
console.log(typeof []);
콘솔 출력 결과는 다음과 같다.
여기서 타입이 object로 나오는 값이 총 3개인 것을 확인 할 수 있다. 바로 null, object, array이다.
2. Array.isArray() : 배열 검사
우선 배열이 object로 나오는 이유는 배열도 오브젝트의 한 형태이기 때문이다. 그렇기 떄문에 배열인지 아닌지 체크하기 위해서는 Array.isArray() 를 사용해야한다.
// 배열 (Array)
console.log(typeof []);
console.log(Array.isArray( []));
null 값이 object로 나오는 이유
그런데 여기서 보면 null값도 object로 나온다. 앞서 null은 원시 타입으로 배웠는데 어째서 참조 타입(object)으로 분류 된단 말인가?
이것은 자바 스크립트 초기 설계상의 버그다.
자바 스크립트 개발 당시 null은 모든 객체의 기본값으로 여겨졌고, 내부적으로 객체와 동일한 타입 태그를 가지고 있었기 때문에 typeof null이 "object"를 반환하게 된 것이다. 그런데 이 버그를 막상 수정하려고 하니 이미 만들어진 자바 스크립트 사이트 들이 많아서 호환성을 위해서 버그를 수정하지 않고 방치하게 된 것이다.
3. 엄격한 동등 연산자(===)
때문에 null을 검사하기 위해서는 typeof 가 아니라 엄격한 동등 연산자(===)를 사용 하는 것이 좋다.
let value = null;
// 잘못된 방법: typeof 사용
if (typeof value === "object") {
console.log("value is object"); // null도 object로 판단됨
}
// 올바른 방법: === 사용
if (value === null) {
console.log("value is null"); // null만 정확하게 판단
}
4. Object.prototype.toString.call()
Object.prototype.toString.call()이라는 복잡한 검사 방법도 있는데 객체의 내부 [[Class]] 속성을 문자열로 반환한다.
때문에 모든 타입을 정확하게 검사할 수 있어서 typeof의 null 문제와 객체 구분 문제를 해결할 수 있다.
console.log(Object.prototype.toString.call(10)); // "[object Number]"
console.log(Object.prototype.toString.call("hello")); // "[object String]"
console.log(Object.prototype.toString.call(true)); // "[object Boolean]"
console.log(Object.prototype.toString.call(undefined)); // "[object Undefined]"
console.log(Object.prototype.toString.call(null)); // "[object Null]"
console.log(Object.prototype.toString.call({})); // "[object Object]"
console.log(Object.prototype.toString.call([])); // "[object Array]"
console.log(Object.prototype.toString.call(function () {})); // "[object Function]"
console.log(Object.prototype.toString.call(new Date())); // "[object Date]"
console.log(Object.prototype.toString.call(/abc/)); // "[object RegExp]"
깔끔하게 타입이 나오는 것을 알 수 있다.
'자바 스크립트(java script) > 자바 스크립트 기초' 카테고리의 다른 글
자바 스크립트 기초(6) - 연산자 (0) | 2025.03.18 |
---|---|
자바 스크립트 기초(5) - 동적 언어, 타입 변환 (0) | 2025.03.18 |
자바 스크립트 기초(3) - 호이스팅이란? (0) | 2025.03.17 |
자바 스크립트 기초(2) - 스코프(Scope)란? : 변수의 참조 범위 (0) | 2025.03.17 |
자바 스크립트 기초(1) - 변수(variable)란? (0) | 2025.03.17 |