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()를 사용합니다.