티스토리 뷰

 

현대 웹 애플리케이션은 수많은 외부 API와 복잡한 데이터 구조 위에서 동작합니다. 프런트엔드 개발자라면 누구나 한 번쯤 Uncaught TypeError: Cannot read property '...' of undefined라는 공포의 에러 메시지를 마주해 보셨을 겁니다.

데이터가 항상 존재할 것이라는 낙관적인 가정은 곧 서비스의 장애로 이어집니다. 과거에는 이를 방지하기 위해 장황한 if 문이나 논리 연산자(&&)를 중첩해서 사용했지만, **ES2020(ES11)**에서 등장한 **Optional Chaining(?.)**과 **Nullish Coalescing(??)**은 코드의 가독성을 비약적으로 높이면서도 안전한 방어 코드를 작성할 수 있게 해주었습니다.


1. Deep Dive: 왜 이 기술이 필요한가?

존재하지 않는 데이터에 대한 접근

자바스크립트에서 null이나 undefined에 마침표(.)를 찍어 속성에 접근하려고 하면 스크립트는 즉시 중단됩니다. 이를 방지하기 위한 전통적인 방식은 다음과 같았습니다.

JavaScript
 
// 고전적인 방어 코드 (AND 연산자 활용)
const zipCode = user && user.address && user.address.zipCode;

데이터의 깊이(Depth)가 깊어질수록 코드는 우측으로 길어지고, 읽기 힘들어집니다. Optional Chaining은 이 과정을 "단락 평가(Short-circuiting)" 방식으로 해결합니다.

0과 빈 문자열('')의 딜레마

기존에 기본값(Default value)을 설정할 때 자주 쓰던 OR 연산자(||)는 치명적인 약점이 있습니다. 0, "", false 같은 값들을 모두 Falsy로 취급하여 무시해버린다는 점입니다.

  • 사용자의 점수가 0점일 때, score || 100을 실행하면 결과는 100이 됩니다.
  • Nullish Coalescing은 오직 null과 undefined만 걸러냄으로써 개발자의 의도를 정확히 반영합니다.

비유로 이해하기: 안전한 배송 시스템

  • Optional Chaining(?.): 택배 기사님이 아파트 동·호수를 확인하는데, 만약 'A동' 자체가 없다면 더 이상 집 호수를 찾지 않고 즉시 배송 불가(undefined) 판정을 내리고 복귀하는 것과 같습니다.
  • Nullish Coalescing(??): 고객이 옵션을 선택하지 않았을 때만 기본 사은품을 넣는 것입니다. 고객이 '0번 옵션'을 선택했다면, 그것도 선택한 것이니 사은품을 주지 않고 0번을 그대로 배송합니다.

2. Creative Hands-on: 실전 이커머스 대시보드 로직

단순한 예제 대신, 다양한 상태를 가진 주문 데이터에서 통계 값을 추출하는 실무형 코드를 살펴보겠습니다.

JavaScript
 
/**
 * 이커머스 주문 데이터를 처리하여 요약 정보를 반환하는 함수
 */
function getOrderSummary(orderData) {
  // 1. Optional Chaining으로 중첩된 객체 안전하게 접근
  // 2. Nullish Coalescing으로 수치 데이터 기본값 설정 (0점이나 빈 문자열 보존)
  
  const customerName = orderData?.customer?.profile?.name ?? "비회원";
  const shippingFee = orderData?.logistics?.fee ?? 0; // 배송비가 0원일 때 ||를 쓰면 0을 무시함
  const couponDiscount = orderData?.payment?.discount?.amount ?? 0;
  
  // 메서드 호출 시에도 안전하게 사용 가능
  const formattedDate = orderData?.getTimestamp?.() ?? "날짜 정보 없음";

  const items = orderData?.items ?? [];
  const itemCount = items.length;

  return {
    customerName,
    shippingFee,
    couponDiscount,
    itemCount,
    formattedDate
  };
}

// 실전 데이터 케이스
const rawOrder = {
  customer: { profile: { name: "Aiden" } },
  logistics: { fee: 0 }, // 무료 배송 케이스
  payment: { discount: { amount: null } },
  // getTimestamp는 누락됨
};

const summary = getOrderSummary(rawOrder);

console.log(`고객명: ${summary.customerName}`);      // Aiden
console.log(`배송비: ${summary.shippingFee}원`);      // 0 (||를 썼다면 undefined나 0이 아닌 다른 값이 나올 위험)
console.log(`할인액: ${summary.couponDiscount}원`);   // 0
console.log(`상품 수: ${summary.itemCount}개`);       // 0
console.log(`주문일: ${summary.formattedDate}`);     // 날짜 정보 없음

🛠 Troubleshooting Tip

orderData?.customer?.profile.name 처럼 중간까지만 체이닝을 걸고 마지막에 실수로 마침표를 찍으면, profile이 없을 때 여전히 에러가 발생합니다. **"불확실한 모든 단계에 ?.를 붙이되, 반드시 존재해야 하는 값에는 .을 써서 의도를 명확히 하는 것"**이 디버깅에 유리합니다.


3. Trade-offs: 고려해야 할 사항

강력한 도구지만 남용은 금물입니다.

  • 남용 시의 위험성 (Silent Fail): 모든 곳에 ?.를 붙이면 데이터 구조가 잘못되어도 에러가 발생하지 않고 조용히 undefined를 반환합니다. 이는 나중에 원인을 알 수 없는 버그(Logic Error)를 추적하기 어렵게 만듭니다.
  • 할당 연산자 사용 불가: obj?.prop = 'value'와 같이 왼쪽에 위치하여 값을 할당하는 용도로는 사용할 수 없습니다.
  • 브라우저 호환성: 대부분의 현대 브라우저는 지원하지만, 구형 환경이나 IE를 지원해야 한다면 Babel과 같은 트랜스파일러 설정이 필수적입니다.

결론 및 제언

Optional Chaining과 Nullish Coalescing은 단순히 코드를 짧게 만드는 '문법적 설탕(Syntactic Sugar)' 이상의 가치를 지닙니다. 이는 개발자가 데이터의 불확실성을 인정하고, 그 예외 케이스를 어떻게 처리할지 선언적으로 기술하게 해줍니다.

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함