(또) 옵셔널 체이닝, ?.

강연주·2025년 3월 21일

📚 TIL

목록 보기
147/186

isPublic: isPublicRef.current?.checked와
isPublic: isPublicRef.current?.checked || false의 차이점은
undefined 값을 처리하는 방식에 있다.

TypeScript에서 옵셔널 체이닝 연산자(?.)를 사용하면,
결과는 접근하려는 값이나 체인의 일부가 null 또는 undefined인 경우
undefined가 될 수 있다. 따라서 isPublicRef.current?.checked는 다음과 같은 결과가 될 수 있다.

  • true (체크박스가 체크된 경우)
  • false (체크박스가 체크되지 않은 경우)
  • undefined (isPublicRef.current가 null이나 undefined인 경우)

내가 정의한 meetupType에 따르면 isPublic이 boolean | undefined가 아닌 boolean이어야 하므로 || false 없이는 타입 오류가 발생한다.

|| false를 추가함으로써, 결과가 undefined(또는 falsy 값)일 때
기본값으로 false를 제공한다. 이렇게 하면 isPublic이 항상 불리언 값을 가지게 되며, 이는 Meetup 타입이 기대하는 것과 일치한다.


옵셔널 체이닝 (?.) 기본 개념

옵셔널 체이닝 연산자 ?.는 참조하는 객체가 null이나 undefined일 때
에러를 발생시키지 않고 대신 undefined를 반환한다.

🧢 객체 속성 접근

🖥️ typescript

const user = {
  name: "홍길동",
  address: {
    city: "서울"
  }
};

// 일반적인 접근법 (user가 null이면 에러 발생)
const city1 = user.address.city; 

// 옵셔널 체이닝 사용 (안전한 접근)
const city2 = user?.address?.city; // user나 address가 null/undefined면 undefined 반환

🧢 배열 요소 접근

🖥️ typescript

const data = null;
const firstItem = data?.[0]; // undefined 반환, 에러 없음

🧢 함수 호출

🖥️ typescript
const obj = {
  method: function() {
    return "결과";
  }
};

// 함수가 존재하는지 확인 후 호출
const result = obj.method?.(); // "결과"

// 메서드가 없는 경우
const obj2 = {};
const result2 = obj2.method?.(); // undefined, 에러 없음

🎒 옵셔널 체이닝과 논리 연산자 조합

옵셔널 체이닝은 종종 기본값을 제공하는 || 연산자와 함께 사용된다.

🖥️ typescript

// user.preferences가 null/undefined면 기본값 사용

const theme = user?.preferences?.theme || "기본 테마";

위와 isPublic을 다루는 내 코드의 패턴이 유사하다.

🖥️ typescript
isPublic: isPublicRef.current?.checked || false

isPublicRef.current가 null이나 undefined면, isPublicRef.current?.checked는 undefined 반환
|| 연산자가 undefined || false를 평가하여 최종적으로 false 반환


옵셔널 체이닝의 장점

  • 코드의 안전성 향상 : 참조 오류로 인한 런타임 에러 방지
  • 코드 간결화 : 여러 중첩된 if 문을 대체 가능
  • 가독성 개선 : 방어적인 코드를 더 간결하게 작성

기억할 점

옵셔널 체이닝으로 접근한 결과가 항상 undefined 또는 원래 값이기 때문에, 타입 시스템에서는 undefined | 원래타입으로 처리된다.
이 때문에 ||나 ?? 연산자와 함께 사용하여 기본값을 제공하는 패턴이 자주 사용된다.

  • 타입 확장 : 옵셔널 체이닝으로 접근한 결과의 타입은 항상 원래 타입에 undefined가 추가된다. 이것은 TypeScript의 타입 시스템이 해당 값이 존재하지 않을 가능성을 반영하는 뜻이다.

  • 타입 불일치 가능성 : 이렇게 확장된 타입(undefined | 원래타입)은 원래 타입만 기대하는 함수나 변수에 할당할 때 타입 오류를 발생시킬 수 있다.

🖥️ typescript


function requireBoolean(value: boolean) { ... }
requireBoolean(obj?.isActive); // 오류: 'undefined | boolean' 타입은 'boolean' 타입에 할당할 수 없습니다

  • 불완전한 타입 가드 : 옵셔널 체이닝만으로는 값이 실제로 존재하는지 확인하기에 충분하지 않을 수 있다.
🖥️ typescript

if (user?.profile) {
  // 여기서도 user.profile은 여전히 undefined일 수 있는 타입으로 간주된다
}

➡️ 이러한 이유들 때문에 옵셔널 체이닝을 사용할 때는 종종 || 또는 ?? 연산자와 함께 사용하여 기본값을 제공하는 패턴이 권장된다. 이렇게 하면 타입이 더 예측 가능해지고 타입 오류를 방지할 수 있다.

🖥️ typescript

// undefined가 될 수 있는 값에 기본값 제공
const isActive: boolean = obj?.isActive ?? false; // 항상 
boolean 타입
profile
아무튼, 개발자

0개의 댓글