Skip to content

자료형과 형 변환

typeof 연산자로 변수의 자료형 확인하기
  • typeof는 변수나 값의 자료형(데이터 타입)을 "문자열"로 반환하는 연산자이다.
js
let num = 123;
console.log(typeof num); // "number"

자료형 (Data Type)

less
자료형 (Data Type)
├── 원시타입 (Primitive Types)
│   ├── Number
│   ├── String
│   ├── Boolean
│   ├── Undefined
│   ├── Null
│   ├── Symbol
│   └── BigInt
└── 비 원시타입 / 참조 타입 (Reference Types)
    └── 객체 Object
        ├── Array
        ├── Function
        ├── Date
        ├── RegExp
        ├── Map
        ├── Set
        └── 기타 사용자 정의 객체
js
// 원시 타입 자료형: 단 하나의 값만 가지는 타입
let num = 100;
num = "one";

// 비 원시 타입은: 한번에 여러 개의 값을 가지는 타입
let arr = [100, "one", 1];
  • 변수의 자료형이란 변수에 할당된 데이터의 종류를 뜻하며, 변수의 타입이라고도 부른다.
  • 자료형은 크게 "원시 타입", "비 원시 타입"으로 나뉜다.

1. 원시 타입 (Primitive Type)

less
원시타입 (Primitive Types)
├── Number
├── BigInt
├── String
├── Boolean
├── Null
├── Undefined
└── Symbol
  • 변수에 값이 직접 저장되며, 다른 변수에 복사해도 서로 독립적인 값으로 존재한다.
  • 즉, 값 하나만 저장하고 그 값 자체로 동작하는 타입을 원시 타입이라 부른다.

(1) Number 숫자형

js
let number1 = 10;
let number2 = 10.01;

console.log(typeof number1); // "number"
console.log(typeof number2); // "number"
  • Number 타입은 모두 IEEE 754 64-bit 부동소수점으로 다뤄지기 때문에, 정수와 소수의 구분 없이 모두 실수(floating‑point)로 처리된다.
  • 이로 인해 큰 정수 연산이나 소수점 연산에서 정밀도(precision) 손실이 발생할 수 있다.

정밀도 손실 예시

js
// 큰 정수 연산 오차 예시
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MAX_SAFE_INTEGER + 1); // 9007199254740992
console.log(Number.MAX_SAFE_INTEGER + 2); // 9007199254740992 ← 의도한 +2가 적용되지 않음

// 소수점 연산 오차 예시
console.log(0.1 + 0.2); // 0.30000000000000004

// 이유: IEEE 754 이진 부동소수점 표현 한계
js
// BigInt로 해결 (BigInt끼리만 연산 가능)
const big = 9007199254740991n;
console.log(big + 1n); // 9007199254740992n
console.log(big + 2n); // 9007199254740993n
console.log(big + 2); // TypeError: Cannot mix BigInt and other types

특수한 숫자 값들

Infinity

js
let num1 = Infinity;
console.log(typeof num1); // "number"

let num2 = 100 / 0;
console.log(num2); // Infinity
console.log(typeof num2); // "number"
  • 무한대를 의미하는 값
  • 변수에 하나의 값으로 직접 할당할 수 있고, 숫자를 0으로 나누거나, 너무 큰 값을 연산할 때 반환된다.

NaN (Not a Number)

js
let num3 = NaN;
console.log(typeof num3); // "number"

let num4 = "자바스크립트" / 10;
console.log(num4); // NaN
console.log(typeof num4); // "number"
  • "숫자가 아님"을 의미하는 값
  • 변수에 하나의 값으로 직접 할당할 수 있고, 부정확한 연산을 하게 될 경우에 반환되는 값(문자열을 숫자로 나누는 연산을 하게 될 경우)

(2) BigInt

js
let big1 = 9007199254740991n;
let big2 = BigInt("9007199254740991");

console.log(typeof big1); // "bigint"
console.log(typeof big2); // "bigint"
  • Number가 "안전하게 표현할 수 없는" 매우 크거나 작은 정수를 다룰 때 사용하는 자료형
  • Number 타입이 "안전하게 표현할 수 있는" 정수 범위: ±(2^53 - 1)
    즉, 2^53 -1 보다 크거나 -(2^53 - 1) 보다 작은 정수
  • BigInt 값은 숫자 뒤에 n을 붙이거나, BigInt() 함수를 사용하여 생성할 수 있다.

BigInt의 사칙연산

js
let big1 = 10n;
let big2 = 5n;
let num = 5;

