[JS] Optional Chaining (?.)

J.yeonยท2025๋…„ 6์›” 16์ผ

์šฐ์—ฐํžˆ ๋ณด๊ฒŒ๋œ ?. / ?? .. ์ง„์งœ ๋ฌผ์Œํ‘œ ๊ทธ ์žก์ฑ„๐Ÿค”


์ •์˜

์˜ต์…”๋„ ์ฒด์ด๋‹(Optional Chaining) ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ(JavaScript)์—์„œ ์ค‘์ฒฉ๋œ ๊ฐ์ฒด์—์„œ ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•  ๋•Œ, ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ undefined ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•˜๋Š” ์—ฐ์‚ฐ์ž์ด๋‹ค.


โš™ ๊ธฐ๋ณธ ๋ฌธ๋ฒ•

ํ˜•ํƒœ์˜๋ฏธ
obj?.propobj๊ฐ€ ์กด์žฌํ•˜๋ฉด prop ๋ฐ˜ํ™˜
obj?.method()obj๊ฐ€ ์กด์žฌํ•˜๋ฉด method() ์‹คํ–‰
arr?.[index]๋ฐฐ์—ด์ด ์กด์žฌํ•˜๋ฉด ํ•ด๋‹น ์ธ๋ฑ์Šค ์ ‘๊ทผ


ex)

const user = {
  name: "Aki",
  address: {
    city: "Seoul",
    zip: "12345"
  }
};

console.log(user.address.city); // โœ… "Seoul"
console.log(user.contact.email); // โŒ ์—๋Ÿฌ

์œ„ ์ด๋ฏธ์ง€์ฒ˜๋Ÿผ user.contact.email ์—†๋Š” ๊ฐ์ฒด๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๊ฒฝ์šฐ, ์—๋Ÿฌ๊ฐ€ ๋œจ๊ฒŒ ๋œ๋‹ค.

์˜ˆ์‹œ๊ฐ€ ๋‹จ์ˆœํ•ด์„œ ๊ทธ๋ ‡์ง€ ๊ฐ์ฒด๊ฐ€ ์ค‘์ฒฉ๋˜์–ด์žˆ๊ณ  ์†Œ์Šค๋„ ๊ธธ๋‹ค๋ฉด ์ด์ฒ˜๋Ÿผ ๊ฐ„ํ˜น ์—†๋Š” ๊ฐ์ฒด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์‹ค์ˆ˜๋ฅผ ํ•  ๋•Œ๊ฐ€ ์žˆ..์—ˆ๋‹ค.


์ด๋Ÿด ๋•Œ Optional Chaining์„ ์‚ฌ์šฉํ•˜๋ฉด ์—๋Ÿฌ๋Œ€์‹  undefined ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.


console.log(user.address?.city); // โœ… "Seoul"
console.log(user.contact?.email); // โœ… undefined (์—๋Ÿฌ โŒ)

โœจ์ด์ฒ˜๋Ÿผ Optional Chaining์€ ์กด์žฌ ์—ฌ๋ถ€๋ฅผ ๋จผ์ € ํ™•์ธํ•œ ํ›„ ์†์„ฑ์ด๋‚˜ ๋ฉ”์„œ๋“œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๊ธฐ๋•Œ๋ฌธ์— ์—๋Ÿฌ๋ฅผ ๋ง‰๊ณ  ์ฝ”๋“œ๊ฐ€ ๋” ์•ˆ์ „ํ•˜๊ฒŒ ์‹คํ–‰๋˜๊ฒŒ ๋„์™€์ค€๋‹ค.






๐Ÿ‘€ ์ถ”๊ฐ€๋กœ... Null ๋ณ‘ํ•ฉ ์—ฐ์‚ฐ์ž ๊ฐ™์ด ์‚ฌ์šฉํ•˜๊ธฐ!

Null ๋ณ‘ํ•ฉ ์—ฐ์‚ฐ์ž (??)

๊ฐ’์ด null ๋˜๋Š” undefined์ธ ๊ฒฝ์šฐ์—๋งŒ ๋Œ€์ฒด๊ฐ’(default) ์„ ์ œ๊ณตํ•˜๋Š” ์—ฐ์‚ฐ์ž์ด๋‹ค.


const result = value ?? defaultValue;
  • value๊ฐ€ null ๋˜๋Š” undefined๋ผ๋ฉด defaultValue๋ฅผ ๋ฐ˜ํ™˜

  • ๊ทธ ์™ธ์˜ falsy ๊ฐ’(0, '', false ๋“ฑ)์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•จ

falsy ๊ฐ’์ด๋ž€? Boolean ๋ฌธ๋งฅ์—์„œ false ๋กœ ํ‰๊ฐ€๋˜๋Š” ๊ฐ’


ex)

const name = null;
const displayName = name ?? "Anonymous";
console.log(displayName); // "Anonymous"
// โœจname๊ฐ’์ด null์ด๊ธฐ๋•Œ๋ฌธ์— ๋Œ€์ฒด๊ฐ’ "Anonymous" ์ œ๊ณต

const age = 0;
const userAge = age ?? 18;
console.log(userAge); // โœ… 0 (0์€ falsy์ง€๋งŒ null/undefined๊ฐ€ ์•„๋‹˜)
// โœจnull/undefined๊ฐ€ ์•„๋‹ˆ๊ธฐ๋•Œ๋ฌธ์— falsy๊ฐ’ ๊ทธ๋Œ€๋กœ ์œ ์ง€

const comment = '';
const userComment = comment ?? 'No comment';
console.log(userComment); // โœ… '' (๋นˆ ๋ฌธ์ž์—ด ์œ ์ง€)
// โœจnull/undefined๊ฐ€ ์•„๋‹ˆ๊ธฐ๋•Œ๋ฌธ์— ๋นˆ ๋ฌธ์ž์—ด ๊ทธ๋Œ€๋กœ ์œ ์ง€


Optional Chaining + Null ๋ณ‘ํ•ฉ ์—ฐ์‚ฐ์ž

๋‘ ์กฐํ•ฉ์„ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ํŽธ

ex)

const user = {
  profile: {
    nickname: null
  }
};

const nickname = user.profile?.nickname ?? "Guest";
console.log(nickname); // "Guest"
// โœจuser.profile?.nickname์ด null์ด๋ผ์„œ "Guest" ๋ฐ˜ํ™˜

์œ„์— ์ฒซ ์˜ˆ์‹œ๋กœ ์ ์šฉํ•ด๋ณด๋ฉด๐Ÿ‘‡

const user = {
  name: "Aki",
  address: {
    city: "Seoul",
    zip: "12345"
  }
};

console.log(user.address?.city ?? "city none"); // โœ… "Seoul"
console.log(user.contact?.email ?? "email none"); // โœ… "email none"
// โœจuser.contact?.email ๊ฐ’์ด undefined ์ด๊ธฐ๋•Œ๋ฌธ์— "email none" ๋ฐ˜ํ™˜


๐Ÿ“์š”์•ฝ

๊ตฌ๋ฌธ์„ค๋ช…
?.์•ˆ์ „ํ•˜๊ฒŒ ์ ‘๊ทผ (์—๋Ÿฌ ๋ฐฉ์ง€)
??๊ฐ’์ด ์—†์„ ๋•Œ ๊ธฐ๋ณธ๊ฐ’ ์„ค์ • (null, undefined์ผ ๋•Œ๋งŒ ์ž‘๋™)
profile
๋‚˜ํ˜ผ์ž๋งŒ ์œˆ๋„์šฐUP๐Ÿ’ป

0๊ฐœ์˜ ๋Œ“๊ธ€