-
PHP 에러 핸들링간단기법 2023. 5. 24. 18:19
PHP 에러 핸들링
PHP에는 error, fatal error, exception이 있다. 이름이 비슷한 error와 fatal error의 차이는 스크립트를 당장 중단하냐 마냐의 것이다. exception은 비교적 나중에 나온 것으로 다른 언어랑 비슷하게 예외를 던져서 try-catch로 핸들링할 수 있는 매커니즘이다. PHP는 버전이 올라감에 따라 error, fatal error의 상당 부분을 exception으로 다룰 수 있게 되었다. PHP의 에러 핸들링 방침은 exception으로 보인다.
Error
다음은 PHP의 에러를 다루는 함수이다.
set_error_handler('에러핸들러함수이름', E_ALL); trigger_error(msg, err_level);
set_error_handler 함수로 에러를 처리할 핸들러를 등록한다. trigger_error로 에러를 인위적으로 발생시킨다. set_error_handler에서 false를 반환하면, 사용자 정의 에러 핸들러가 호출된 다음 기본 에러 핸들러(default error handler)도 호출된다. 그 후, PHP 코드에서 에러가 발생했던 코드 다음 줄의 코드를 실행한다. 에러가 발생해도 스크립트의 진행은 중단되지 않고, 에러가 발생한 이후의 코드를 실행하는 것이다.
echo $undefined_variable; echo "이 코드는 에러 발생 이후의 코드 입니다";
예를 들어, 위와 같은 코드를 호출하면 정의되지 않은 변수에 접근했다는 에러가 발생한다. 그리고 나서 다음 줄의 코드가 실행된다. 실행 결과는 다음과 같다.
정의되지 않은 변수 $undefined_variable에 접근하여 에러가 발생했다. 하지만 심각한 에러가 아니므로 스크립트의 진행은 계속된다. 전체 코드의 호출 순서를 보면 다음과 같다.
PHP 인터프리터는 error가 발생해도 스크립트를 중단하지 않는다. fatal error와 다른 지점이다. set_error_handler가 다루는 에러 타입은 "E_USER..." 계통의 유저 수준 에러이다.
Fatal Error
Fatal error는 스크립트가 바로 중단되는 에러이다. 이 에러는 set_error_handler로 등록한 사용자 정의 에러 핸들러에서 다룰 수 없다. 그 대상은 다음과 같다.
E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING
error나 exception이 발생하면 사용자가 에러 리커버리를 시도할 수 있다. 이러한 시도를 권장하지 않을 수도 있겠지만, 시스템적으로 가능하다. fatal error는 이것이 불가능하고 그렇게 동작하지도 않는다. 이 에러가 발생했을 때, 핸들러를 등록하는 방법은 register_shutdown_function으로 등록하는 것이다.
이 함수는 사실 PHP스크립트가 종료되면 무조건 호출된다. 그래서 에러만 처리하는 함수는 아니다. 에러가 발생해서 종료했는지를 따져야 한다. 이때 사용되는 함수가 error_get_last()이다.
register_shutdown_function( "script_complete_handler" ); function script_complete_handler() { // 이 함수는 PHP스크립트가 정상 종료되도 호출된다. $error = error_get_last(); if($error !== NULL) { // key에는 type, file, line, message 등이 있다. } }
Exception
여러 언어들에서 사용되는 그 exception이다. try 문 안에서 예외가 발생하면 catch에서 잡는다. 만약, catch에서 잡을 수 없다면 버블링 되어 올라가고, 끝까지 올라가면 예외핸들러로 등록한 함수가 호출되어 예외를 처리한다.
set_exception_handler('예외핸들러'); try { 예외발생 } catch(Error $e) { $e->... }
Error와 Exception
모던 PHP에 와서는 Error와 Exception가 합쳐지는 방향으로 변했다. 에러를 예외로 만들어서 처리할 수 있게 된 것이다. 미리 정의되어 있는 ErrorException클래스를 이용하여 에러 핸들러 안에서 예외를 던지면 된다.
function errorHandler($errno, $errstr, $errfile, $errline) { throw new \ErrorException($errstr, $errno, 0, $errfile, $errline); }
위 코드를 기반으로 에러를 처리하면 다음과 같이 진행된다.
try { echo $invalid_variable; } catch (Exception $e) { echo "AAA"; } /* 위 코드는 정의되지 않은 변수를 사용하여 에러가 발생하는 코드이다. 발생한 에러는 등록했던 에러 핸들러에 전달된다. 그리고, 에러핸들러에서 다시 예외를 던져 catch 블록에서 예외를 받을 수 있다. 만약 try-catch가 없다면, 버블링되어 예외 핸들러에서 예외를 처리한다. */
이렇게 에러 핸들러 안에서 다시 예외를 던지면, 오류를 처리하는 코드를 예외 핸들러 안에서 통합하여 처리할 수 있게 된다.
Fatal error와 Exception
fatal error는 에러 핸들러로 받을 수 없었다. 그래서 register_shutdwon_function으로 등록하여 에러를 핸들링했었다. 이제는 Exception에서도 처리가 가능하다.
try{ new InvalidClass(); } catch(Error $e) { $e->... }
위 코드는 존재하지 않는 클래스를 생성하여 fatal error를 발생시킨다. 예외가 아니라 fatal error이지만, Error 클래스를 catch하여 예외처리 하는 방향으로 처리할 수 있다.
이러한 코드가 가능한 이유는 Exception과 Error 클래스 모두 Thorwable이라는 클래스를 상속받아 사용하기 때문이다.
참고
'간단기법' 카테고리의 다른 글
정규식 연습 (0) 2023.06.02 JS 문득 궁금한거 생길때 정리 (0) 2023.06.02 에러 핸들링, PHP, mysqli, prepared statement (0) 2023.05.17 PHP 문득 궁금한거 생길때 정리 (0) 2023.05.16 동적인 데이터를 처리하는 다양한 방법. (0) 2023.03.13