학습 자료

자료형 — 값에도 종류가 있다


Article

변수라는 상자에 값을 담는 법을 배웠다. 이제 그 안에 들어가는 값에도 종류가 있다는 걸 볼 차례다.

숫자 3과 글자 "3"은 화면에는 비슷하게 보이지만 완전히 다른 값이다. 하나는 계산할 수 있고 하나는 이어붙일 수 있다. 이 구분이 자료형이다.

큰 틀부터

자바스크립트의 값은 크게 두 부류로 나뉜다. 이 구분은 이 시리즈 끝까지 계속 따라온다.

자바스크립트의 자료형
    • 원시 타입primitive — 값 그 자체
      • number숫자
      • string문자열
      • boolean참 / 거짓
      • undefined값이 없음 (아직)
      • null값이 없음 (일부러)
      • symbol고유한 식별자
      • bigint아주 큰 정수
    • 객체 타입object — 값이 있는 위치
      • object일반 객체
      • array배열도 객체다
      • function함수도 객체다

원시 타입은 일곱 개고, 나머지는 전부 객체다. 지금 다 외울 필요는 없다. 실제로 매일 쓰는 건 앞의 다섯 개다.

매일 쓰는 다섯 가지

number — 숫자

정수와 소수를 구분하지 않는다. 둘 다 number다.

const age = 27;
const height = 178.5;
const minus = -10;

특이한 값도 몇 개 있다.

console.log(1 / 0);
console.log("글자" * 2);
콘솔
  • Infinity
  • NaN

Infinity는 무한대고, NaN은 "Not a Number", 숫자가 아니라는 뜻이다. 숫자로 계산할 수 없는 걸 계산하려 하면 나온다.

string — 문자열

따옴표로 감싼 글자다. 작은따옴표, 큰따옴표, 백틱 셋 다 된다.

const a = "큰따옴표";
const b = '작은따옴표';
const c = `백틱`;

셋의 기능은 거의 같지만, 백틱만 할 수 있는 게 있다. 변수를 문장 안에 끼워 넣는 것이다.

const name = "지원";

console.log("안녕, " + name + "님");
console.log(`안녕, ${name}님`);
콘솔
  • 안녕, 지원님
  • 안녕, 지원님

아래쪽이 훨씬 읽기 좋다. 백틱으로 감싸고 ${ } 안에 값을 넣는 이 문법을 템플릿 리터럴이라 부른다. 앞으로 계속 쓴다.

boolean — 참과 거짓

값이 딱 두 개뿐이다. truefalse.

const isAdult = true;
const isMember = false;

console.log(10 > 5);
콘솔
  • true

비교의 결과가 boolean이다. 조건문에서 "이 길로 갈지 말지"를 정하는 데 쓰인다.

undefined 와 null — 둘 다 "없음"인데 왜 둘일까

초보자가 가장 자주 헷갈리는 지점이다. 결론부터 말하면 누가 비웠는지가 다르다.

없음의 두 종류

undefined

자바스크립트가 비워둔 것

  • 선언만 하고 값을 안 넣었을 때
  • 없는 속성을 꺼냈을 때
  • 함수가 아무것도 반환하지 않을 때
  • "아직 값이 정해지지 않았다"

null

개발자가 일부러 비운 것

  • 직접 null 을 넣어야만 생긴다
  • "여기 값이 없다"는 의도적 표시
  • 찾는 걸 못 찾았을 때 반환값으로 쓴다
  • "비어 있음을 알고 있다"

코드로 보면 차이가 분명하다.

let a;
console.log(a);

let b = null;
console.log(b);

const user = { name: "지원" };
console.log(user.age);
콘솔
  • undefined
  • null
  • undefined

a는 값을 넣지 않았으니 자바스크립트가 알아서 undefined를 넣어뒀다. b는 내가 직접 "비었다"고 표시했다. user.age는 존재하지 않는 속성이라 undefined가 나온다.

