본문으로 건너뛰기
기술스택 · stack/javascript/논리 연산자와 ??로 기본값 다루기

JavaScript · 2장 기본

논리 연산자와 ??로 기본값 다루기

"회원이면서 성인일 때", "이름이 없으면 손님으로"처럼 조건을 묶고 기본값을 채우는 일은 거의 모든 코드에 나와요. 논리 연산자가 실제로 무엇을 돌려주는지 알면, 짧고 정확한 코드를 쓸 수 있어요.

#2.7

01. &&, ||, !로 조건 묶기

&&(그리고)는 양쪽이 모두 참이어야, ||(또는)는 한쪽만 참이어도 참이에요. !(아니다)는 참과 거짓을 뒤집어요. 섞어 쓰면 ! → && → || 순서로 계산되는데, 읽는 사람이 순서를 따지지 않아도 되게 괄호로 묶어 쓰는 게 좋아요.

const isMember = true;
const age = 17;

console.log(isMember && age >= 19);         // false — 회원이지만 성인이 아니에요
console.log(isMember || age >= 19);         // true
console.log(!isMember);                     // false
console.log((isMember || age >= 19) && age > 10); // true

02. 답이 정해지면 멈춰요: 단락 평가

||와 &&는 왼쪽부터 값을 보다가 답이 정해지는 순간 멈추고, 그때 본 값을 그대로 돌려줘요. 결과가 꼭 true · false인 게 아니에요.

  • A || B: A가 참 같은 값이면 A를, 아니면 B를 돌려줘요. → "A가 없으면 B"
  • A && B: A가 거짓 같은 값이면 A를, 아니면 B를 돌려줘요. → "A가 있을 때만 B"
console.log('' || '이름 없음');      // 이름 없음
console.log('하늘' || '이름 없음');  // 하늘
console.log(0 && '여기는 안 봐요');  // 0
console.log(1 && '여기까지 봐요');   // 여기까지 봐요

const isAdmin = false;
isAdmin && console.log('관리자 메뉴를 보여요'); // 아무것도 출력하지 않아요
console.log('끝');

멈춘 뒤의 코드는 실행조차 되지 않아요. 그래서 isAdmin && showMenu()처럼 "조건이 맞을 때만 함수 부르기"를 한 줄로 쓰기도 해요. 다만 읽기 쉬운 건 여전히 if라서, 화면 템플릿(React의 JSX 등)처럼 식만 쓸 수 있는 자리가 아니면 if를 권해요.

03. || 대신 ??: 0과 빈 문자열 지키기

||로 기본값을 채우면 문제가 하나 있어요. 0, '', false도 거짓 같은 값이라 정상 값인데도 기본값으로 바꿔 버려요. 음량 0, 할인율 0, 빈 메모는 "값이 없음"이 아니라 "0이라는 값"인데도요.

??(널 병합 연산자)는 왼쪽이 null이나 undefined일 때만 오른쪽을 써요. 그래서 기본값을 채울 때는 ??가 맞는 경우가 대부분이에요.

①여섯 값에 각각 || '기본'과 ?? '기본'을 붙여 봐요. ||는 0 · '' · false · NaN까지 '기본'으로 바꾸지만, ??는 null과 undefined만 바꾸고 나머지는 그대로 둬요.
const settings = { volume: 0, nickname: '' };

console.log(settings.volume || 50);  // 50 — 0을 "없음"으로 봤어요
console.log(settings.volume ?? 50);  // 0
console.log(`[${settings.nickname || '손님'}]`); // [손님]
console.log(`[${settings.nickname ?? '손님'}]`); // [] — 빈 문자열을 지켰어요
console.log(settings.theme ?? 'light');          // light — 없는 속성은 undefined라서 기본값

앞 글의 객체 표에도 바로 쓸 수 있어요. STATUS_LABEL[status] ?? '알 수 없는 상태'처럼요. 한 가지 규칙이 있어요. ??를 || · &&와 괄호 없이 섞으면 문법 오류예요. 어느 쪽을 먼저 계산할지 괄호로 밝혀야 해요.

const a = null, b = 0;
console.log(a ?? b || 'c');

04. ??=, ||=, &&=

"비어 있으면 기본값을 넣어 두기"는 자주 하는 일이라 줄임 표기가 있어요. x ??= 값은 x가 null · undefined일 때만 값을 넣어요. 같은 방식으로 ||=와 &&=도 있어요.

const options = { retries: 0 };
options.retries ??= 3;       // 0은 값이 있는 거라 그대로
options.timeoutMs ??= 5000;  // 없던 속성이라 채워요
console.log(options);        // { retries: 0, timeoutMs: 5000 }

할인율을 주지 않으면 10%를 기본으로 할인하는 함수예요. 그런데 "할인 없음"을 뜻하는 0을 넣어도 10%가 할인돼요. 한 곳을 고쳐서 세 줄이 차례로 8000, 9000, 10000이 나오게 해 보세요.

function finalPrice(price, discountRate) {
  const rate = discountRate || 0.1;
  return price * (1 - rate);
}

console.log(finalPrice(10000, 0.2));
console.log(finalPrice(10000));
console.log(finalPrice(10000, 0));
해답 보기

discountRate || 0.1은 0을 거짓으로 보고 0.1로 바꿔요. ??로 바꾸면 할인율을 주지 않았을 때(undefined)만 0.1을 써요.

const rate = discountRate ?? 0.1;

매개변수 기본값 function finalPrice(price, discountRate = 0.1)로 써도 같은 결과예요. 이건 함수 글에서 다뤄요.

05. 실전 포인트

  • 언제 쓰나요? 조건을 묶을 땐 && · ||를 괄호와 함께 써요. 서버 응답 · 설정 · 함수 인자에서 빠진 값을 채울 땐 ??를 기본으로 써요.
  • 대신 쓰는 것: || 기본값은 "빈 문자열도 없는 것으로 치고 싶을 때"처럼 의도가 분명할 때만 써요. 함수 인자의 기본값은 매개변수 기본값(= 0.1)이 더 읽기 쉬워요. 깊은 속성을 꺼낼 땐 옵셔널 체이닝 ?.(4장)과 함께 써요.
  • 흔한 실수: count || 1로 0을 1로 바꾸는 것, &&로 함수를 부르는 줄이 늘어나 읽기 어려워지는 것, ??와 ||를 괄호 없이 섞어 문법 오류가 나는 것이에요.

정리

  • &&는 둘 다, ||는 하나라도, !는 뒤집기예요. 섞을 땐 괄호로 순서를 밝혀요.
  • || · &&는 답이 정해지면 멈추고, 그때 본 값을 그대로 돌려줘요.
  • 기본값은 ??로 채워요. null · undefined일 때만 바꾸고 0 · '' · false는 지켜요.
  • x ??= 값은 비어 있을 때만 값을 넣어요.
SIMPLE · 기술스택 / JavaScript — 2장 기본