타입스크립트, 오리의 걸음으로 배우는 타입 내로잉과 타입 가드

Taesoo Kim·2025년 5월 27일
2
post-thumbnail

타입스크립트로 복잡한 객체 지향 설계를 하다 보면, "거대 클래스"를 주입받아 다양한 하위 타입을 런타임에 구분해야 하는 상황이 자주 발생합니다. 이럴 때 안전하게 타입을 좁혀서(내로잉) 원하는 메서드나 속성을 사용하는 방법이 바로 덕타이핑(duck typing)사용자 정의 타입 가드(user-defined type guard)입니다.


시나리오: 거대 클래스를 주입받는 상황

class MegaService {
  doSomething(): void { /* ... */ }
  doAnotherThing(): void { /* ... */ }
  isSpecial(): boolean { return false; }
}

class SpecialService extends MegaService {
  override isSpecial(): boolean { return true; }
  doSpecialThing(): void { /* ... */ }
}

class Consumer {
  constructor(private service: MegaService) {}

  process() {
    // 여기서 타입 내로잉이 필요!
  }
}

Consumer는 MegaService 타입을 주입받지만, 실제로는 SpecialService 등 다양한 하위 타입이 들어올 수 있습니다. 이때 타입 내로잉이 필요합니다.


덕타이핑(duck typing)이란?

덕타이핑은 "오리처럼 걷고, 오리처럼 꽥꽥거린다면, 그건 오리다"라는 말에서 유래한 개념입니다. 즉, 객체의 실제 타입이 아니라, 특정 속성이나 메서드가 존재하는지로 타입을 판별하는 방식입니다.

예시: 덕타이핑으로 타입 내로잉

process() {
  if ('doSpecialThing' in this.service) {
    // doSpecialThing 메서드가 있으면 SpecialService로 간주
    (this.service as SpecialService).doSpecialThing();
  } else {
    this.service.doSomething();
  }
}

이 방식은 상속 구조가 아니거나, 외부 라이브러리 등에서 타입 정보가 불명확할 때 유용합니다. 하지만 오타나 속성 이름 충돌 등으로 인한 런타임 오류 가능성이 있으니 주의해야 합니다.


사용자 정의 타입 가드(user-defined type guard)

타입스크립트에서는 사용자 정의 타입 가드를 통해 타입 내로잉을 더욱 안전하게 할 수 있습니다.

문법

function isSpecialService(svc: MegaService): svc is SpecialService {
  return 'doSpecialThing' in svc;
}
  • 반환 타입에 svc is SpecialService를 명시하면,
  • 이 함수가 true를 반환하는 경우, 타입스크립트는 svc를 SpecialService로 내로잉합니다.

사용 예시

process() {
  if (isSpecialService(this.service)) {
    this.service.doSpecialThing(); // 타입 에러 없이 사용 가능!
  } else {
    this.service.doSomething();
  }
}

이렇게 하면 코드의 가독성과 안전성이 높아지고, 여러 곳에서 재사용도 가능합니다.


언제 어떤 방법을 써야 할까?

  • 상속 구조라면: instanceof와 사용자 정의 타입 가드를 조합하는 것이 가장 안전합니다.
  • 인터페이스 기반/속성 기반이라면: 덕타이핑(속성 체크) + 타입 가드 함수로 감싸서 사용하면 좋습니다.
  • 항상 타입 가드를 만들어서 코드의 의도를 명확히 하고, 재사용성을 높이는 것이 유지보수에 유리합니다.

결론

  • 덕타이핑은 객체의 실제 타입이 아니라, 속성/메서드 존재 여부로 타입을 판별하는 방식입니다.
  • 사용자 정의 타입 가드는 타입스크립트에서 타입 내로잉을 안전하게 할 수 있는 강력한 기능입니다.
  • 두 방법을 적절히 조합하면, 거대 클래스를 주입받는 상황에서도 안전하고 유연하게 타입을 다룰 수 있습니다.

실제 프로젝트에서 타입 내로잉이 필요한 상황이 있다면, 위의 패턴을 적극적으로 활용해 보세요!

profile
뭔 생각을 해. 그냥 하는 거지 뭐

0개의 댓글