Technote

개발 워크플로우 실무

var_dump 없이 디버깅하기 — 로그와 도구를 쓰는 순서

화면에 값을 찍는 방식은 라이브 사이트에서 내부를 노출하고, AJAX · REST 응답을 깨뜨리며, 리다이렉트 구간에서는 아무것도 보여 주지 않습니다. 대신 쓸 세 가지 도구에는 순서가 있습니다.

var_dump() 는 배우기 쉽고 즉시 답을 줍니다. 그래서 손이 먼저 갑니다. 문제는 이 방식이 동작하는 경우가 생각보다 좁다는 점이고, 동작하지 않을 때 그 사실조차 조용하다는 점입니다.

화면에 찍는 방식이 무너지는 자리

첫째, 라이브 사이트에서는 방문자가 봅니다. 덤프에는 경로 · 테이블명 · 설정값 · 때로는 자격증명 조각까지 섞여 나오는데, 그것이 그대로 페이지에 렌더됩니다. 디버깅 흔적을 지우고 배포했다고 생각했는데 한 줄이 남아 있는 상황은 드물지 않습니다.

둘째, 응답이 HTML 이 아닌 곳에서는 응답을 깨뜨립니다. AJAX 핸들러나 REST 라우트에 덤프를 넣으면 JSON 앞에 잡문이 붙어 파싱이 실패하고, 화면에는 “알 수 없는 오류” 만 뜹니다. 원래 찾던 버그 위에 새 증상 하나를 얹은 셈입니다.

셋째, 리다이렉트 구간에서는 아예 보이지 않습니다. 폼 제출 처리처럼 값을 저장하고 곧바로 이동하는 코드에서는 출력이 화면에 닿기 전에 페이지가 바뀝니다. 아무것도 안 보이니 “이 코드가 안 도는구나” 로 오해하기 쉬운데, 도는 중입니다.

넷째, 헤더 전송 이후에는 경고를 만듭니다. 출력이 시작된 뒤 쿠키나 헤더를 세우려는 코드가 있으면 그때부터 다른 종류의 오류가 겹칩니다.

1단계 — 로그 파일에만 남깁니다

기본 도구는 워드프레스의 디버그 로그입니다. 핵심은 기록은 켜고 화면 출력은 끄는 조합입니다.

// wp-config.php
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );     // wp-content/debug.log 에 기록
define( 'WP_DEBUG_DISPLAY', false ); // 화면에는 절대 띄우지 않는다
@ini_set( 'display_errors', 0 );

세 번째 줄이 이 글의 요지입니다. WP_DEBUG 만 켜면 오류가 화면으로 나가므로, 로그를 켤 때는 항상 표시를 함께 끕니다. 로그 파일이 웹에서 열리지 않도록 접근 차단도 확인합니다 — 서버 설정에서 막거나, 로그 경로를 문서 루트 밖으로 옮깁니다.

그다음 error_log() 로 필요한 지점에 기록을 남깁니다. 두 가지 습관이 로그를 쓸모 있게 만듭니다. 태그를 붙이는 것과 맥락을 함께 적는 것입니다.

error_log( sprintf(
    '[acme][order] sync %s status=%s user=%d',
    $order_id,
    $status,
    get_current_user_id()
) );

// 배열 · 객체는 문자열로 만들어 넘긴다
error_log( '[acme][order] payload ' . wp_json_encode( $payload ) );

태그가 있으면 로그가 커져도 원하는 줄만 골라 볼 수 있고, 맥락(주문 번호 · 사용자 · 상태)이 있으면 재현 조건을 로그만 보고 알 수 있습니다. “여기 도착함” 만 적힌 로그는 그 순간에만 쓸모가 있습니다.

디버깅 도구의 순서 — 값이 궁금하면 로그, 흐름이 궁금하면 디버거

2단계 — 관찰 도구는 개발 환경에서만

값이 아니라 무엇이 얼마나 실행됐는가가 궁금할 때가 있습니다. 어떤 쿼리가 몇 번 돌았는지, 어떤 훅에 무엇이 붙어 있는지, 템플릿이 어느 파일에서 그려졌는지 같은 것들입니다. 이때는 관찰용 플러그인을 씁니다.

다만 이 도구들은 개발 · 스테이징 전용입니다. 쿼리와 훅 정보를 노출하고, 모든 요청에 관측 비용을 얹기 때문입니다. 프로덕션에 켜 둔 채 잊는 사고가 실제로 자주 일어나므로, 환경별 플러그인 활성화 목록을 나눠 두는 편이 안전합니다.

디버깅 환경 점검 — 아래 둘은 사고로 이어진 적이 있는 항목이다

3단계 — 값이 아니라 흐름이 문제일 때

로그를 아무리 찍어도 안 잡히는 종류의 버그가 있습니다. 어디를 지나갔는지가 문제인 경우입니다. 조건 분기가 예상과 다르게 갈리거나, 재귀나 필터 체인 중간에서 값이 바뀌거나, 어느 콜백이 먼저 도는지가 핵심일 때는 로그를 추가하는 속도보다 코드가 복잡해지는 속도가 빠릅니다.

이때가 단계 실행 디버거를 붙일 자리입니다. 중단점을 걸고 한 줄씩 진행하면서 호출 스택을 보면, 로그 수십 줄로 추측하던 것을 한 번에 확인합니다. 설정에 시간이 조금 들지만 그 시간은 대개 한 번의 어려운 버그에서 회수됩니다.

마지막으로 디버깅 코드를 남기지 않습니다. 임시 로그와 중단점용 변수는 원인을 찾은 뒤 반드시 걷어 냅니다. 커밋 전에 변경 파일을 한 번 훑어보는 습관, 또는 error_log 를 찾는 간단한 검사 하나를 CI 에 두는 것만으로 충분합니다.

프로덕션의 로그 설정과 배포 절차는 로컬에서 프로덕션까지 연재에서, 쿼리 수와 실행 시간을 다루는 관점은 워드프레스 성능 프로파일링 연재에서 이어집니다. 관련 글은 개발 워크플로우 아카이브에 모여 있고, 운영 중인 사이트의 로그 · 성능 · 보안 설정을 한 번에 정비하려면 최적화 지원 사업을 참고하세요.

이 주제의 다른 글

노하우 목록으로

개발 워크플로우 입문

대시보드를 열기 전에 질문을 먼저 정합니다

질문 없이 연 대시보드는 관찰을 만들고 결정을 만들지 않습니다. 화면을 열기 전에 한 문장을 적는 것만으로 회의의 성격이 달라집니다.

기획자 3분 읽기

개발 워크플로우 입문

“이 기능 넣어 주세요” 뒤에 있는 진짜 문제

요청은 이미 한 번 번역된 결과입니다. 요청한 사람은 자기 필요를 해법으로 바꾼 뒤에 말을 꺼냈고, 그 해법을 그대로 만들면 대개 틀린 문제를 풀게 됩니다.

기획자 4분 읽기

개발 워크플로우 입문

개편 범위는 하지 않을 것부터 적습니다

끝나는 조건이 없는 개편은 끝나지 않습니다. "이왕 하는 김에" 가 일정을 무너뜨리는 방식이고, 그것을 막는 문서는 할 일 목록이 아니라 하지 않을 일 목록입니다.

기획자 4분 읽기

₩270,000 · 신청하기