본문 바로가기
JAVASCRIPT

[JS][강제변환][마무리] 추상 관계 비교

by KBS 2022. 2. 13.
728x90

추상 관계 비교

이 암시적 강제변환은 비교적 덜 관심받는 분야지만 그래도 a < b 비교 과정에서 어떤 일들이 벌어지는지 잘 알아둬야 한다.

ES5 11.8.5 '추상적 관계 비교'알고리즘은 비교시 피연산자 모두 문자열일 때와 그 외의 경우, 두 가지로 분류된다.

명세에는 a < b에 대해서만 정의되어 있다. a > b는 b < a로 처리된다.

이 알고리즘은 먼저 두 피연산자에 대해 ToPrimitive 강제변환을 실시하는 것으로 시작한다. 그 결과 어느 한쪽이라도 문자열이 아닐 경우 양쪽 모두 ToNumber로 강제변환 하여 숫자 값으로 만들어 비교한다.

예를 들면,

var a = [42];
var b = ["43"];

a < b; // true
b < a; // false

 

-0과 NaN 등을 조심해야 하는 건 앞서 설명한 == 알고리즘이다.

그러나 < 비교 대상이 모두 문자열 값이면, 각 문자를 단순 어휘 비교 한다.

var a = ["42"];
var b = ["043"];

a < b; // false

 

두 배열을 ToPrimitive로 강제변환 하면 문자열이기 때문에 a, b는 숫자로 강제변환 하지 않는다. 따라서 "42"와 "043"을 문자 다누이로 비교한다.(우선 "4"와 "0"을 비교하고, 그다음 "2"와 "4"를 비교하는 식으로) "0"은 어휘상 "4"보다 작은 값이므로 비교는 처음부터 실패한다.

다음 코드 역시 수행 로직은 동일하다.

var a = [4, 2];
var b = [0, 4, 3];

a < b; // false

 

a는 "4, 2"로 b는 "0, 4, 3"문자열화 시킨 후 앞 예제와 마찬가지로 어휘 비교를 한다.

다른 예제를 보자.

var a = { b: 42 };
var b = { b: 43 };

a < b; // ??

 

결과는 false다. a도 [Object object], b도 [Obejct object]로 변환되어 어휘적인 비교를 할 수 없기 때문이다.

하지만 이상한 건,

var a = { b: 42 };
var b = { b: 43 };

a < b; // false
a == b; // false
a > b; // false

a <= b; // true
a >= b; // true

 

a == b는 왜 true가 아닐까? 둘 다 동일한 문자열이면 동등한 것 아닐까? 아니다. 이미 앞에서 ==이 객체 레퍼런스에서 어떻게 작동하는지 살펴봤다.

그건 그렇고 a < b, a == b, a > b모두 false인데 a <= b, a >= b는 어떻게 true인 걸까?

a <= b는 실제로 b < a의 평가 결과를 부정하도록 명세에 기술되어 있기 때문이다. 그래서 b < a가 false이므로 a <= b는 이를 부정한 true이다.

우리는 지금까지 <=이 '같거나 더 작은'이라는 부등호의 의미일 거라 당연시해왔겠지만, 참 짓궂게도 정반대일가능성도 있다. 실제로 자바스크립트 엔진은 <=를 '더 크지 않은
의 의미로 해석한다. 더구나 a >= b는 먼저 b <= a로 재해석한 다음 동일한 추론을 적용한다.

불행히도 동등비교에 관한 한 '엄격한 관계 비교'는 없다. 다시 말해, 비교 전 a와 b모두 명시적으로 동일한 타입임을 확실히 하는 방법 말고 a < b 같은 관계 비교 과정에서 암시적 강제변환을 원천 봉쇄할 수는 없다.

앞 에서 == 대 === 문제를 근본적으로 따져본 것과 같은ㅁ 원리다. 42 < "43"처럼 강제변환이 유용하고 어느 정도 안전한 관계 비교라면 그냥 사용하자. 반면, 조심해서 관계를 비교해야 할 것 같은 상황에서는 <를 사용하기 전, 비교할 값들을 명시적으로 강제변환 해주는 편이 안전하다.

정리하기

강제변환이라고 하는 자바스크립트의 타입변환의 작동 원리를 명시적/암시적 두가지 유형으로 나누어 알아보았다.

강제변환은 많은 욕얼 얻어먹는 애물단지지만 알고보며 많은 경우 꽤 유용한 기능이다. 자바스크립트 개발을 천직으로 생각하는 사람이라면 시간을 내서 강제변환을 꼼곰히 학습하고 강제변환의 어떤 특성을 적극 활용하고 어떤 부분은 조심해서 우회해야 할 지 잘 판단해서 결정해야 한다.

명시적 강제변환은 다른 타입의 값으로 변환하는 의도가 확실한 코드를 말하며 혼동의 여지를 줄이고 코드 가독성 및 유지 보수성을 높일 수 있는 장점이 있다.

암시적인 강제변환은 '숨겨진' 로직에 의한 부수효과가 있으며 타입변환이 처리되는 과정이 명확하지 않다. 그래서 암시적 강제벼노한이 명시적 강제변환의 정반대고 나쁜 것이라고들 하지만 실은 암시적 강제변환이 오히려 코드 가독성을 향상하는 장점도 있다.

암시적 강제변환은 변환 과정이 구체적으로 어떻게 일어나는지 명확하게 알고 사용해야 한다. 우리 스스로 지금 내가 무슨 코드를 짜고 있고 어덯게 작동할 거란 점은 알고 있어야 한다. 더 나아가 다른 개발자들도 쉽게 배우고 이해할 수 있는 코드를 작성하도록 노력하기 바란다.

 


참고

  • You Don't Know JS - 타입과 문법, 스코프와 클로저( 한빛 미디어 )
728x90

댓글