console.log(big1 + big2); // 15n
console.log(big1 + num); // TypeError: Cannot mix BigInt and other types
  • BigInt끼리만 연산이 가능하며, 일반 숫자(Number)와 혼합하여 연산할 수 없다.
2^53 -1의 의미

Number데이터 타입은 64비트(8바이트) 부동소수점 형식을 사용한다.
이 중 53비트가 정수 부분을 저장하는 데 사용된다.(나머지는 부호와 소수점 위치 정보)
따라서, 이 53비트로 표현할 수 있는 최대 정수는 2^53 -1 이다.

2^53 -1 = 9,007,199,254,740,991 → 최대 정수값.
-(2^53 -1) = -9,007,199,254,740,991 → 최소 정수값.
이 범위를 벗어나면 정밀도 문제가 발생하기 때문에, BigInt가 필요하다.

BigInt는 왜 정밀도 문제를 해결하는지?

BigInt는 임의 정밀도를 지원하는 자료형이다. 즉, 숫자가 커질수록 그에 따라 저장공간이 동적으로 늘어나므로, 크기에 제한이 없고 매우 큰 정수를 정확하게 표현할 수 있다. 정수에 대한 정확한 연산을 지원하므로, 크고 작은 숫자 간 연산 시 정밀도를 잃지 않는다.

  • Number: 64비트 부동소수점 방식을 사용하며, 정수 범위에 한계가 있어 정밀도 문제 발생
  • BigInt: 임의 크기 정수를 지원하여, 정밀도 손실 없이 큰 숫자를 정확하게 표현한다. 크기에 제한이 없어서 매우 큰 정수도 정확하게 다룰 수 있다.

(3) String

js
let name1 = "bin"; // 큰 따옴표

console.log(typeof name1); // "string"
  • 문자열을 변수에 할당할 때는 따옴표로 문자열을 감싸야 한다.
  • 큰 따옴표""와 작은 따옴표''는 같은 기능을 하기 때문에 문자열 할당 시 아무거나 사용 가능하다.

템플릿 리터럴 방식(Template Literals)

js
let name = "bin";
let greeting = `안녕하세요. 제 이름은 ${name}입니다.`;

console.log(greeting); // 제 이름은 bin입니다.
  • 백틱``을 사용하면 문자열을 만들 수 있는데, 이걸 템플릿 리터럴이고 부른다.
  • 템플릿 리터럴 안에서는 ${} 구문을 사용해 문자열 내에 변수에 저장된 값이나 표현식을 쉽게 삽입할 수 있다.

문자열 이스케이프 문자

css
// 큰 따옴표: \"
console.log('He said, \"Hello!\"');

// 작은 따옴표: \'
console.log("It\'s OK.");

// 줄바꿈: \n
console.log("줄\n바꿈");

// 탭(들여쓰기): \t
console.log("탭\t탭");
js
He said, "Hello!"
It's OK.

바꿈
탭	탭
  • 문자열 안에 특수 문자를 넣고 싶을 때는 이스케이프 문자(\)를 사용한다.
  • \", \', \n, \t

(4) Boolean

js
let isClicked = false; // 버튼이 클릭되었는지 여부
let isOpen = true; // modal이 열렸는지 여부

if (isClicked) {
  console.log("클릭O");
} else {
  console.log("클릭X");
}
  • true, false 두 가지 값만 가질 수 있는 논리형 자료형이다.
  • 주로 조건문에서 참과 거짓을 판단할 때 사용된다.
  • "어떤 상태인지", "조건이 만족되었는지" 와 같은 논리적인 상태를 표현할 때 유용하다.

(5) Null

js
let name = null;
console.log(typeof name); // "object" (자바스크립트의 오래된 버그)
console.log(name === null); // true
js
let selectedUser = null; // 아직 선택된 사용자가 없음

// 나중에 유저가 선택되면 값 할당
selectedUser = "hyebin";
  • "값이 없음"을 명시적(의도적)으로 할당하는 자료형이다.
  • 변수에 아직 값이 정해지지 않았지만, 일부러 비워두겠다는 의도를 표현할 때 사용한다.
  • 주로 초기화가 필요한 변수에 사용되며, 값이 존재하지 않음을 나타낼 때 유용하다.

(6) Undefined

js
let name; // 변수 선언만 하고 값은 할당하지 않음
console.log(name); // undefined
console.log(typeof name); // "undefined"
  • undefined는 값이 할당되지 않은 변수에 자바스크립트가 자동으로 할당하는 특별한 값(암묵적)이다.
  • null과 마찬가지로 "값이 없음"을 나타내는 자료형이지만, null이 명시적(의도적)으로 값이 없음을 나타내는 것과 달리, undefined는 변수에 값이 아직 할당되지 않은 상태를 의미한다.

