연산자와 비교 — === 와 == 의 차이
산술·비교·논리 연산자, 그리고 영원한 입문 함정 == 의 타입 강제 변환.
5편은 입문 파트의 마지막 — 연산자입니다. 산술·비교·논리 세 카테고리를 빠르게 훑고, 입문자의 가장 큰 함정인 == 의 타입 강제 변환을 정리합니다. 결론부터: 항상 === 를 쓰세요.
산술 연산자 — 6개 + 하나의 함정
10 + 3 // 13
10 - 3 // 7
10 * 3 // 30
10 / 3 // 3.3333...
10 % 3 // 1 (나머지)
10 ** 3 // 1000 (제곱, ES2016+)
// 함정: + 는 문자열일 때 "이어 붙이기"
"3" + 2 // "32" ← !!
3 + "2" // "32"
1 + 2 + "3" // "33" (왼쪽부터 평가, 1+2=3, 그 다음 string)
"1" + 2 + 3 // "123" (한 번 string 되면 끝까지)
이중 인생. + 는 number 끼리면 더하기, 한 쪽이 string 이면 이어 붙이기. 사용자 입력은 Number() 로 변환하거나, 한국에서 자주 쓰는 패턴은 단항 +x — +"3" === 3. 명시적 변환이 가장 안전합니다.
비교 연산자 — === 와 == 의 진실
// === : 엄격 동등 — 타입까지 같아야 true
"3" === 3 // false
1 === 1 // true
null === undefined // false
// == : 느슨 동등 — 타입 다르면 강제 변환 후 비교
"3" == 3 // true ← string→number
0 == false // true
"" == false // true
null == undefined // true
[] == false // true ← !! 빈 배열이 false?
// !== / != 도 같은 규칙
== 는 1995년에 만든 규칙이 너무 관대해서 예측이 어렵습니다. 위 표만 봐도 머리가 아프죠. 새 코드는 무조건 ===, !== — 예외는 x == null(null 과 undefined 한 번에 확인) 정도밖에 없습니다.
ESLint 가 강제. 대부분의 팀이 eqeqeq 규칙으로 == 사용 자체를 금지합니다. 한 줄을 빨갛게 그어주는 안전벨트라고 생각하세요.
대소 비교 — 그대로
5 < 10 // true
5 <= 5 // true
5 > 10 // false
// 문자열도 비교 가능 — 사전순(유니코드 코드 포인트)
"a" < "b" // true
"가" < "다" // true
// 한 가지 함정 — NaN 은 어떤 비교도 false
NaN < 1 // false
NaN > 1 // false
NaN === NaN // false
논리 연산자 — &&·||·! 와 단락 평가
true && "yes" // "yes" (왼쪽이 truthy 면 오른쪽 그대로)
false && "yes" // false (왼쪽이 falsy 면 왼쪽 그대로)
true || "yes" // true
false || "yes" // "yes" (왼쪽이 falsy 면 오른쪽)
// 그래서 기본값 패턴
const name = userName || "익명";
const port = config.port || 3000;
이게 단락 평가(short-circuit) — JS 의 &&·|| 는 boolean 으로 변환하지 않고 마지막으로 평가된 값을 그대로 반환합니다. 그 결과 다음과 같은 표현이 가능해집니다.
// 함수가 있으면 실행 (옵셔널 체이닝 ?. 이 더 안전)
callback && callback();
// React 조건부 렌더
{isLoggedIn && <UserMenu />}
?? — nullish 병합 (가장 안전한 기본값)
// || 는 0·""·false 까지 "비어있다" 로 본다 — 의도와 다를 수 있음
const count = 0;
const c1 = count || 10; // 10 ← count 가 0이면 기본값으로 덮음
const c2 = count ?? 10; // 0 ← null/undefined 만 덮음
?? 권장. 0·""·false 가 유효한 값인 경우(점수·이름·플래그) 가 많기 때문에, 새 코드의 기본값은 ?? 입니다. || 는 "어떤 falsy 든 다 갈아엎기" 의도일 때만.
truthy / falsy — 한 번에 정리
falsy 6개만 외우세요. 나머지는 모두 truthy.
| 분류 | 값들 |
|---|---|
| falsy (6개) | false · 0 · "" · null · undefined · NaN |
| truthy | 위 6개 빼고 전부 — "0"·[]·{} 도 truthy! |
if ("0") console.log("실행됨"); // 실행됨 — 문자열 "0" 은 truthy
if ([]) console.log("실행됨"); // 실행됨 — 빈 배열도 truthy!
if ({}) console.log("실행됨"); // 실행됨 — 빈 객체도 truthy
// 배열이 비었는지 확인은 length 로
if (arr.length === 0) ...
6편 — 조건문 if·else·switch
입문 파트가 끝나고 기초 파트로. 조건 분기를 보기 좋게 쓰는 법, switch 가 좋을 때와 if 가 좋을 때.
이전: 4편 자료형 · 현재: 5편 (입문 마지막) · 다음 → 6편 조건문 (기초 파트 시작) · 진행: 5/26