Menu

PHP 에러 표시: display_errors와 E_ALL 설정

PHP 에러를 모두 표시하려면 스크립트 맨 위에 ini_set('display_errors', '1');과 error_reporting(E_ALL);을 넣거나, php.ini에서 display_errors = On과 error_reporting = E_ALL로 설정하세요. 운영 환경에서는 에러를 표시하지 말고 로그로 남기세요.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

PHP 에러를 표시하려면 스크립트 맨 위에 다음 줄을 넣으세요: ini_set('display_errors', '1');와 error_reporting(E_ALL);. 첫 번째는 PHP가 에러 메시지를 출력하게 하고, 두 번째는 경고와 deprecation을 포함한 모든 종류의 에러를 보고하게 합니다.

<?php
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

이렇게 해 두면 설정된 적 없는 변수를 읽는 것 같은 실수가 조용히 실패하는 대신 파일과 줄 번호가 담긴 메시지를 출력합니다.

Warning: Undefined variable $total in /home/index.php on line 7

인자 없이 호출한 error_reporting()은 현재 설정을 숫자로 반환합니다. Run을 눌러 레벨을 설정하고 그것을 다시 이름으로 풀어 보세요.

각 에러 유형은 비트 하나이므로 E_ALL & ~E_DEPRECATED는 "deprecation을 제외한 전부"라는 뜻입니다. 첫 줄을 error_reporting(E_ERROR | E_WARNING);로 바꾸고 다시 실행해 보세요.

php.ini에서 에러 표시

스크립트 안의 설정은 스크립트가 실행되기 시작한 뒤에만 적용됩니다. 구문 에러를 포함해 모든 스크립트에서 에러를 표시하려면 php.ini를 수정하세요(php --ini로 찾을 수 있습니다).

; Development
display_errors = On
display_startup_errors = On
error_reporting = E_ALL

수정한 뒤에는 Apache나 PHP-FPM을 재시작하세요. php -S 내장 서버와 명령줄은 시작할 때마다 파일을 읽습니다. php.ini에 접근할 수 없는 공유 호스팅에서는 mod_php를 쓰는 Apache가 .htaccess 줄도 받아들입니다.

php_flag display_errors on
php_value error_reporting -1

-1은 모든 비트를 설정하므로 E_ALL과 같습니다.

에러 레벨

상수발생 원인스크립트 중단
E_ERROR메모리 부족 같은 치명적 런타임 에러예
E_PARSE파일의 구문 에러예
E_WARNING정의되지 않은 변수나 배열 키, include의 파일 누락아니요
E_NOTICE사소한 문제(PHP 8에서는 거의 남아 있지 않음)아니요
E_DEPRECATED향후 PHP 버전에서 거부될 코드아니요
E_USER_*trigger_error()로 직접 발생시킨 에러E_USER_ERROR만
E_ALL여기 없는 코어 및 컴파일 에러를 포함한 모든 레벨

PHP 8.0은 예전 경고 다수를 예외로 바꾸었습니다. /로 0으로 나누기와 내장 함수에 잘못된 타입 전달은 이제 Error 하위 클래스를 던지며, 이는 PHP 7부터 정의되지 않은 함수 호출이 그랬던 것과 같습니다. 세 가지 모두 잡을 수 있습니다.

예외는 try와 catch에서 다룹니다. 경고, notice, deprecation은 여전히 여기서 설명하는 에러 보고 시스템을 거칩니다.

에러를 표시하지 말고 로그로 남기기

운영 중인 사이트에서는 방문자가 에러 메시지를 보면 안 됩니다. 경로, SQL, 코드가 드러나기 때문입니다. 대신 로그 파일에 기록하세요.

; Production
display_errors = Off
log_errors = On
error_log = /var/log/php/app-errors.log
error_reporting = E_ALL

운영 환경에서도 error_reporting = E_ALL을 유지하세요. 레벨을 낮춘다고 에러가 사라지지 않고, 에러 소식을 듣지 못하게 될 뿐입니다. 직접 남기는 메시지도 error_log()로 같은 로그에 보낼 수 있습니다.

<?php
error_log("Payment failed for order 1042");

테스트하는 동안 파일을 지켜보세요: tail -f /var/log/php/app-errors.log.

