Skip to content

TypeScript에서의 에러 처리 (Error Handling)

TypeScript의 에러 처리는 기본적으로 JavaScript의 예외 처리 메커니즘을 기반으로 하지만, 타입 시스템을 통해 에러 객체를 더 안전하게 다룰 수 있는 방법을 제공한다.


1. 기본 구조 try / catch / finally

try 블록에서 에러가 발생하면, 제어 흐름이 catch 블록으로 이동하며, finally 블록은 에러 발생 여부와 상관없이 항상 실행된다.

ts
try {
  // 에러가 발생할 수 있는 코드
  fn(); // throw new Error("Something went wrong")
} catch (error) {
  console.error(error.message);
} finally {
  console.log("항상 실행됩니다.");
}
  • finally 블록은 리소스 정리, 상태 복구 등의 역할을 할 때 유용하다.

2. unknown 타입으로 안전하게 에러 처리하기

TypeScript는 catch 블록의 매개변수 타입을 자동으로 unknown으로 추론한다.
“에러가 어떤 타입인지 확실하지 않다”는 의미이며, 명시적인 타입 좁히기를 통해 안전하게 다뤄야 한다.

ts
function checkPositiveNumber(num: number) {
  if (num < 0) {
    throw new Error("number should be positive");
  }

  console.log(`${num} is a positive number`);
}

try {
  checkPositiveNumber(10);
  checkPositiveNumber(-10);
} catch (error: unknown) {
  // 타입 좁히기
  if (error instanceof Error) {
    console.error(error.message);
  }
}
  • instanceof를 이용해 런타임에서 에러 타입을 좁혀야 .message 등의 프로퍼티 접근이 타입 안전하게 보장된다.

3. 사용자 정의 에러 클래스 (Custom Error)

에러를 구체적으로 구분하거나, 도메인에 맞는 의미 있는 에러를 표현하려면 사용자 에러 클래스를 사용하는 것이 좋다.

ts
class CustomError extends Error {
  constructor(message: string) {
    super(message);
    this.name = "CustomError"; // 에러 이름 명시
  }
}

try {
  throw new CustomError("custom error..");
} catch (error) {
  if (error instanceof CustomError) {
    console.error(error.message); // custom error..
  }
}
  • this.name을 지정하면 스택 추적이나 로깅 시 에러 식별이 명확해진다.

TypeScript에서는 런타임 에러를 완전히 막을 수는 없지만,

타입 시스템을 통해 에러 객체의 형태를 명확히 정의함으로써 더 안정적이고 예측 가능한 예외 처리 로직을 작성할 수 있다.