IMG-LOGO
공지사항 :

PHP 디버깅

lmkfox - 2025-08-13 06:40:58 33 Views 0 Comment

1 디버깅의 기본 원칙

  • 먼저 재현 가능한 최소 재현 사례(small reproducible example)를 만든다.

  • 에러/로그 → 재현 → 원인 추적 → 수정 → 재검증 순으로 접근한다.

  • 개발 환경과 운영 환경의 설정(특히 display_errors)은 절대 같게 두지 않는다.

2 에러 표시 · 로깅 기본 설정 (개발/운영 차이)

개발 환경(일시적):

// 코드 최상단(개발 중에만)
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

운영 환경(권장):

display_errors = Off
log_errors = On
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
error_log = /var/log/php_errors.log

  • 운영에서는 에러를 화면에 그대로 노출하면 안 된다. log_errors로 파일/중앙 로깅으로 전송한다.

  • PHP-FPM/Apache/Nginx 각각의 php.ini 또는 pool 설정을 확인해야 한다 (CLI와 FPM은 다른 ini를 읽음).

3 런타임 에러·예외 핸들링

예외와 에러를 중앙에서 잡아 로깅/통보하도록 설정하면 문제 원인 파악이 쉬워짐.

set_error_handler(function($severity, $message, $file, $line) {
    error_log("[ERROR] $message in $file:$line");
    /* 개발시에만 예외로 전환하고 싶다면 throw new ErrorException(...) */
});

set_exception_handler(function(Throwable $e){
    error_log("[UNCAUGHT EXCEPTION] {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}");
    error_log($e->getTraceAsString());
});

register_shutdown_function(function() {
    $err = error_get_last();
    if ($err && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        error_log("[FATAL] {$err['message']} in {$err['file']}:{$err['line']}");
    }
});

  • register_shutdown_function() + error_get_last()로 치명적 오류를 잡을 수 있다.

4 빠른 출력 디버깅 도구

  • var_dump(), print_r(), var_export() — 구조 확인용.

  • HTML 출력용: <pre><?php var_dump($x); ?></pre>

  • error_log() — 웹 요청 중에서도 서버 로그로 보낸다.

  • debug_backtrace() / debug_print_backtrace() — 호출 스택 확인.

  • memory_get_usage(), memory_get_peak_usage() — 메모리 사용량 체크.

5 Xdebug (가장 강력한 도구)

Xdebug는 중단점/스텝디버깅, 프로파일링, 트레이스, 향상된 var_dump 출력 등 많이 제공.

  • Xdebug 3 기준(php.ini 예):

zend_extension=xdebug.so
xdebug.mode = develop,debug,profile,trace
xdebug.start_with_request = trigger    ; yes|no|trigger 중 선택 (trigger 권장)
xdebug.client_host = 127.0.0.1
xdebug.client_port = 9003
xdebug.output_dir = /tmp/xdebug
xdebug.log = /tmp/xdebug.log

  • xdebug.start_with_request=trigger이면 GET/POST/COOKIE에 XDEBUG_TRIGGER(또는 브라우저 확장)를 넣었을 때만 디버그 시작.

  • Docker 환경에서는 client_host를 host.docker.internal 또는 호스트 IP로 설정해야 함.

  • CLI에서 바로 디버깅하려면:

php -dxdebug.mode=debug -dxdebug.start_with_request=yes script.php

  • IDE 연동: PhpStorm, VSCode(php-debug 확장) 등에서 포트 9003을 리슨. 조건부/함수별 중단점, 변수 관찰(watch) 등 사용.

6 스텝 디버깅(브레이크포인트, 워치)

  • IDE에서 중단점 설정 → 요청 실행 → 코드가 중단된 지점에서 변수, 콜스택, 표현식 평가 가능.

  • 조건부 중단점(예: $i > 1000)으로 많은 반복 중 악성 케이스만 잡아낼 수 있음.

  • “Step Into / Over / Out”으로 문제 지점까지 좁혀간다.

