[모던 자바스크립트 Deep Dive] - 9장 정리

2026. 4. 1. 23:53Book Review

반응형

자바스크립트를 쓰다 보면 분명히 숫자인데 문자열처럼 동작하거나, null인 줄 알았던 값이 갑자기 에러가 터지거나 하는 상황을 마주치게 된다. 대부분 타입 변환을 제대로 이해하지 못해서 생기는 일이다. 이번 글에서는 자바스크립트에서 타입 변환이 어떻게 일어나는지, 단축 평가 및 최신 연산자들에 대해 정리해봤다. 

타입 변환이란?

자바스크립트의 모든 값에는 타입이 있다. 그리고 그 타입은 두 가지 방식으로 바뀔 수 있다.

명시적 타입 변환(타입 캐스팅) 은 개발자가 의도적으로 타입을 바꾸는 것이고 암묵적 타입 변환(타입 강제 변환) 은 자바스크립트 엔진이 표현식을 평가하는 도중에 자동으로 타입을 바꾸는 것이다.

한 가지 중요한 포인트가 있다. 두 방식 모두 기존 원시 값을 직접 바꾸는 게 아니다. 원시값은 변경 불가능한 값이기 때문에 타입 변환은 기존 원시값을 이용해 새로운 타입의 원시값을 만들어내는 것이다. 암묵적으로 생성된 값 또한 이전 변수에 재할당되지 않는다. 새로운 값을 만들어서 한 번 쓰고 버리는 일회용으로 만들어진다.

그렇다고 "암묵적 타입 변환은 위험하니까 무조건 명시적으로 써야 해"라는 논리도 맞지 않다. (10).toString()보다 10 + ''가 훨씬 간결하니까. 중요한 건 코드가 예측 가능해야 한다는 것이다. 어떤 값으로 변환되는지 이해하고 사용하면 된다.

암묵적 타입 변환

자바스크립트는 가급적 에러를 발생시키지 않으려고 암묵적 타입 변환을 통해 표현식을 평가한다. 보통 문자열, 숫자, 불리언 중 하나로 자동 변환된다.

문자열로 변환

+ 연산자는 피연산자 중 하나라도 문자열이면 문자열 연결 연산자로 동작한다.

1 + '2'      // '12'
true + ''    // 'true'
null + ''    // 'null'
undefined + ''  // 'undefined'
[] + ''      // ''
{} + ''      // '[object Object]'

 

ES6에서 도입된 템플릿 리터럴도 표현식 평가 결과를 문자열로 암묵적 변환한다.

`결과는 ${1 + 2}입니다`  // '결과는 3입니다'

숫자로 변환

+를 제외한 산술 연산자(-, *, /)는 숫자 타입이 아닌 피연산자를 숫자로 변환해서 사용한다. 변환할 수 없으면 NaN이 된다.

'10' - 5    // 5
'3' * '2'   // 6
'one' * 2   // NaN

// 단항 + 연산자로 변환 확인
+''         // 0
+'5'        // 5
+true       // 1
+false      // 0
+null       // 0
+undefined  // NaN
+[]         // 0
+{}         // NaN

 

비교 연산자도 크기를 비교하기 때문에 암묵적 타입 변환이 발생한다.

'5' > 3     // true (문자열 '5'가 숫자 5로 변환됨)

불리언으로 변환

if, for, 삼항 연산자의 조건식은 불리언 값이어야 하는데 불리언이 아니면 자동으로 변환된다. 이때 Falsy 값과 Truthy 값으로 구분된다.

Falsy로 평가되는 값은 딱 이것들이다.

false, undefined, null, 0, -0, NaN, ''  // 빈 문자열

 

이 외의 값은 전부 Truthy다. 빈 문자열이 아닌 문자열, 빈 배열 [], 빈 객체 {}도 전부 true로 평가된다.

if ('') console.log('실행 안 됨');
if ('hello') console.log('실행됨');   // ← 이게 실행됨
if ([]) console.log('실행됨');        // ← 이것도 실행됨

 

명시적 타입 변환

개발자가 의도적으로 타입을 변환하는 방법이다. 표준 빌트인 생성자 함수를 new 없이 호출하거나, 빌트인 메서드를 사용하거나, 앞서 본 암묵적 변환을 활용한다.

문자열로 변환

// 1. String 생성자 함수 (new 없이)
String(123)      // '123'
String(true)     // 'true'
String(null)     // 'null'

// 2. toString() 메서드
(123).toString()   // '123'
(true).toString()  // 'true'

// 3. 문자열 연결 연산자 (암묵적 방식 활용)
123 + ''   // '123'
true + ''  // 'true'

숫자로 변환

// 1. Number 생성자 함수 (new 없이)
Number('123')    // 123
Number(true)     // 1
Number(false)    // 0
Number(null)     // 0
Number('')       // 0

