스폰지밥 밈으로 알아보는 JavaScript 비교 연산자와 형 변환
개발 지식을 무겁지 않게 다룰 수 있는 방법이 있을까 고민하다가 밈을 이용해 보기로 했습니다. 해석이 필요한 활자에 비해 뭔가 무해한 첫인상을 가진 밈은 사람들의 경계심을 풀어주기에 좋은 소재니까요.
그래서 이번 시간에는 JavaScript 언어에 대한 밈 하나를 소개하고, 한 단계씩 해부해보도록 하겠습니다.
이보다 무해할 수 없는 뚱이와, 이보다 유해할 수 없는 내용의 환장의 콜라보를 들고 왔습니다.
자바스크립트에서 비교하는 연산자는 ==입니다. 그래서 a == b라고 적는다면 a와 b가 동일한 값인지 확인하고 같으면 true, 다르면 false를 반환합니다. 1==1 이면 true를 반환하겠죠.
밈을 요약하자면 아래와 같습니다.
분명 고등 교육에서 a = b, b = c 면 a = c라는 방정식 법칙을 배웠건만 왜 자바스크립트 코드에서는 엉뚱한 결과가 나올까요. 이해하신 분들을 웃으며 넘어가시면 되고 지금 웃지 못하고 계시는 분들을 위해 지금부터 한 단계씩 보도록 하겠습니다.
우선 맨 처음에 악당(?)은 0은 "0"과 같은지 물어봤고 우리의 뚱이 자바스크립트는 맞다고 답했습니다. 단순히 0이랑 0이랑 같으니까?라고 이해할 수 있지만 여러분은 대부분의 프로그래밍 언어들이 타입에 민감하다는 사실을 기억하셔야 합니다.
자바스크립트의 타입은 숫자(number), 문자열(string), 없는 값을 표현할 때 사용하는 null, undefined, 배열(array), 객체(object) 등이 있습니다. 그중 기본이 되는 타입들(숫자, 문자열 등)은 원시형 타입이라 부르고, 이런 원시형 타입을 값으로 가지는 타입들(배열, 객체 등)은 참조형 타입이라 부릅니다.
참고로 0은 숫자 타입, "0"은 따옴표로 감싸여 있으므로 문자열 타입입니다.
그럼 왜 자바스크립트는 숫자 타입과 문자열 타입이 같다고 얘기하고 있을까요? 그 이유는 자바스크립트는 두 피연산자의 타입이 다를 경우, 비교하기 전에 동일한 타입으로 변환하기 때문입니다. 이걸 암시적 형 변환(Explicit Type Conversion)이라고 합니다. 왜 우리 의사도 묻지 않고 마음대로 타입을 바꾸는지 따져보고 싶지만 어쩔 수 없습니다. 자바스크립트니까요.
여하튼 어떤 기준에 따라 변환하는지에 대해선 공식 명세 에서 자세히 설명하고 있으며, 여기서 우리가 주목해야 할 부분은 딱 2가지입니다.
1. 숫자와 문자열을 비교할 경우, 문자열을 숫자로 변환하도록 합니다.
2. 하나의 피연산자가 참조형 타입이고 다른 하나가 문자열이나 숫자 타입이면, 피연산자를 valueOf()나 toString()등을 사용해 원시형 타입으로 변환하도록 합니다.
쉽게 설명하자면 숫자랑 문자열이 붙으면 문자열이 숫자로 탈바꿈하고, 원시형 타입(문자열, 숫자 등) 과 참조형 타입(배열, 객체 등) 이 붙으면 참조형에 요런조런 작업을 해서 비교 대상의 타입처럼 바꾼다는 거죠. 조금 감이 잡히시나요?
어떻게 바뀌는 지도 알았으니 다시 돌아가 0 == "0"를 비교해 보겠습니다.
0 == "0"의 경우 아까 언급했듯 숫자 타입과 문자열 타입의 비교입니다. 그리고 공식 문서 1번에서 이 두 타입을 비교할 경우 문자열이 숫자 타입으로 변환된다고 했죠. 그럼 값을 number타입으로 바꾸는 Number() 함수를 써서 "0"이 어떻게 바뀌는지 봅시다.
"0"은 0이 되었네요. 그리고 0과 0은 같은 값이니 이 식의 결과는 true가 맞다는 사실을 알 수 있습니다. 그럼 빠르게 다음 짤을 볼까요.
이번에는 0과 []의 비교네요. 0은 아까 언급했듯 숫자 타입이고, []는 [1, 2, 3] 이런 식으로 안에 값을 담을 수 있는 배열 타입입니다. 그리고 배열 타입은 아까 예시처럼 안에 원시형 타입을 넣을 수 있기 때문에 참조형 타입이죠. 그럼 공식 문서 2번에 나왔던 것처럼 배열 타입을 옆에 있는 숫자 타입처럼 바꿔서 보면 되겠죠? 아까처럼 Number() 함수를 사용하여 한 번 어떤 값이 나오는지 봅시다.
0이 나왔네요! 왜냐하면 []는 값이 없는 빈 배열이고, 숫자의 세계에서 아무것도 없다는 뜻에 가장 잘 어울리는 수는 0이니까요. 그럼 0 == 0 이 되어 이것 또한 true가 나오는 것이 맞겠군요.
이제 대망의 마지막 짤로 넘어가 봅시다.
'0' == [] 은 위의 두 번째 짤과 같이 배열 타입을 비교 대상의 타입으로 변경하면 됩니다. '0'은 string 타입이니까 이번에는 값을 string 타입으로 변환하는 toString() 함수를 쓰면 되겠네요. 한 번 결과를 볼까요?
예상하신 분도 계시겠지만 ""이 나왔네요. 보통 타입이 문자열이고 값이 없는 경우는 이렇게 따옴표만 붙여 빈 문자열임을 표현합니다.
"0"이 아닌 이유는 "0"은 값이 없는 게 아니라 0이라는 문자가 들어 있는 문자열이기 때문입니다.
결과적으로 "" == "0"를 묻는 것이 되고, 같은 타입끼리 비교하는 경우는 정확히 그 값이 일치해야 하기 때문에 결과는 false가 나옵니다. 왜 true가 아니었는지 이제 이해가 되셨나요?
사실 이런 비교 자체가 정상적이진 않습니다. 정확한 연산을 요구하는 코딩의 세계에서 괜한 오류를 만들 여지가 있으니까요. 이런 불만을 가진 사람은 한둘이 아니었고, 몸에 화가 가득 찬 자바스크립트 유저들을 보다 못한 JavaScript는 마침내 자동 형 변환을 하지 않고 값을 그대로 비교하는 연산자를 만들어 냅니다. 그게 바로 triple equal 연산자 (===)입니다. 그래서 이 === 연산자를 사용하면 0 === "0" 도 false, 0 === [] 도 false가 나오죠.
오늘은 귀여운 뚱이 밈을 이용해 자바스크립트에서 어떤 과정을 거쳐 값을 비교하는지 알아봤습니다. 저 작은 밈 하나에 이렇게 많은 정보가 들어있다니 신기하죠? 저도 신기하네요.
그럼 다음 시간에는 더 흥미로운 이야기로 찾아뵙겠습니다.
== 는 JavaScript에서 양쪽의 값을 비교하는 비교 연산자다.
== 를 이용해 다른 타입끼리 비교할 때 JavaScript는 임의로 형 변환을 한 뒤에 비교한다.
타입을 변경하지 않고 엄격히 비교하는 === 연산자를 쓰는 것이 정신건강에 이롭다.