set_error_handler로 경고를 예외로 바꾸기

set_error_handler는 경고, notice, deprecation에 대한 PHP 기본 처리를 내 함수로 대체합니다. 흔한 패턴은 이들을 모두 ErrorException으로 바꾸는 것으로, 그러면 빠뜨린 배열 키도 다른 예외처럼 코드를 멈추고 잡을 수 있게 됩니다.

핸들러는 첫 번째 인자로 에러 레벨을 받으므로 레벨별로 다르게 처리할 수 있습니다. 이 핸들러는 deprecation은 로그만 남기고 나머지는 모두 예외로 바꿉니다.

치명적 에러와 구문 에러는 그 뒤에 스크립트가 계속될 수 없으므로 핸들러에 도달하지 않습니다. 이를 기록하려면 error_get_last()를 읽는 종료 함수를 등록하세요.

error_get_last로 마지막 에러 읽기

어떤 함수는 false를 반환하고 이유는 경고로만 알립니다. 예를 들어 없는 파일에 대한 file_get_contents입니다. error_get_last()는 그 경고를 배열로 반환하므로, 직접 만든 메시지를 보여 주고 싶을 때 유용합니다.

호출 앞의 @ 연산자는 그 표현식 하나의 메시지를 억제합니다. 여기처럼 바로 뒤에서 결과를 확인할 때만 아껴서 쓰세요. 그냥 붙인 @는 버그를 숨길 뿐입니다.

흔한 실수: 에러 표시를 켰는데 페이지가 여전히 빈 화면

ini_set('display_errors', '1')을 추가했는데도 흰 페이지가 보인다면 아마 구문 에러일 것입니다. PHP는 첫 줄을 실행하기 전에 파일 전체를 파싱하므로, ;나 } 하나가 빠지면 ini_set이 실행되기 전에 모든 것이 멈춥니다. 항상 메시지를 출력하는 터미널에서 파일을 검사하세요.

php -l index.php
Errors parsing index.php
PHP Parse error:  syntax error, unexpected token "," in index.php on line 2

줄 번호는 PHP가 포기한 지점을 가리키며, 실제 실수의 다음 줄인 경우가 많습니다. 고친 뒤 No syntax errors detected가 나올 때까지 php -l을 다시 실행하고, 페이지를 새로 고치세요.

자주 묻는 질문

PHP에서 모든 에러를 표시하려면 어떻게 하나요?

스크립트 맨 위에 ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); error_reporting(E_ALL);를 추가하거나, php.ini에서 display_errors = On과 error_reporting = E_ALL로 설정하고 웹 서버나 PHP-FPM을 재시작하세요.

PHP 페이지가 하얀 빈 화면으로 나오는 이유는?

display_errors가 꺼진 상태에서 치명적 에러가 스크립트를 멈춰서 아무것도 출력되지 않은 것입니다. 에러 표시를 켜거나 에러 로그를 읽어(예: error_log가 가리키는 파일에 tail -f) 메시지와 줄 번호를 확인하세요.

ini_set('display_errors', 1)을 써도 구문 에러가 안 보이는 이유는?

구문 에러는 파일의 어떤 줄도 실행되기 전에 PHP를 멈추므로 ini_set 호출이 실행되지 않습니다. php.ini에서 display_errors를 설정하거나, ini_set을 작은 파일에 넣고 그 파일에서 문제의 파일을 include하세요.

운영 환경에서 display_errors를 켜야 하나요?

아니요. 에러 메시지는 방문자에게 파일 경로와 코드 세부 정보를 노출합니다. 운영 환경에서는 display_errors = Off, log_errors = On, 그리고 error_log 경로를 쓰고, 문제가 계속 기록되도록 error_reporting = E_ALL은 유지하세요.

error_reporting(0)은 무엇을 하나요?

스크립트의 나머지 부분에서 모든 에러 유형의 보고를 끄므로, 경고는 물론 치명적 에러도 메시지를 내지 않습니다. 문제를 고치는 것이 아니라 숨기는 것이므로, 에러를 묵살하기보다 로그로 남기는 편이 좋습니다.

Coddy 프로그래밍 언어 일러스트

Coddy로 코딩 배우기

시작하기