본문 바로가기
JAVASCRIPT

[JS][강제변환] 추상 연산 ToBoolean

by KBS 2022. 2. 9.
728x90

강제변환

ToBoolean

자바스크립트에서 불리언에 대해 간단히 살펴보자. 아직도 많은 혼동과 오해를 불러일으키는 주제이다.

 

우선 자바스크립트에는 truefalse라는 키워드가 존재하며 우리가 예상하는 그대로 잘 작동한다. 흔히들 1과 0이 각각 true, false에 해당한다고 생각하는데 다른 언어에서는 몰라도 자바스크립트에서는 숫자는 숫자고, 불리언은 불리언으로 서로 별개다. 1을 true로 0을 false로 강제변환 할수는 있지만 그렇다고 두 값이 똑같은건 아니다.

Falsy 값

지금부터가 재미있다. true/false가 아닌 값을 불리언에 상당한 값으로 강제변환 했을 때. 이 값들은 어떻게 작동할까?

자바스크립트의 모든 값은 다음 둘 둥 하나다.

  1. 불리언으로 강제변환하면 false가 되는 값
  2. 1번을 제외한 나머지

우리에게 짓궂은 장난을 치려는 게 아니다. 불리언으로 강제변환시 false가 되는 몇 개 안되는 특별한 값들이 자바스크립트 명세에 이미 정의되어 있다.

 

이 값들으 목록은 어떻게 알 수 있을까? ES5 9.2 ToBoolean 추상 연산을 읽어보면 '불리언으로' 강제변환시 모든 가능한 경우의 수가 나열되어 있다.

 

명세가 정의한 'falsy' 값은 다음과 같다.

  • undefined
  • null
  • false
  • +0, -0, NaN
  • ""

이게 전부다. 이 목록에 있으면 'falsy'값이며, 불리언으로 강제변환하면 false다.

 

반대로 이 목록에 없으면 다른 목록, 즉 'truthy' 값 목록에 있는 것이다. 그런데 정작 자바스크립트 명세에 'truthy' 값 목록 같은 건 없다. 모든 객체는 명백히 truthy하다는 식의 몇 가지 예시만 있을 뿐 'falsy' 값 목록에 없으면 응당 'truthy'값이 되는 것이다.

Falsy 객체

방금 전 명세에 모든 객체는 truthy하다고 했는데 그럼 'Falsy 객체'같은건 없는 것 아닐까? 무슨소릴까?

 

(" ". 0, false 같은) falsy 값을 둘러싼 객체 래퍼를 두고 하는 얘기가 아닐까 생각하기 쉽다. 하지만 함정에 빠지지말자

var a = new Boolean(false);
var b = new Number(0);
var c = new String("");

 

a, b, c는 명백히 falsy 값을 감싼 객체다. 세 변숫값은 true일까? false일까? 이건 쉽다.

 

var d = Boolean(a && b && c);
d; // true

d가 true인 것으로 봐서 세 변수 모두 true임을 알 수 있다.

 

'falsy 객체'가 falsy 값을 감싼 객체가 아니라면 대체 뭐란 말이지? 여기서부터가 어려웠다, 사실 이객체는 순수 자바스크립트의 일부가 아니다...?

 

일반적인 자바스크립트의 의미 뿐만 아니라 브라우저만의 특이한 작동방식을 가진 값을 생성하는 경우가 있는데, 이것이 바로 'falsy 객체'의 정체다.

 

'falsy 객체'는 겉보기엔 평범한 객체처럼 작동할 것 같지만 불리언으로 강제변환 하면 false다. 잉?

 

가장 유명한 사례가 개발자들이 DOM에서 사용했던 유사배열, document.all이다. document.all은 웹 페이지의 요소를 자바스크립트 프로그램에서 가져올 수 있게 해주었고 그래서 실제로 truthy한 일반 객체처럼 작동했다. 하지만 이젠 더 이상 아니다.

 

알 만한 사람들은 다 알겠지만 document.all은 '비표준'이며, 이미 오래전에 비 권장/폐기되었다.

 

그런데 왜 'falsy' 객체로 작동해야 할까? document.all을 불리언으로 강제변환한 결괏값을 오래된, 비표준 IE브라우저를 감지하는 수단으로써 줄 곧 사용해왔기 때문이다. IE는 한참이 지난 후에서야 표준을 준수하기 시작해쏙 지금은 오히려 많은 경우 다른 브라우저 이상으로 표준을 밀어붙이고 있다.

 

하지만 아직도 if (document.all){ /* it's IE */ }같은 낡은 코드가 사용 중이고 아마 완전히 박멸될 것 같지는 않는다고 한다. 이런 레거시 코드는 10여젼전 사용자들에게 불쾌한 경험을 선사했던, 구 IE 브라우저에 아직도 기대고 있다.

 

IE 개발팀 입장에선 document.all을 완전히 걷어낼 순 없지만 if (document.all) {}같은 코드가 옛날 처럼 잘 돌아가게 돠두면, 현대 IE에서는 표준을 준수하는 새로운 코드 로직을 갖게 되므로 난감했다. 어떻게 했을까..? 자바스크립트 타입 체계를 살짝 바꿔서 document.allfalsy인 것처럼 돌아가게 하자~!.. 였다.

truthy 값

truthy 값의 의미는 정확히 무엇일까? falsy 값 목록에 없으면 무조건이다.

 

var a = "false";
var b = "0";
var c = "' '";

var d = Boolean(a && b && c);
d;

d에는 어떤 값이 들어갈까? true아니면 false인데..

 

정답은 true다. 이유는? 문자열 값을 보면 falsy처럼 보이지만 무자열 값 자체는 모두 truthy이기 때문이다.(falsy 값 목록에 있는 유일한 문자열은 "" 이다.)

 

var a = []; // 빈 배열 - truthy일까? falsy일까?
var b = {}; // 빈 객체 - truthy일까? falsy일까?
var c = function () {}; // 빈 함수 - truthy일까? falsy일까?

var d = Boolean(a && b && c);
d;

 

다들 맞췄겠지만 이번에도 d는 true이다. 같은 이유에서이다. 외양이야 어떻든 [], {}, function(){}falsy값 목록에 없으므로 모두 truthy 값이다.

 

truthy 값 목록은 사실상 무한하여 일일이 작성하는 게 불가능하다. 그래서 몇 안되는 falsy 값 목록을 만들고 참조하라는 것이다.

truthy/falsy 개념은 어떤 값을 불리언 타입으로 강제변환 시 해당 값의 작동방식을 이해한다는 점에서 중요하다. 이제 우리는 두 목록을 모두 알고있으니 어던 강제변환 문제가 나와도 당황하지 않도 달려들 준비가 되었다.

 


참고

  • You Don't Know JS ( 한빛 미디어 )
728x90

댓글