전체 목록
JavaScriptEasy#06

== 와 === 의 차이점은 무엇인가요?

#JS#연산자#타입
힌트

타입 강제 변환(type coercion)의 발생 여부를 기준으로 설명해보세요.

정답 및 해설

== 와 === 의 차이점은 무엇인가요?

JavaScript에는 두 가지 동등 비교 연산자가 있습니다. ==(동등 연산자)와 ===(일치 연산자)입니다. 가장 큰 차이는 타입 강제 변환(Type Coercion) 의 수행 여부입니다. 이 차이를 이해하지 못하면 예상치 못한 버그가 발생할 수 있습니다.

핵심 차이

연산자이름타입 변환비교 기준
==동등 연산자 (Loose Equality)수행값만 비교
===일치 연산자 (Strict Equality)수행 안 함값 + 타입 모두 비교

=== (일치 연산자)

타입 변환 없이 값과 타입이 모두 같아야 true를 반환합니다. 예측 가능하고 직관적입니다.

// 같은 타입, 같은 값
console.log(1 === 1);         // true
console.log('hello' === 'hello'); // true
console.log(true === true);   // true

// 다른 타입
console.log(1 === '1');       // false (number vs string)
console.log(0 === false);     // false (number vs boolean)
console.log(null === undefined); // false

// 참조 타입 — 참조(주소)를 비교
const a = { x: 1 };
const b = { x: 1 };
const c = a;
console.log(a === b); // false (다른 객체)
console.log(a === c); // true (같은 참조)

== (동등 연산자)

비교 전에 **타입 강제 변환(Type Coercion)**을 수행합니다. ECMA 명세의 추상 동등 비교 알고리즘에 따라 동작하며, 규칙이 복잡하고 직관적이지 않습니다.

주요 변환 규칙

// 숫자와 문자열 비교 — 문자열을 숫자로 변환
console.log(1 == '1');   // true  (문자열 '1'이 숫자 1로 변환)
console.log(0 == '');    // true  (빈 문자열이 0으로 변환)
console.log(0 == '0');   // true  ('0'이 0으로 변환)

// null과 undefined — 서로만 느슨하게 같음
console.log(null == undefined); // true
console.log(null == 0);         // false
console.log(null == '');        // false
console.log(undefined == 0);   // false
console.log(undefined == '');  // false

// 불리언 비교 — 불리언이 먼저 숫자로 변환됨
console.log(0 == false);  // true  (false가 0으로 변환)
console.log(1 == true);   // true  (true가 1로 변환)
console.log(2 == true);   // false (true가 1이 되므로 2 != 1)
console.log('' == false); // true  (false → 0, '' → 0)

// 객체와 원시값 비교 — valueOf/toString 호출
console.log([] == 0);    // true  ([] → '' → 0)
console.log([] == '');   // true  ([] → '')
console.log([1] == 1);   // true  ([1] → '1' → 1)
console.log({} == '[object Object]'); // true ({}.toString())

헷갈리는 예시 모음

// 직관과 다른 결과들
console.log('' == false);   // true
console.log('0' == false);  // true  ('0' → 0, false → 0)
console.log('' == '0');     // false (둘 다 string, 값이 다름)

// null 관련 특이 사항
console.log(null == false); // false (특별 규칙)
console.log(null == 0);     // false (특별 규칙)

// NaN은 자기 자신과도 같지 않음
console.log(NaN == NaN);  // false
console.log(NaN === NaN); // false
// NaN 체크는 Number.isNaN() 사용
console.log(Number.isNaN(NaN)); // true

타입 강제 변환 흐름

x == y 평가 시 타입에 따른 변환 규칙을 간략히 정리하면 다음과 같습니다.

x와 y의 타입이 같으면 → === 비교
x 또는 y가 null/undefined이면 → 둘 다 null/undefined인 경우만 true
x 또는 y가 boolean이면 → 숫자로 변환 후 재비교
string == number이면 → string을 숫자로 변환 후 재비교
object == primitive이면 → object.valueOf() 또는 object.toString() 후 재비교

실무에서의 권장 사항

=== 를 기본으로 사용

// 나쁜 예 — 예상치 못한 결과 가능
function isEmpty(value) {
  return value == null; // null과 undefined 모두 잡음 (의도적인 경우 제외)
}

// 좋은 예 — 명확한 의도
function isNullOrUndefined(value) {
  return value === null || value === undefined;
}

// 또는 이 경우만 == 사용 (null check 관용 표현)
function isNullOrUndefined(value) {
  return value == null; // null과 undefined만 true, 다른 falsy 값은 false
}

== 를 의도적으로 사용하는 경우

실무에서 ==를 허용하는 거의 유일한 경우는 null 체크입니다.

// null 또는 undefined 모두를 체크할 때
// 이 두 경우는 동일한 의미
if (user == null) { /* user가 null이거나 undefined */ }
if (user === null || user === undefined) { /* 위와 동일 */ }

ESLint 설정

대부분의 프로젝트에서는 ESLint의 eqeqeq 규칙으로 == 사용을 강제로 금지합니다.

// .eslintrc.json
{
  "rules": {
    "eqeqeq": ["error", "always", { "null": "ignore" }]
    // "always": 항상 === 사용
    // "null": "ignore": null 비교 시 == 허용
  }
}

Object.is() — 엣지 케이스 처리

ES6에서 도입된 Object.is()===와 거의 동일하지만, NaN-0 / +0 구분에서 차이가 있습니다.

// NaN 처리 차이
console.log(NaN === NaN);         // false
console.log(Object.is(NaN, NaN)); // true

// -0 / +0 처리 차이
console.log(+0 === -0);           // true
console.log(Object.is(+0, -0));   // false

// 나머지는 동일
console.log(Object.is(1, 1));     // true
console.log(Object.is('a', 'a')); // true

정리

  • ===는 타입과 값을 모두 비교하며, 예측 가능하고 안전합니다.
  • ==는 타입 강제 변환을 수행하며, 결과가 직관적이지 않을 수 있습니다.
  • 실무에서는 ===를 기본으로 사용하고, null / undefined 체크 시에만 == null 관용 표현을 허용하는 것이 일반적입니다.
  • NaN 비교에는 Number.isNaN() 또는 Object.is()를 사용합니다.