(7) Symbol

js
const sym1 = Symbol("id");
const sym2 = Symbol("id");

console.log(sym1 === sym2); // false
console.log(typeof sym1); // "symbol"
  • symbol은 유일하고 변경 불가능한 원시 값을 만들기 위한 자료형이다.
  • 주로 객체의 고유한 프로퍼티 키(key)로 사용된다. 같은 이름이라도 서로 다른 Symbol 값은 절대 같지 않기 때문에, 충돌 없이 안전하게 사용할 수 있다.
  • Symbol() 함수를 호출해서 생성하며, 선택적으로 설명을 붙일 수 있다.
  • 주로 라이브러리나 프레임워크에서 객체 속성 이름이 겹치지 않게 하기 위해 사용한다.
  • 심볼 값은 문자열로 변환할 수 없으며, 직접 출력하면 설명이 나오지만 고유한 식별자로 작동한다.

2. 비 원시 타입 (Reference Types)

less
비 원시타입 / 참조 타입 (Reference Types)
└── 객체 Object
    ├── 배열 Array
    ├── 함수 Function
    ├── 날짜 Date
    ├── 정규표현식 RegExp
    ├── Map
    └── Set
  • 비원시 타입은 변수에 값 자체가 아닌 그 값이 저장된 메모리 주소(참조값)를 저장하는 자료형이다.
  • 즉, 변수는 실제 데이터를 직접 담지 않고, 데이터가 저장된 위치를 참조합니다.
  • 대표적인 비원시 타입은 객체(Object)이며, 배열, 함수 등도 객체의 일종이다
  • 원시 타입과 달리, 비 원시 타입은 변경 가능한 값(mutable)이며, 여러 개의 값을 하나의 변수에 저장할 수 있다.
  • 같은 객체를 여러 변수가 참조할 수 있고, 값을 변경하면 참조된 모든 변수에 영향을 미칠 수 있다.
비 원시 타입의 특징 #참조형 #변경 가능

참조형 (Reference Type)

js
let obj1 = { name: "Alice" };
let obj2 = obj1; // obj1과 obj2는 같은 객체를 참조함

obj2.name = "Bob";
console.log(obj1.name); // "Bob"

// obj2에서 수정한 값이 obj1에도 영향을 미친다.
  • 변수에 저장되는 것은 값이 아니라 객체가 저장된 메모리 주소이다.
  • 같은 객체를 참조하는 변수끼리는 서로 영향을 주고받는다. 즉, 복사된 객체를 수정하면 원본 객체도 영향을 받는다.

변경 가능 (Mutable)

js
let numbers = [1, 2, 3];
numbers[0] = 100; // 배열의 첫 번째 값 수정
console.log(numbers); // [100, 2, 3]
  • 객체나 배열 같은 비 원시 타입은 내용을 자유롭게 수정하거나 속성을 추가할 수 있다.
  • 메모리 주소(참조)는 그대로 유지된 채 내부 데이터만 변경된다.

객체 (Object)

js
let person = {
  name: "Bin", // 문자열
  age: 30, // 숫자
  isEmployed: true, // 불리언
};
  • 객체는 key: value형태의 데이터 구조이다.
  • 객체의 값에는 문자열, 숫자, 불리언뿐 아니라 배열, 함수, 또 다른 객체도 들어갈 수 있다.
  • 배열(Array), 함수(Function), 날짜(Date), 정규표현식(RegExp), Map, Set 등 모두 객체의 일종이다.

(1) 배열 Array

js
let colors = ["red", "green", "blue"];
let mixedArray = [1, "apple", true, [2, 3], { key: "value" }];
  • 배열은 여러 개의 값을 순서대로 저장할 수 있는 자료형이다.
  • 각 값은 숫자 인덱스를 통해 접근할 수 있으며, 배열 안에 다양한 타입의 값을 저장할 수 있다.
숫자 인덱스란?

자바스크립트에서 배열은 순서가 있는 값들의 집합이다. 배열의 각 요소는 0부터 시작하는 숫자 인덱스로 자동 부여되어, 해당 순서를 통해 값을 참조하거나 수정할 수 있다.

js
// 배열 선언
let fruits = ["apple", "banana", "cherry"];

// 배열에서 첫 번째 요소(apple)에 접근
console.log(fruits[0]); // "apple"

// 배열에서 두 번째 요소(banana)에 접근
console.log(fruits[1]); // "banana"