typeof — 타입을 확인하는 법

값의 타입이 궁금하면 typeof를 앞에 붙인다.

console.log(typeof 42);
console.log(typeof "글자");
console.log(typeof true);
console.log(typeof undefined);
console.log(typeof { name: "지원" });
console.log(typeof [1, 2, 3]);
console.log(typeof null);
콘솔
  • 'number'
  • 'string'
  • 'boolean'
  • 'undefined'
  • 'object'
  • 'object'
  • 'object'

마지막 두 줄이 이상하다.

배열이 'object'로 나오는 건 버그가 아니다. 배열은 실제로 객체의 한 종류다. 배열인지 확인하려면 전용 함수를 쓴다.

console.log(Array.isArray([1, 2, 3]));
console.log(Array.isArray({ a: 1 }));
콘솔
  • true
  • false

원시 타입과 객체 타입의 진짜 차이

이제 3강 끝에서 미뤄뒀던 이야기를 마무리한다. 왜 const 배열에는 값을 추가할 수 있었나.

핵심은 상자에 무엇이 들어 있느냐다.

원시 타입은 값이 상자에 직접 들어간다. 객체는 너무 커서 상자에 안 들어가므로, 다른 곳에 두고 그 위치만 상자에 적어둔다.

상자 안을 들여다보면

원시 타입은 값 자체를, 객체 타입은 위치를 담는다

age
27
name
"지원"
scores
0x1a2b
[90, 85, 100]
user
0x3c4d
{ name: "지원" }

이 차이는 복사할 때 겉으로 드러난다.

let a = 10;
let b = a;
b = 20;
console.log(a);

let x = [1, 2];
let y = x;
y.push(3);
console.log(x);
콘솔
  • 10
  • [1, 2, 3]

첫 번째는 예상대로다. b를 바꿔도 a는 그대로다. 값 자체가 복사됐기 때문이다.

두 번째가 함정이다. y를 바꿨는데 x도 바뀌었다. 복사된 건 배열이 아니라 위치였고, xy가 같은 배열을 가리키고 있었기 때문이다.

무슨 일이 벌어졌나
  1. 01

    x 가 배열을 가리킨다

    배열은 메모리 어딘가에 있고, x 에는 그 위치가 적힌다.

    let x = [1, 2];
  2. 02

    y 가 위치를 복사한다

    배열이 복사된 게 아니다. 주소만 복사됐다. 이제 둘이 같은 배열을 본다.

    let y = x;
  3. 03

    y 로 배열을 바꾼다

    x 가 보고 있는 것도 같은 배열이므로 함께 바뀐 것처럼 보인다.

    y.push(3);  // x 도 [1, 2, 3] 이 된다

이 동작 때문에 생기는 버그가 아주 흔하다. 복사본을 진짜로 만들고 싶다면 별도의 방법이 필요한데, 18강에서 스프레드 문법과 함께 다룬다.

나머지 두 개는 가볍게

symbolbigint는 입문 단계에서 거의 만나지 않는다. 존재만 알아두면 된다.

타입언제 쓰나예시
symbol절대 겹치지 않는 이름이 필요할 때Symbol("id")
bigintnumber 로 감당 안 되는 큰 정수9007199254740993n

정리하면

  • 원시 타입 일곱 개(number, string, boolean, undefined, null, symbol, bigint)와 객체가 있다.
  • undefined는 자바스크립트가 비워둔 것, null은 개발자가 일부러 비운 것이다.
  • typeof null'object'인 건 고칠 수 없는 옛날 버그다.
  • 원시 타입은 값이, 객체 타입은 주소가 복사된다. 이 하나만 기억해도 나중에 버그를 크게 줄인다.

다음 강의부터 Part 2로 넘어간다. 숫자와 문자열을 실제로 다루는 방법을 본다.

자료형 — 값에도 종류가 있다 — 디코드랩(DCODELAB)