03. 연산자와 표현식
사칙연산 외에도 나머지 `%`, 거듭제곱 `**`, 증감 `++`/`--` 가 있습니다. 할당 연산자 `+=`, `-=` 등은 짧고 자주 쓰입니다.
이 강의에서 배우는 것
- 1산술/할당/비교/논리 연산자를 상황에 맞게 사용할 수 있다.
- 2`==` 와 `===` 의 차이를 이해하고 `===` 를 기본으로 사용한다.
- 3단축 평가(short-circuit) 와 nullish 병합(`??`) 을 활용할 수 있다.
- 4옵셔널 체이닝(`?.`) 으로 안전하게 속성에 접근할 수 있다.
- 5표현식과 문(statement) 의 차이를 설명할 수 있다.
소개
사칙연산 외에도 나머지 `%`, 거듭제곱 `**`, 증감 `++`/`--` 가 있습니다. 할당 연산자 `+=`, `-=` 등은 짧고 자주 쓰입니다.
핵심 개념
1. 산술과 할당
사칙연산 외에도 나머지 `%`, 거듭제곱 `**`, 증감 `++`/`--` 가 있습니다. 할당 연산자 `+=`, `-=` 등은 짧고 자주 쓰입니다.
let n = 10;
n **= 2; // 100
n %= 7; // 100 % 7 = 22. 비교 연산자
`==` 은 타입을 변환해 비교하고, `===` 은 타입까지 같은지 비교합니다. 거의 모든 상황에서 `===` 를 사용하세요.
0 == ""; // true
0 === ""; // false
NaN === NaN; // false → Number.isNaN 사용3. 논리 연산자와 단축 평가
`&&`, `||` 는 boolean 으로만 평가하지 않고 원본 피연산자를 반환합니다. `??` 는 `null` 또는 `undefined` 일 때만 오른쪽 값을 사용합니다.
const name = userName || "익명"; // userName 이 falsy 면 "익명"
const port = process.env.PORT ?? 3000; // null/undefined 일 때만 30004. 옵셔널 체이닝
`?.` 은 좌측이 `null` 또는 `undefined` 면 평가를 멈추고 `undefined` 를 반환합니다. 깊은 객체에 안전하게 접근할 때 유용합니다.
const city = user?.address?.city ?? "미상";
fn?.(); // fn 이 있으면 호출
arr?.[0]; // arr 가 있으면 첫 요소핵심 예제
| 파일 | 다루는 내용 |
|---|---|
| `01_arithmetic.js` | 산술/할당 연산자와 거듭제곱, 나머지 |
| `02_comparison.js` | `==` vs `===` 와 NaN 비교 |
| `03_logical.js` | `&&`, ` |
| `04_optional_chaining.js` | `?.` 로 안전한 속성 접근 |
src/01_arithmetic.js
/** 산술/할당 연산자를 살펴본다. */
const a = 17;
const b = 5;
console.log("a + b =", a + b);
console.log("a - b =", a - b);
console.log("a * b =", a * b);
console.log("a / b =", a / b);
console.log("a % b =", a % b);
console.log("a ** b =", a ** b);
let n = 10;
n += 5; console.log("n += 5 →", n);
n *= 2; console.log("n *= 2 →", n);
n **= 2; console.log("n **= 2 →", n);
src/02_comparison.js
/** == 와 === 의 차이, NaN 비교를 확인한다. */
console.log(0 == ""); // true
console.log(0 === ""); // false
console.log(null == undefined); // true
console.log(null === undefined); // false
console.log(NaN === NaN); // false
console.log(Number.isNaN(NaN)); // true
console.log(Object.is(NaN, NaN)); // true
src/03_logical.js
/** &&, ||, ?? 의 단축 평가를 비교한다. */
const empty = "";
const zero = 0;
console.log(empty || "기본값"); // "기본값" (empty 가 falsy)
console.log(empty ?? "기본값"); // "" (null/undefined 아님)
console.log(zero || 100); // 100
console.log(zero ?? 100); // 0
// && 는 첫 falsy 또는 마지막 값을 반환
console.log(true && "ok"); // "ok"
console.log(0 && "skip"); // 0
src/04_optional_chaining.js
/** 옵셔널 체이닝으로 안전하게 접근한다. */
const user = {
name: "Ada",
address: { city: "London" },
};
console.log(user?.address?.city); // "London"
console.log(user?.company?.name); // undefined
console.log(user?.company?.name ?? "무직"); // "무직"
const maybeFn = undefined;
console.log(maybeFn?.()); // undefined (에러 아님)
const arr = null;
console.log(arr?.[0]); // undefined
자주 하는 실수
- `0 || default` 패턴에서 `0` 을 유효한 값으로 쓰고 싶을 때 `??` 가 필요한데 `||` 를 쓰는 경우.
- 부동소수점 연산 결과 (`0.1 + 0.2 !== 0.3`) 를 정확하다고 가정하는 경우.
- `NaN === NaN` 이 false 인 것을 잊고 `=== NaN` 으로 비교하려는 시도.
- `++x` 와 `x++` 의 차이로 인한 미묘한 버그.
- `a?.b.c` 처럼 첫 단계만 옵셔널로 만들고 뒤를 빠뜨리는 경우.
FAQ
Q1. `==` 는 절대 쓰면 안 되나요?
`x == null` 로 null/undefined 를 한꺼번에 체크하는 관용구 외에는 권장하지 않습니다.
Q2. `??` 와 `||` 중 무엇을 기본으로?
"값이 없을 때 기본값" 이라는 의도라면 `??` 가 더 안전합니다. `0`, `""` 를 유효한 값으로 다룰 수 있기 때문입니다.
Q3. 표현식과 문의 차이는?
표현식은 값으로 평가됩니다. 문은 동작을 수행합니다. `if (...)` 는 문, `a ? b : c` 는 표현식입니다.
과제
- `homework_01.js` — 두 숫자의 합/차/몫/나머지/거듭제곱을 표로 출력.
- `homework_02.js` — 중첩 객체에서 `?.` 와 `??` 로 안전한 값을 추출.
homework/README.md
## homework_01.js
- 두 숫자 `a`, `b` 를 상수로 정의하고, +, -, *, /, %, ** 결과를 `console.table` 로 출력하세요.
## homework_02.js
- 중첩 객체 `order.customer.address.city` 를 옵셔널 체이닝으로 안전하게 가져오세요.
- 없으면 "주소 미입력" 을 기본값으로 사용하세요.
- 일부 속성이 빠진 객체로도 테스트해 보세요.
homework/answer/homework_01.js
/** 두 숫자의 산술 결과를 표로 출력한다. */
const a = 13;
const b = 4;
const result = {
"+": a + b,
"-": a - b,
"*": a * b,
"/": a / b,
"%": a % b,
"**": a ** b,
};
console.table(result);
homework/answer/homework_02.js
/** 옵셔널 체이닝과 nullish 병합으로 안전한 값을 얻는다. */
const orders = [
{ id: 1, customer: { name: "A", address: { city: "Seoul" } } },
{ id: 2, customer: { name: "B" } },
{ id: 3 },
];
for (const order of orders) {
const city = order?.customer?.address?.city ?? "주소 미입력";
console.log(`주문 ${order.id}: ${city}`);
}
다음 단원
[04_제어문](../04_제어문/) — 조건과 반복으로 흐름을 제어합니다.