[PHP] Exception이 왜 모든 예외를 잡지(catch) 못하는 거지?

,

아래처럼 이메일을 보내는 로직을 try … catch로 감싸 놨습니다. 이메일 발송에 실패해도 결제 자체는 진행될 수 있도록 말이죠.

그런데 생각지 못하게 catch가 안 되는 에러가 발생합니다. $email_addressstring이 들어와야 하는데 null이 들어왔다고 말이죠.

try {
    Mail::to($email_address)
        ->send(new MailNotice($purchase));
} catch (\Exception $e) {
    Log::error(
        $e->getMessage() . PHP_EOL
        . $e->getTraceAsString()
        . PHP_EOL . $purchase->toJson()
    );
}

무슨 일일까요?

결론부터 말하면 타입 불일치 에러는 Exception으로 잡을 수 없고, Throwable로 잡아야 합니다. 아래처럼 고치면 이제 작동하는데요.

try {
    Mail::to($email_address)
        ->send(new MailNotice($purchase));
} catch (\Throwable $e) {
    Log::error(
        $e->getMessage() . PHP_EOL
        . $e->getTraceAsString()
        . PHP_EOL . $purchase->toJson()
    );
}

이게 뭘까요?

Exception보다 나중에 도입된 Error 클래스

PHP에서 Exception은 PHP 5부터 도입됐습니다. 그 전에 PHP에는 에러만 있었고 예외는 없었죠.

그런데 예외가 도입되고 나서도 PHP에는 예외로 처리하지 못하는 에러나 경고들이 있었습니다. 예컨대 없는 함수를 호출하면 PHP는 Fatal Error를 표시하면서 멈췄습니다. 예외 처리를 통해 시스템이 다운되지 않게 하면서 우아하게 처리할 수 있는 방법이 없었죠.

PHP 7부터는 이런 종류의 에러들이 Error라는 객체를 던지게 변경됐습니다. 이제 개발자들은 모든 예외상황을 우아하게 다룰 수 있게 된 것이죠.

이 Error 클래스와 이전의 Exception을 통합하는 개념이 바로 Throwable입니다.

결론

Throwable의 등장으로 개발자들은 더 많은 제어를 할 수 있게 됐습니다. 이전 같으면 속절없이 당해야 했던 Fatal Error까지도 처리할 수 있게 됐으니까요.

또한 그래서 모든 예외 상황을 잡아서 처리하려면(catch) Exception이 아니라 Throwable을 사용해야 하는 것입니다.

참고

카테고리

,

대표글

댓글 남기기