JavaScript 공부를 하면서 난감한 경우 중 하나가 아래와 같이 물음표(?)와 같은 특수 문자를 마주할 때입니다.

const dogName = adventurer.dog?.name;

 

  구글에서 'JavaScript ?.' 으로 검색을 하면 'JavaScript' 검색 결과만 나와서 이걸 어떻게 찾아야 할지 막막했던 기억이 납니다. 그래서 이번에는 JavaScript에서 물음표를 사용하는 연산자들을 정리해 보도록 하겠습니다.


1. 조건 (삼항) 연산자 (A ? B : C) - Conditional (ternary) operator

(조건) ? (조건이 True일 때) : (조건이 False일 때)

 

  삼항 연산자는 if문과 비슷하지만, if문을 쓸 수 없을 때나 간결하게 쓸 수 있을 때 많이 사용합니다.

const age = 26;
const beverage = age >= 21 ? "Beer" : "Juice";
console.log(beverage); // "Beer"
// -----------------------------------------------------
const age = 17;
const beverage = age >= 21 ? "Beer" : "Juice";
console.log(beverage); // "Juice"

 

  위의 예시를 보면 age가 21 이상인 경우에는 'Beer', 그 외에는 'Juice'가 beverage의 값이 됩니다. age가 26일 경우에 console.log를 찍어보면 true일 때 값인 "Beer"가, age가 17일 경우에는 false일 때의 값인 "Juice"가 표시됩니다. 

if (age >= 21) {
  return "Beer";
} else {
  return "Juice";
}

 

  if문으로 표현하면 여러 줄이 필요하기 때문에, if문이 복잡하지 않은 경우에는 삼항 연산자를 쓰는 편이 깔끔해 보입니다.

<main>
  <h1>Welcome to this website</h1>
  {isLoggedIn ? (
    <button onClick={logout}>Log out</button>
  ) : (
    <button onClick={login}>Log in</button>
  )}
</main>

 

  다음으로는 if문을 사용할 수 없는 경우입니다. React에서 사용하는 경우가 많습니다. 위의 예시에서는 로그인이 되어있으면 isLoggedIn 값을 true로 설정해 줍니다. 따라서 로그인이 되어 있는 경우에는 로그아웃 버튼이 보이고, 로그아웃이 되어있는 경우에는 isLoggedIn 값이 false이므로, 로그인 버튼이 보이게 됩니다.

<button onClick={isPlaying ? onClickPause : onClickPlay}>
  {isPlaying ? "Pause" : "Play"}
</button>

 

  위의 예시에서도 동영상이 재생 중인 경우에는 isPlaying 값이 true로 설정되어 있습니다. 따라서 재생 중일 때는 버튼의 이름이 "Pause"가 되고 버튼을 클릭하면 동영상을 멈추는 onClickPause 함수가 실행됩니다. 반대로 동영상이 멈춰있는 경우에 isPlaying 값이 false가 되어서, 버튼 이름은 "Play"가 되고 버튼을 클릭하면  동영상을 재생해 주는 onClickPlay 함수가 실행됩니다. 

<main>
  <h2 style={{ display: "flex", gap: "6px" }}>
    Secret password
    <button onClick={() => setExpended(false)}>-</button>
    <button onClick={() => setExpended(true)}>+</button>
  </h2>
  {isExpended && (
    <p>
      password: <code>hunter2</code>
    </p>
  )}
</main>;

 

  참고로 AND(&&) 연산자 사용하면 연산자 앞의 값이 True일 때, 연산자 뒤의 값을 리턴해줍니다. + 버튼을 누르면 isExpended값이 true가 되면서 <p> 태그 안에 있는 password의 값이 보이게 됩니다.


2. 널 병합 연산자 (??) - Nullish coalescing operator

a ?? b // a 값이 null, undefined면 b를 반환함

 

  물음표 두 개(??)는 Nullish coalescing operator입니다. ?? 앞의 값이 null 값이거나 undefined면 뒤의 값을 반환해줍니다.

const firstName = null;
const lastName = undefined;
const nickName = "Violet";

