Menu

자바스크립트 == vs === 차이와 Object.is 완벽 정리

자바스크립트의 동등 연산자 == 와 ===, 그리고 Object.is까지. 타입 강제 변환, NaN 비교, 객체 참조 비교의 함정을 예제로 정리했습니다.

이 페이지에는 실행 가능한 에디터가 있습니다 — 편집하고 실행하면 결과를 바로 볼 수 있습니다.

"같다"를 묻는 두 가지 방법

자바스크립트에는 동등 연산자가 두 개 있습니다. 엄격 비교 ===와 느슨한 비교 ==죠. 생김새는 거의 똑같지만, 동작은 완전히 다릅니다.

===는 양쪽 피연산자의 타입과 값이 모두 같은지 확인합니다. 반면 ==는 먼저 공통 타입으로 변환한 뒤 비교하죠. 바로 이 변환 과정, 즉 **타입 강제 변환(type coercion)**이 자바스크립트의 동등 비교가 악명을 얻게 된 주범입니다.

짧게 요약하면, 기본적으로는 ===를 쓰세요. 하지만 왜 ==를 피하는지 그 이유는 한 번쯤 제대로 알아둘 가치가 있습니다.

엄격 비교(===): 대부분의 경우 이게 정답

===는 타입과 값이 모두 일치할 때만 true를 반환합니다. 타입 변환도, 의외의 결과도 없죠:

타입이 다르면 결과는 곧바로 false입니다. 반대로 타입이 같으면 자바스크립트는 값을 비교하는데, 원시 타입(primitive)은 값 자체를 비교하고 객체는 참조(reference)를 비교합니다. 객체 비교에 대해서는 잠시 뒤에 자세히 다루겠습니다.

!==는 엄격 부등 연산자이며, 같은 규칙을 그대로 뒤집어 적용합니다.

느슨한 동등 비교: 숨겨진 타입 강제 변환

== 연산자는 양쪽의 타입이 달라도 괜찮습니다. 대신 비교하기 전에 양쪽 타입을 맞추려고 타입 강제 변환(coercion) 과정을 거칩니다.

정확한 규칙은 명세에 다 적혀 있고 뜯어보면 그렇게 끔찍한 수준은 아니지만, 디버깅 한창일 때 그걸 머릿속에서 떠올리는 건 또 다른 얘기죠. "0" == falsetrue라는 사실은 경력 많은 개발자도 종종 헷갈립니다. [] == false도 마찬가지예요 (배열이 ""로 강제 변환되고, 그게 다시 0으로 변환되기 때문에 결과는 true입니다).

대부분의 스타일 가이드와 ESLint의 eqeqeq 규칙이 기본적으로 ===를 쓰라고 권하는 이유가 여기에 있습니다. 키 하나 더 치는 대신 머리로 기억할 수 있는 규칙을 얻는 거죠.

알아둘 만한 단 하나의 == 패턴

그래도 느슨한 동등 비교(==) 중에 딱 하나 기억해둘 만한 관용 패턴이 있습니다. 바로 x == null인데요, xnull이거나 undefined일 때 true를 반환하고 그 외에는 모두 false를 반환합니다.

엄격하게 쓰자면 x === null || x === undefined가 되는데, 솔직히 좀 번잡해 보입니다. 그래서 많은 프로젝트에서 == null만큼은 유일한 예외로 허용하곤 합니다. 어느 쪽이든 규칙을 하나 정했으면 일관되게 지키는 게 중요합니다.

객체는 참조로 비교된다

객체, 배열, 함수를 비교할 때는 =====든 던지는 질문이 똑같습니다. "양쪽이 메모리상에서 같은 객체를 가리키고 있는가?" 라는 질문이지, "내용물이 같은가?"가 아닙니다.

내용이 똑같아 보이는 객체 리터럴 두 개도 자바스크립트에서는 엄연히 다른 객체입니다. 객체 비교를 처음 다룰 때 누구나 한 번은 걸려 넘어지는 부분이죠.

값 기반으로 객체를 비교하고 싶다면 직접 헬퍼 함수를 만들거나, 라이브러리(lodash.isequal)를 쓰거나, 단순한 평범한 객체라면 JSON.stringify로 직렬화해서 비교하는 방법을 씁니다:

JSON.stringify는 단순한 데이터에만 잘 동작합니다. 함수, undefined, 심볼은 무시되고, 엔진마다 모든 형태의 객체에서 키 순서를 보장해 주지도 않죠. 빠르게 확인할 때 쓰는 꼼수일 뿐, 범용 해법은 아닙니다.

NaN은 그 무엇과도 같지 않다

NaN("not a number")은 숫자 연산이 의미 있는 답을 낼 수 없을 때 자바스크립트가 돌려주는 값입니다. 예를 들어 0/0, Number("abc"), Math.sqrt(-1) 같은 경우죠. 두 동등 연산자(==, ===) 모두 한쪽이 NaN이면 false를 반환하고, 양쪽 다 NaN이어도 결과는 false입니다:

NaN을 판별하려면 Number.isNaN(value)을 사용하세요. 예전부터 있던 전역 isNaN은 쓰지 않는 게 좋습니다. 인자를 먼저 형 변환하기 때문에 isNaN("hello")true가 되는데, 이런 동작을 원하는 경우는 거의 없습니다.

Object.is: ===에 두 가지만 손본 비교

Object.is(a, b)는 기본적으로 ===와 동일하게 동작하지만, 딱 두 가지 경우에서 다르게 처리됩니다.

대부분의 경우에는 ===를 쓰면 됩니다. Object.is가 필요한 순간은 딱 두 가지예요. NaN을 자기 자신과 같다고 처리해야 할 때, 그리고 +0-0을 구분해야 할 때입니다. 둘 다 흔한 상황은 아니지만, 수치 계산 코드나 프레임워크 내부 구현에서는 가끔 중요하게 쓰입니다(실제로 React는 상태 비교에 Object.is를 사용합니다).

부등 연산자도 똑같이 두 갈래

!==는 엄격 비교, !=는 느슨한 비교예요. 앞서 말한 원칙이 그대로 적용됩니다:

기본은 !==입니다. 만약 == null 사용을 허용하는 스타일이라면, "null도 아니고 undefined도 아니다"를 확인하는 짝꿍인 != null도 함께 허용해도 좋습니다.

값을 비교할 때 체크리스트

두 값을 비교해야 할 때는 아래 순서대로 따져보세요.

  • 같은 타입의 원시값(primitive) 비교인가?===를 씁니다.
  • null이나 undefined 체크인가? → 스타일 가이드가 허용한다면 x == null로 간단히, 아니라면 x === null || x === undefined로 풀어 씁니다.
  • NaN 체크인가?Number.isNaN(x)를 씁니다.
  • 객체를 참조(identity) 기준으로 비교하는가?===가 정확히 그 역할을 합니다.
  • 객체를 내용(contents) 기준으로 비교하는가? → 직접 헬퍼 함수를 만들거나, 라이브러리를 쓰거나, 직렬화(serialize)해서 비교해야 합니다. 기본 연산자로는 해결되지 않습니다.

평소에는 ===만 고수하고, ==== null 패턴에서만 제한적으로 꺼내 쓴다는 원칙을 지키면, 자바스크립트 FAQ를 가득 채우는 동등 비교의 함정들을 대부분 피할 수 있습니다.

다음 주제: 연산자

동등 비교는 자바스크립트 연산자의 일부일 뿐입니다. 다음 문서에서는 산술 연산자, 논리 연산자, 할당 연산자, 그리고 실무에서 자주 쓰는 단축 연산자까지 나머지 연산자들을 차례로 살펴봅니다.

자주 묻는 질문

자바스크립트에서 == 와 === 는 어떻게 다른가요?

===는 엄격한 동등 비교(strict equality)로, 타입과 값이 모두 같아야 true를 반환합니다. 반면 ==는 느슨한 동등 비교(loose equality)라서, 비교 전에 양쪽 피연산자를 같은 타입으로 강제 변환합니다. 예를 들어 1 === '1'false지만, 1 == '1'은 문자열을 숫자로 변환하기 때문에 true가 됩니다.

자바스크립트에서는 무조건 === 만 쓰는 게 좋나요?

기본적으로는 ===를 쓰는 게 좋습니다. 규칙이 단순해서 머릿속으로 예측하기 쉽거든요. 유일하게 자주 쓰이는 예외가 x == null 패턴인데, 이렇게 쓰면 nullundefined를 한 번에 걸러낼 수 있습니다. ESLint의 eqeqeq 룰도 보통 ===를 강제하면서 이 패턴만 옵션으로 허용합니다.

왜 NaN === NaN 이 false인가요?

IEEE 754 표준에서 NaN은 자기 자신을 포함해 그 어떤 값과도 같지 않다고 정의되어 있습니다. 그래서 NaN이 낀 동등 비교는 무조건 false가 나와요. 어떤 값이 NaN인지 확인하려면 Number.isNaN(x)를 쓰거나, Object.is(NaN, NaN)을 쓰면 됩니다. Object.is는 이 경우 true를 돌려줍니다.

객체 두 개가 같은지 어떻게 비교하나요?

=====든 객체는 내용이 아닌 참조(reference)로 비교합니다. 그래서 {a: 1} === {a: 1}은 서로 다른 객체이기 때문에 false가 나와요. 내용까지 같은지 보려면 직접 비교 로직을 짜거나, Lodash의 isEqual 같은 라이브러리를 쓰거나, 단순한 plain object라면 JSON.stringify로 직렬화해서 비교하는 방법도 있습니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기