안녕하세요, 단테입니다.
자바스크립트를 처음 배우며 만나는 객체 간의 reference, value 비교에 있어서 많은 분들이 === 사용을 당연하게 받아들입니다.
웬만한 코드에서는 ==
를 보기 어렵기 때문에 ===
사용이 자연스럽게 되고 ==
를 피하는 것에 대해 별다른 의문을 가지게 되지 않는 것 같습니다.
본 글은 경우에 따라 ==
를 사용해야 한다고 말하지 않습니다.
오히려 경우에 따라 ==
를 사용해도 되는 상황이라도 ==
를 권장하는게 맞는지 생각해보며 적은 글입니다.
우리는 코드 한 줄을 줄이는데 생각보다 큰 점수를 주고는 합니다. 삼항 연산자를 두번 이상 연결해 사용하면 가독성이 낮춰지지만 그래도 if else 문을 사용하는 것을 많은 사람들이 꺼려하곤 합니다.
you don't know JS의 저자 카일 심슨은 ==를 사용하는 것이 더 나은 경우가 있다고 합니다.
https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/types-grammar/ch4.md#type-aware-equality
https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/types-grammar/ch4.md#type-aware-equality
임의의 객체, 값 a,b를 비교할 때 ==, ===의 차이점에 대해 먼저 알아보겠습니다.
즉, ===는 Type Aware Equality를 체크합니다.
if(... ) {
}
== ,=== 를 사용하는 상황은 크게 두가지로 나뉩니다.
a,b가 동일한 타입일 때는 ==
를 사용해도 coercion이 발생하지 않습니다.
카일 심슨은 이 경우 =를 추가적으로 사용하는 것은 좋지 않다고 합니다.
if( x == y ) { // best
}
if( x === y ) { // strictly worse
}
근데 이건 사용자 측에서 type assertion 구문을 안쓴다고 엄격하게 가정할 때 이야기입니다.
코드를 작성하다보면 type assertion을 어쩔 수 없이 해야 하는 경우가 있습니다.
==
를 사용해서 예상치 못한 type coercion이 발생했을 때 개발자가 아! ==를 써서 type coercion이 발생했을 수 있겠군, 이 버그는 그 부분에서 발생했을 거야
라고 운 좋게 떠올리지 않으면 이 문제점을 찾기 어렵겠죠. IDE에서 이 부분은 빨간줄로 표시되지 않으니까요.
===를 썼을 때 문제되는 지점이 있을까요?
동일한 타입이 아니라면 다음 if문 내부는 실행되지 않습니다.
카일 심슨은 따라서 ===를 사용하면 안된다고 합니다.
if ( x === y) {
...
}
저는 이부분을 읽을 때 상당한 의아함을 느꼈습니다.
===
를 쓰는 이유는 타입까지 같이 포함해서 equality를 비교하려고 의도적
으로 ===
를 작성하는 것인데
if 문 내부가 실행되지 않는 것을 마치 false positive 처럼 생각한다니?
비교 구문을 작성할 때 coercion을 고려해서 ==를 사용하는게 맞는 것인가?
x == y
이걸 다 감안하고 ==를 사용해? 🤔 거의 프로젝트 온보딩의 한 부분으로 할당해야하는 수준이겠는걸
좋습니다. 일단 넘어가고 타입이 다른 경우 어떤 선택지가 남는지 봅시다.
타입이 다른 두 객체 및 값을 비교하는 경우를 피하도록 코드를 재작성한다.
아뇨 전 싫습니다. 비 맞기 싫다고 건물 내부로만 걸어다니진 않을 겁니다.
==
// `x` and `y` have different types,
// so let's allow JS to coerce them
// for equality comparison
if (x == y) {
// .. (so, you're saying there's a chance?)
}
coercion을 감수하고 == 비교를 해요? 왜 그래야하죠?
카일 심슨은 타입을 모르는 Unknown Types를 사용하는 상황에서는 코드를 고치는 것이 최선이라고 말하지만,
타입스크립트에서 Union type을 사용하는 경우에는 개발자가 작성하는 ㅎ마수에서 런타임에서 어떤 타입의 인자를 받을지 모릅니다.
비교 피연산자의 타입을 보장하지 않는 채로 coercion을 발생시키는 것은 바람직하지 않습니다.
이럴 떄는 ===를 사용하는 것이 더 안전하겠죠.
MDN 문서에 다음의 코드가 있습니다.
const temp = obj.first;
const nestedProp = temp === null || temp === undefined ? undefined : temp.second
==를 활용하면 다음과 같이 코드를 줄일 수 있습니다.
const nestedProp = temp == null ? undefined : temp.second;
==
를 사용해도 temp가 nullish한지 체크를 할 수 있어서 ===를 사용하지 않아도 되는 것인데요,
optional chaining을 사용하면 다음과 같이 줄일 수 있습니다.
const nestedProp = temp?.second;
coercion을 사용해서 코드를 줄일 수 있기 때문에 === 대신 ==를 사용하는 것은 제가 보기에는
안전 장치를 미리 풀어놓으면 빠르게 총을 쏠 수 있기 때문에 나는 주머니에 총을 넣어두기 전에 미리 안전 장치를 해제해두겠다
고 말하는 것과 다를 바가 없습니다.
let result = (42 == "42");
js에서 42 == "42"는 coercion이 되기 때문에 true입니다.
ts에서 위 코드는 허용되지 않습니다.
이게 런타임에서 true로 동작할지 모르지만 42 =="42" 를 비교하는 경우는 많지 않다고 봅니다.
타입이 다르면 다르게 간주되는게 더 적절한 것 같습니다.
javascript는 이해하기 어렵게 동작하는 부분이 있습니다.
좋게 말해서 우리 애는 개성이 넘쳐요. 가끔 이해하기 어렵게 행동한답니다.
이지
사실 큰 글자로 경고 문구를 붙여놓아야 하는 언어입니다.
안전장치를 붙일 수 있으면 붙여놓고 사용해야죠.
불편하니 안전장치를 해제할 수 있는 경우를 다 외워두어야 한다는 여러 명이 작업하는 환경에서는 받아들이기 어려운 부분입니다.
저는 함께 코드를 작성하는 입장에서 불필요한 coercion 고민과 오해의 가능성을 남겨두는 것을 지양하고 싶습니다.