the_content 는 본문 HTML 을 바꿀 수 있는 필터입니다. 그런데 이 필터에는 워드프레스 코어가 이미 여러 콜백을 걸어 두었고, 그 콜백들이 마크업을 실제로 변형합니다. 우리가 어느 번호에 서느냐에 따라 손에 들어오는 문자열이 달라집니다.
기본으로 걸려 있는 콜백들
정리하면 이렇습니다. 우선순위 1에 걸면 post_content 에 저장된 거의 원본을 봅니다 — 블록은 아직 HTML 주석이고, 숏코드는 문자열 그대로이며, <p> 는 하나도 없습니다. 우선순위 12 이후에 걸면 문단이 감싸지고 숏코드가 실행되고 이미지 속성까지 채워진 완성 HTML 을 봅니다.
“내 정규식이 아무것도 못 잡는다” 의 정체
가장 흔한 실패가 여기입니다. 첫 문단 뒤에 무언가를 끼우려고 </p> 를 찾는 정규식을 우선순위 1에 걸면, 그 시점에는 <p> 가 존재하지 않으므로 영원히 매칭되지 않습니다. 반대로 숏코드 문자열을 치환하려고 우선순위 12에 걸면 이미 실행된 뒤라 찾을 것이 없습니다.
규칙은 단순합니다. 원본 마크업을 다루려면 앞쪽, 완성된 HTML 을 다루려면 뒤쪽에 섭니다. 그리고 앞쪽에 HTML 을 끼워 넣으면 그것도 wpautop 의 처리 대상이 되므로, 블록 요소를 넣었다가 엉뚱한 </p> 가 따라붙는 일이 생깁니다.
// 원본을 보는 자리 — 블록 주석과 숏코드가 그대로 있다
add_filter( 'the_content', 'wper_early', 1 );
// 완성된 HTML 을 보는 자리 — <p> 가 붙어 있고 이미지 속성도 채워졌다
add_filter( 'the_content', 'wper_late', 12 );
이 저장소의 아티클 상세가 뒤쪽을 쓰는 예입니다. 본문의 h2 를 파싱해 앵커를 달고 그 파싱으로 목차를 그리는데, 이 작업은 완성된 HTML 을 대상으로 해야 블록으로 쓰인 제목과 클래식 마크업이 같은 모양으로 잡힙니다. 그래서 우선순위 12입니다.
이 필터는 본문 화면에서만 도는 것이 아닙니다
또 하나 놓치기 쉬운 점이 있습니다. the_content 는 발췌를 만들 때도 실행됩니다. 워드프레스가 수동 발췌 없는 글의 발췌를 만들 때 본문을 이 필터에 통과시키기 때문입니다.
그래서 본문 끝에 CTA 를 붙이는 필터를 아무 판정 없이 걸면, 목록 화면 카드의 발췌마다 CTA 문구가 섞여 나옵니다. 피드에서도 마찬가지입니다. 판정을 붙입니다.
function wper_late( $html ) {
if ( ! is_singular() || ! in_the_loop() || ! is_main_query() ) {
return $html; // 발췌 · 피드 · 보조 쿼리에서는 손대지 않는다
}
return $html . '<aside class="wper-cta">…</aside>';
}
in_the_loop() 까지 보는 이유는, 같은 단독 화면 안에서도 관련 글 같은 보조 루프가 본문을 다시 통과시킬 수 있기 때문입니다. 세 판정이 함께 있어야 “지금 그리는 것이 이 글의 본문” 이라고 말할 수 있습니다.
본문 렌더링과 성능의 관계는 개발 워크플로우 아카이브에서 더 다루고, 본문 처리와 캐시 계층을 함께 정리하는 작업은 최적화 지원 사업에 포함돼 있습니다.
다음 회차
덮어쓰는 대신 아예 내리는 편이 맞을 때가 있습니다. 다음 회차는 남의 훅을 내리는 방법과, 그것이 조용히 실패하는 세 가지 이유입니다.