7 프로파일링 & 성능 분석

  • Xdebug 프로파일러(xdebug.mode=profile)로 Cachegrind 파일 생성 → KCacheGrind, QCacheGrind, Webgrind로 분석.

  • 타사 툴: Blackfire, Tideways, New Relic, XHGui 등도 권장(상용/개발용에 따라 선택).

  • 자주 사용하는 측정 함수:

$start = microtime(true);
// 코드
$elapsed = microtime(true) - $start;
error_log("Elapsed: {$elapsed}s");

  • 느린 쿼리 로깅(데이터베이스 측) + PHP 프로파일링으로 병목 지점 확인.

8 phpdbg (내장 디버거)

  • PHP에 포함된 대화형 디버거. CLI용:

phpdbg -qrr script.php
# 내부에서는 break, run, step, next, print 등 사용

  • 서버-사이드의 간단한 트레이싱이나 CLI 스크립트 디버깅에 유용.

9 정적 분석과 테스트

  • PHPStan, Psalm: 타입·문법 기반 정적 분석(오류 사전 제거).

  • PHPCS: 코딩 스타일 검사.

  • PHPUnit: 단위 테스트 + 코드 커버리지(Xdebug와 연동).

  • CI(eg. GitHub Actions, GitLab CI)에 정적 분석과 유닛테스트를 포함시키면 회귀 방지에 도움.

10 데이터베이스 디버깅

  • PDO 사용 시 항상 예외 모드:

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  • Prepared statement 파라미터 값도 로깅(수동)하여 실제 실행되는 쿼리 확인.

  • MySQL slow query log, general query log를 켜서 DB 쪽 병목 확인.

  • 트랜잭션을 활용해 문제 재현(롤백 가능).

11 HTTP / API 디버깅 도구

  • 브라우저 개발자도구 (Network 탭): 요청/응답 헤더, 페이로드 확인.

  • curl / Postman / Insomnia로 요청 재현.

  • 요청에 X-Request-Id 같은 correlation id를 붙여 로그에서 요청 추적.

  • AJAX 요청 문제는 콘솔과 네트워크 로그로 먼저 확인.

12 운영 환경에서의 안전한 디버깅 관행

  • 운영에서는 display_errors = Off, 에러는 로그로 전송.

  • 민감 정보(패스워드, 토큰, 개인정보)는 절대로 로그에 그대로 남기지 않음(마스킹).

  • 요청 식별자(Trace ID)를 생성해 로그를 연관(분산 로깅, ELK/Graylog).

  • 에러 모니터링 서비스(Sentry 등) 연동으로 예외 알림 자동화.

13 빈번한 문제와 체크리스트

  • 브레이크포인트가 작동하지 않을 때:

    • Xdebug가 실제로 로드됐는가? (php -i | grep xdebug)

    • FPM과 CLI의 php.ini가 다른 경우가 많음(각각 확인).

    • xdebug.start_with_request 설정 확인 (yes|trigger).

    • 방화벽/포트(9003) 문제 혹은 Docker 네트워크 문제.

    • xdebug.output_dir 권한 문제로 프로파일 파일이 안 생기는 경우.

  • 코드 변경이 서버에 반영되지 않음:

    • OPcache 활성화 시 opcache.validate_timestamps=1 또는 php-fpm 재시작 필요.

  • 에러 메시지가 불충분:

    • PDO::ERRMODE_EXCEPTION, set_exception_handler()로 스택트레이스 확보.

14 유용한 커맨드·스니펫 모음

  • 문법 체크(린트):

php -l file.php

  • CLI에서 빠르게 Xdebug로 실행:

php -dxdebug.mode=debug -dxdebug.start_with_request=yes script.php

  • Git으로 회귀 찾기:

git bisect start
git bisect bad HEAD
git bisect good v1.2.3
# 반복 테스트로 원인 커밋 찾기

15 권장 워크플로우(요약)

  1. 로컬에서 error_reporting = E_ALL, display_errors = On으로 재현.

  2. Xdebug로 브레이크포인트/스텝 통해 원인 추적.

  3. 로그(서버/DB)로 추가 정보 수집.

  4. 수정 후 유닛테스트/통합테스트 실행.

  5. 운영 반영 시 display_errors = Off, 로그·모니터링 확인.


댓글