// 배열에서 세 번째 요소(cherry)에 접근
console.log(fruits[2]); // "cherry"

  • 배열에 값 추가하기
    배열은 인덱스를 통해 새로운 값을 추가할 수 있으며, 추가된 값에는 자동으로 다음 인덱스 번호가 할당된다.
js
let numbers = [10, 20, 30];
numbers[3] = 40; // 인덱스 3에 40을 추가

console.log(numbers); // [10, 20, 30, 40]

(2) 함수 Function

js
function greet(name) {
  return `Hello, ${name}!`;
}
  • 함수는 자바스크립트에서 객체의 한 종류로 취급된다.
  • 일련의 명령문을 하나로 묶어, 필요할 때마다 호출할 수 있는 실행 블록이다.
  • 주로 코드의 재사용을 위해 사용되며, 입력값(매개변수)을 받아 처리하고, 출력값(반환값)을 반환할 수 있다.

3. Falsy & Truthy

  • 자바스크립트에서는 모든 값이 불리언 문맥에서 truthy or falsy로 변환된다.
  • Boolean(value) 또는 !!value 로 확인할 수 있다.

Falsy 값

설명
false불리언 false 자체
0숫자 0, 음수 0
0nBigInt 0
"", '', ``빈 문자열
null명시적 빈(없음)
undefined암묵적 빈(미할당)
NaN숫자가 아님(Not a Number)
js
Boolean(0); // false
Boolean(""); // false
Boolean(null); // false
Boolean(undefined); // false
Boolean(NaN); // false
Boolean(false); // false

Truthy 값

falsy 값이 아닌 나머지 모든 값은 truthy로 평가된다.

설명
"hello"빈 문자열이 아닌 모든 문자열
420이 아닌 모든 숫자
[]빈 배열도 truthy
{}빈 객체도 truthy
true불리언 true 자체
" "공백 하나 이상의 문자열
js
Boolean("hello"); // true
Boolean(42); // true
Boolean([]); // true
Boolean({}); // true
Boolean(" "); // true
Boolean(true); // true

형 변환 (Type Conversion)

자바스크립트는 동적 타입(Dynamic Typing) 언어이다.

js
let nowType = “안녕하세요”;
console.log(typeof nowType); // "string"

nowType = 100;
console.log(typeof nowType); // "number"
  • 자바스크립트는 동적 타입(Dynamic Typing) 언어로, 변수에 저장된 값에 따라 자료형이 자동으로 결정된다.
  • 따라서 같은 변수에 서로 다른 타입의 값을 할당해도 에러 없이 동작한다.

형 변환이란?

  • 어떤 연산을 수행하기 위해 값의 자료형을 바꾸는 과정이다.
  • 자바스크립트에서는 형 변환이 자동으로 발생하기도 하고, 개발자가 직접 지정할 수도 있다.
  • 형변환에는 묵시적 형변환, 명시적 형변환이 있다.

(1) 묵시적 형변환 (Implicit Type Conversion)

js
let result = "3" * 2;
console.log(result); // 6
console.log(typeof result); // "number"
  • 묵시적 형 변환이란, 자바스크립트 엔진이 연산을 수행하기 위해 자동으로 자료형을 변환하는 것을 말한다.
  • 위 예시처럼, 문자열 "3"을 * 연산을 위해 자동으로 숫자 3으로 변환하여 계산한다.
  • 사칙연산 중 /, *, - 연산은 "문자열"을 "숫자형"으로 변환한다.
  • +연산자는 문자열 결합 기능을 포함하고 있기 때문에, 연산 대상 중 하나라도 문자열이면 나머지 피연산자도 문자열로 변환하여 문자열로 결합하는 방식으로 처리한다.

(2) 명시적 형변환 (Explicit Type Conversion)

js
let num1 = "15";
let num2 = 5;

console.log(num1 + num2); // "155"
// + 연산자로 숫자도 문자열로 변환되어 문자열 결합

// 형변환
console.log(parseInt(num1) + num2); // 20
// parseInt 문자열을 정수로 변환해주는 함수 (정수로만 변환)

console.log(Number(num1) + num2); // 20
// Number 문자열을 숫자로 변환해주는 함수 (정수, 실수 모두 가능)

console.log(String(num2) + num1); // "515"
// String 숫자열을 문자열로 변환해주는 함수
  • 명시적 형변환이란, 개발자가 의도적으로 자료형을 변환하는 것이다.
  • 내장 함수 Number(), String(), Boolean() 등을 사용해 직접 타입을 바꾼다.