pre_get_posts 는 쿼리가 실행되기 직전에 그 조건을 고칠 수 있게 해 주는 훅입니다. 아카이브의 글 개수를 바꾸거나, 특정 조건의 글만 남기거나, 정렬을 바꾸는 일이 전부 여기서 됩니다. 템플릿에서 새 쿼리를 만들지 않고 메인 쿼리 자체를 고친다는 점이 핵심입니다 — 페이지네이션과 조건 태그가 그대로 살아 있기 때문입니다.
이 훅은 모든 쿼리에 대해 돕니다
가장 먼저 알아야 할 것은 이 훅이 메인 쿼리만이 아니라 모든 WP_Query 인스턴스에 대해 돈다는 사실입니다. 메뉴를 그릴 때도, 위젯이 최근 글을 뽑을 때도, 관리자 글 목록 화면을 그릴 때도 돕니다.
그래서 콜백의 첫 두 줄이 사실상 정해져 있습니다.
add_action( 'pre_get_posts', 'wper_book_archive' );
function wper_book_archive( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( ! $query->is_post_type_archive( 'book' ) ) {
return;
}
$query->set( 'posts_per_page', 12 );
$query->set( 'orderby', 'menu_order' );
}
판정에 전역 조건 태그가 아니라 $query-> 메서드를 쓰는 이유가 있습니다. 전역 태그는 언제나 메인 쿼리를 가리키므로, 지금 손보고 있는 그 쿼리가 아닌 다른 것에 대해 답할 수 있습니다.
덮어쓰지 말고 읽어서 더합니다
meta_query 와 tax_query 를 그냥 set() 하면 이미 들어 있던 조건이 통째로 사라집니다. 다른 플러그인이 넣었을 수도 있고, 워드프레스가 그 화면을 위해 넣었을 수도 있습니다. 읽어서 더하는 형태로 씁니다.
$meta = (array) $query->get( 'meta_query' );
$meta[] = [
'key' => '_in_stock',
'value' => '1',
'compare' => '=',
];
$query->set( 'meta_query', $meta );
남의 조건이 우리 화면을 비울 수도 있습니다
반대 방향의 사고도 있습니다. 이 저장소에서 커스텀 택소노미 아카이브 열 곳이 전부 0건으로 서 있던 적이 있습니다. 리라이트도 쿼리 대상도 정상이었는데, 실행된 SQL 에 우리가 넣지 않은 _thumbnail_id 조인이 들어 있었습니다.
부모 테마가 포트폴리오 목록에서 대표 이미지 없는 항목을 숨기려고 pre_get_posts 에 넣은 조건이었고, 그 판정이 $query->is_tax( $portfolio_taxonomies ) 였습니다. 이 사이트에는 포트폴리오 포스트 타입이 없어 그 배열이 빈 배열이 되는데, is_tax() 는 첫 인자가 비어 있으면 “택소노미를 가리지 않는다” 로 읽어 무조건 참을 돌려줍니다. 결과적으로 커스텀 택소노미 아카이브 전부가 포트폴리오 쿼리가 됐고, 우리 글은 썸네일을 코드로 그려 대표 이미지가 0장이므로 목록이 비었습니다.
화면은 200이고 제목도 필터도 멀쩡히 그려지고 빈 상태 문구까지 정상 출력됐습니다 — “아직 글이 없구나” 로 읽히지 고장으로 보이지 않습니다. 배운 것 두 가지입니다. 빈 배열과 빈 문자열을 같게 다루지 말 것, 그리고 목록이 이상하면 조건이 아니라 실제로 실행된 쿼리를 볼 것.
쿼리 디버깅 도구와 그 운영상의 주의는 개발 워크플로우 아카이브에 있고, 이런 지점을 포함한 전면 점검은 최적화 지원 사업에서 다룹니다.
다음 회차
다음 회차는 the_content 입니다. 같은 필터인데 우선순위 1에서 보는 것과 12에서 보는 것이 완전히 다른 문자열이고, “내 정규식이 아무것도 못 잡는다” 의 대부분이 여기서 나옵니다.