// 2. parseInt, parseFloat — 문자열만 변환 가능
parseInt('123.5')    // 123
parseFloat('123.5')  // 123.5
parseInt('abc')      // NaN

// 3. 단항 + 연산자
+'123'   // 123
+true    // 1

// 4. 산술 연산자 활용
'123' * 1   // 123

불리언으로 변환

// 1. Boolean 생성자 함수 (new 없이)
Boolean('hello')  // true
Boolean('')       // false
Boolean(0)        // false
Boolean(null)     // false

// 2. 부정 논리 연산자 두 번 (!!)
!!'hello'  // true
!!''       // false
!!0        // false
!!null     // false
!![]       // true  ← 빈 배열도 true

 

!!은 실무에서 자주 쓰는 패턴이다. 어떤 값이 truthy인지 falsy인지 빠르게 boolean으로 변환하고 싶을 때 유용하다.

단축 평가

논리 연산자 &&, ||의 평가 결과가 항상 불리언은 아니다. 여기서 단축 평가 개념이 나온다.

  • && (논리곱): 두 피연산자가 모두 true여야 true. 좌항이 true면 우항의 값이 결과를 결정하기 때문에 우항을 그대로 반환한다.
  • || (논리합): 하나만 true여도 true. 좌항이 true면 더 볼 필요 없으니 좌항을 그대로 반환한다.
'cat' && 'dog'   // 'dog'  ← 우항 반환
false && 'dog'   // false  ← 좌항에서 이미 결정

'cat' || 'dog'   // 'cat'  ← 좌항이 truthy라 바로 반환
false || 'dog'   // 'dog'  ← 좌항이 falsy라 우항 반환

평가 결과가 확정되는 순간 나머지 평가를 생략하는 것, 이게 단축 평가다. 이를 활용하면 if문을 대체할 수 있다.

// if문 대신 && 활용
const isLoggedIn = true;
isLoggedIn && console.log('환영합니다');  // 로그인 상태일 때만 실행

// if/else 대신 || 활용
const name = '';
const displayName = name || '익명';  // name이 falsy면 '익명' 사용
console.log(displayName);  // '익명'

언제 단축 평가를 쓰면 좋을까?

1. 객체 프로퍼티 참조 전 null/undefined 체크

객체가 아닌 값에서 프로퍼티를 참조하면 타입 에러가 발생한다. 단축 평가로 안전하게 막을 수 있다.

const user = null;

// 단축 평가 없이 — 에러 발생
console.log(user.name);  // TypeError!

// 단축 평가 사용 — 안전하게 처리
console.log(user && user.name);  // null (에러 없음)

2. 함수 매개변수 기본값 설정

인수를 전달하지 않으면 매개변수에 undefined가 할당된다. 이로 인한 오류를 단축 평가로 막을 수 있다.

function greet(name) {
  name = name || '익명';  // name이 없으면 기본값 사용
  console.log(`안녕하세요, ${name}님!`);
}

greet('지수');  // '안녕하세요, 지수님!'
greet();        // '안녕하세요, 익명님!'

 

옵셔널 체이닝 연산자 (?.)

ES11에서 도입된 ?.는 좌항이 null 또는 undefined면 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다.

const user = null;

// 기존 && 방식
const name = user && user.name;  // null

// ?. 방식 — 훨씬 간결
const name = user?.name;  // undefined

 

&&를 쓰던 방식에는 한계가 있었다. 0이나 ' '처럼 falsy지만 유효한 값으로 판단해야 할 때 문제가 생긴다.

const str = '';

// && 방식 — 빈 문자열도 falsy라 프로퍼티 참조를 못 함
const len = str && str.length;  // '' (0이 아닌 빈 문자열이 반환됨)

// ?. 방식 — null/undefined가 아니면 정상적으로 참조
const len = str?.length;  // 0 (정확히 빈 문자열의 길이를 반환)

 

null 병합 연산자 (??)

ES11에서 함께 도입된 ??는 좌항이 null 또는 undefined면 우항을 반환하고, 그렇지 않으면 좌항을 반환한다.

주로 변수에 기본값을 설정할 때 유용하다.

const value = null ?? '기본값';   // '기본값'
const value2 = 'hello' ?? '기본값';  // 'hello'

 

기존에는 ||로 기본값을 설정했는데 0이나 ' '처럼 falsy지만 유효한 값으로써 기본값으로 쓸 때 문제가 됐다.

// || 방식 — 0도 falsy라 의도치 않게 기본값으로 대체됨
const count = 0 || 10;   // 10 (의도하지 않은 결과)

// ?? 방식 — null/undefined만 걸러냄
const count = 0 ?? 10;   // 0 (의도한 대로 0이 유지됨)

 

반응형