본문 바로가기
카테고리 없음

TypeScript 26강: 타입 가드와 사용자 정의 타입 가드 활용법

by mystory55776 2025. 5. 26.

타입 가드(Type Guard)란 무엇인가?

타입스크립트의 타입 가드(Type Guard)는 코드 실행 중 변수의 타입을 판별하여 특정 타입임을 좁히는 방식입니다. 유니온 타입이나 any 타입을 사용할 때, 올바른 타입에 따라 안전하게 접근할 수 있도록 돕습니다. 조건문 안에서 사용되며, 타입 안전성을 강화하는 핵심 기능입니다.

function process(value: string | number) {
  if (typeof value === "string") {
    console.log(value.toUpperCase());
  } else {
    console.log(value.toFixed(2));
  }
}

위 함수는 typeof 연산자를 사용해 타입을 확인하고, 타입에 따라 적절한 메서드를 호출합니다.

내장 타입 가드 종류

TypeScript는 몇 가지 기본적인 타입 가드 방법을 제공합니다:

  • typeof: string, number, boolean, symbol, bigint, function 등
  • instanceof: 클래스 기반 객체의 인스턴스를 판별
  • in 연산자: 객체에 특정 속성이 존재하는지 확인
function isDate(value: any): boolean {
  return value instanceof Date;
}
function hasName(obj: any): boolean {
  return "name" in obj;
}

이러한 기본 가드는 자주 사용되는 타입에 대해 안전하게 타입을 좁히는 데 유용합니다.

사용자 정의 타입 가드 (User-defined Type Guard)

사용자 정의 타입 가드는 특정 조건을 만족할 경우, 개발자가 직접 타입을 좁힐 수 있도록 만드는 함수입니다. 반환 타입에 value is Type 형태를 사용합니다.

type Dog = { kind: "dog"; bark: () => void };
type Cat = { kind: "cat"; meow: () => void };
type Pet = Dog | Cat;

function isDog(pet: Pet): pet is Dog {
  return pet.kind === "dog";
}

function handlePet(pet: Pet) {
  if (isDog(pet)) {
    pet.bark();
  } else {
    pet.meow();
  }
}

이처럼 커스텀 타입 가드를 사용하면 유니온 타입에서 안전하게 분기 처리할 수 있습니다.

in 연산자를 활용한 타입 가드

in 연산자는 객체의 특정 속성 유무를 검사해 타입을 좁힐 수 있습니다.

type Admin = { name: string; accessLevel: number };
type Guest = { name: string };

function isAdmin(user: Admin | Guest): user is Admin {
  return "accessLevel" in user;
}

accessLevel 속성의 존재 여부로 타입을 판별하여, Admin 타입임을 안전하게 확인할 수 있습니다.

instanceof를 활용한 클래스 타입 가드

클래스 인스턴스를 판별할 경우에는 instanceof 연산자를 사용합니다.

class Car {
  drive() {
    console.log("Driving...");
  }
}

class Boat {
  sail() {
    console.log("Sailing...");
  }
}

function isCar(vehicle: Car | Boat): vehicle is Car {
  return vehicle instanceof Car;
}

function move(vehicle: Car | Boat) {
  if (isCar(vehicle)) {
    vehicle.drive();
  } else {
    vehicle.sail();
  }
}

이 방식은 클래스를 기준으로 타입을 판별할 수 있어, 객체지향 구조에 적합합니다.

복잡한 유니온 타입 처리 예제

유니온 타입이 많아질수록 타입 가드의 중요성이 커집니다. 예를 들어 다양한 알림 타입을 처리하는 구조를 보면 다음과 같습니다.

type Email = { type: "email"; subject: string };
type SMS = { type: "sms"; phone: string };
type Push = { type: "push"; title: string };

type Notification = Email | SMS | Push;

function handleNotification(notif: Notification) {
  switch (notif.type) {
    case "email":
      console.log(`Email: ${notif.subject}`);
      break;
    case "sms":
      console.log(`SMS to: ${notif.phone}`);
      break;
    case "push":
      console.log(`Push title: ${notif.title}`);
      break;
  }
}

이 방식은 디스크리미네이티드 유니온(discriminated union)이라 불리며, 각 타입에 고유 식별자 필드를 포함해 타입을 명확히 구분합니다.

사용자 정의 타입 가드의 장점

  • 복잡한 타입 판별 로직을 함수로 추출 가능
  • 가독성과 재사용성 향상
  • 코드 내 안전성 강화 및 런타임 오류 방지
  • TypeScript의 타입 시스템을 적극적으로 활용 가능

주의할 점

타입 가드 구현 시 다음과 같은 점을 유의해야 합니다:

  • 타입이 불완전한 경우 anyunknown을 사용하기보다 명확한 검사 수행
  • 객체 속성 검사 시 존재 여부만 판단하지 말고 타입까지 확인
  • 타입 가드를 너무 남용하면 코드 복잡도가 높아질 수 있음

결론: 타입 안전성과 가독성을 동시에 높이는 타입 가드

TypeScript 타입 가드는 코드의 타입 안전성을 유지하면서 유연하고 복잡한 로직을 구현할 수 있는 강력한 도구입니다. 특히 유니온 타입, 클래스 인스턴스, 복합 객체를 다룰 때 효과적입니다.

사용자 정의 타입 가드는 TypeScript의 정적 분석 기능을 극대화하며, 실무에서 데이터의 안정성과 예측 가능성을 보장하는 데 매우 유용합니다. 타입 가드를 전략적으로 활용하면 코드의 품질이 한층 향상됩니다.