alert(firstName ?? lastName ?? nickName ?? "Cheese"); // Violet

 

  firstName 값이 null이고, lastName 값은 undefined이므로, 뒤에 있는 nickname 값이 반환됩니다. 만약 nickName도 null이거나 undefined였다면, 뒤에 있는 "cheese" 값을 반환해 줄 것입니다.

1. Nullish coalescing operator 
  -> 첫 번째 정의된(defined) 값을 반환
  -> null, undefined 값만 취급한다.
2. OR(||) 연산자
  -> 첫 번째 truthy 값을 반환
  -> null, undefined 외에도 0 값을 falsy 값으로 취급한다.

 

  앞에서 AND(&&) 연산자가 사용된 경우를 봤다면, 이번에는 OR(||) 연산자가 사용된 경우를 보겠습니다. Nullish coalescing operator는 || 연산자와 유사하지만, 차이점이 존재합니다. 전자의 경우에는 첫 번째 정의된 값을 반환하고, null과 undefined 값만 취급합니다. 후자의 경우에는 첫 번째 truthy 값을 반환하고, null과 undefined 외에도 0 값을 falsy 값으로 취급합니다. 따라서, 숫자 0이 할당될 수 있는 변수를 사용할 때는 ||보다는 ??을 사용하는 것이 좋습니다.

let height = 0;

alert(height || 100); // 100
alert(height ?? 100); // 0

 

  height 값을 0으로 설정하고 || 연산자를 사용하는 경우에는, 0을 falsy 값으로 취급하므로 첫 번째 truthy 값인 100을 반환합니다. ?? 연산자를 사용하는 경우에는 0은 truthy 값이 되어 null이나 undefined 값이 아니게 됩니다. 따라서 첫 번째 정의된 값인 0을 반환해 줍니다. 위의 예시처럼 0이 의미가 있는 값이라면 ?? 연산자를 사용하는 것이 적합합니다. 


3. 옵셔널 체이닝 (?.) - Optional chaining

let user = {}; // 주소 정보가 없는 사용자

alert( user?.address?.street ); // undefined, 에러가 발생하지 않습니다.

// Nullish coalescing operator를 사용할 경우
alert( user && user.address && user.address.street ); // undefined, 에러가 발생하지 않습니다.

 

  Optional Chaining은 ?. 앞의 값이 "있다.", "없다."만을 평가합니다. 만약 ?. 앞의 값이 null이나 undefined인 경우에는 평가를 멈추고 undefined를 반환합니다. 에러는 발생시키지 않습니다. Nullish coalescing operator와 유사하지만, Optional Chaning을 사용하면 코드를 더 간결하게 작성할 수 있습니다. 위의 예시에서는 user는 존재하지만, user의 address 항목이 존재하지 않기 때문에 undefined를 반환할 것입니다.

const hashedPassword = await User.findOne({ userId }, "password")
  .lean()
  .then((user) => user?.password);

 

  제가 프로젝트 하면서 작성했던 코드입니다. findOne함수를 이용해 DB에서 userId가 일치하는 user의 password를 가져왔습니다.

{
  _id: new ObjectId('684e4ccc91757a381b66e7ad'),
  password: '$2b$10$sXCscjG5Wn6FKBEfn.lwF.NOVyAO/6EP5HDO.OBgn9GbXXCVzjIZS'
}

 

  만약 user가 존재한다면 위와 같이 _id와 password 필드를 가져올 것입니다. user가 존재하지 않는다면 user?.password는 undefined 값을 반환할 것입니다. 이 예시에는 user가 존재하므로, 객체의 password 값을 아래와 같이 반환합니다.

$2b$10$sXCscjG5Wn6FKBEfn.lwF.NOVyAO/6EP5HDO.OBgn9GbXXCVzjIZS

참고 문헌

1. Conditional (ternary) operator - MDN 문서

2. Nullish coalescing operator - MDN 문서

3. Nullish coalescing operator - JAVASCRIPT.INFO

4. Optional chaining - MDN 문서

5. Optional chaining - JAVASCRIPT.INFO

'코딩 공부 > JavaScript' 카테고리의 다른 글

[JavaScript] Number와 parseInt의 차이  (0) 2024.05.28

+ Recent posts