Technote

테마 · 플러그인 실무

연재 자식 테마 개발 실무 8부 중 6부

템플릿 안의 보조 쿼리 — reset 을 빠뜨리면

관련 글 목록을 넣었더니 그 아래의 모든 것이 엉뚱한 글을 가리킵니다. 템플릿 문제처럼 보이지만 원인은 빠뜨린 한 줄입니다.

단일 글 화면에 관련 글 세 개를 붙였습니다. 그런데 그 아래의 댓글 영역이 다른 글의 것을 보여 주고, 브레드크럼도 엉뚱한 글을 가리킵니다. 템플릿을 아무리 들여다봐도 이상한 곳이 없습니다. 원인은 빠뜨린 한 줄입니다.

the_post() 는 전역 상태를 바꿉니다

워드프레스 템플릿 태그(the_title() · the_permalink() · get_the_ID())는 인자를 받지 않습니다. 대신 전역 $post 를 읽습니다. 그리고 루프 안의 the_post() 가 하는 일이 바로 그 전역을 다음 글로 바꿔 놓는 것입니다.

보조 쿼리를 돌리면 그 안의 the_post() 가 같은 전역을 건드립니다. 루프가 끝나면 전역은 보조 쿼리의 마지막 글을 가리킨 채로 남습니다. 원래 글로 돌려놓지 않으면 그 아래 코드는 전부 다른 글을 그리게 되고, 증상은 “템플릿이 이상하다” 로 나타납니다.

reset 이 없을 때 전역 $post 가 남는 자리 — 아래 코드는 원인을 알 수 없다

wp_reset_postdata() 는 전역을 메인 쿼리의 현재 글로 되돌립니다. 보조 루프 바로 뒤에 두고, 습관적으로 함께 씁니다.

<?php
$related = new WP_Query( [
    'post_type'      => 'post',
    'posts_per_page' => 3,
    'post__not_in'   => [ get_the_ID() ],
    'no_found_rows'  => true,
] );

if ( $related->have_posts() ) :
    while ( $related->have_posts() ) :
        $related->the_post();
        get_template_part( 'template-parts/card', 'note' );
    endwhile;

    wp_reset_postdata();   // ← 이 한 줄이 없으면 아래가 전부 틀어진다
endif;

query_posts() 는 쓰지 않습니다

비슷해 보이는 함수가 하나 더 있습니다. query_posts() 는 보조 쿼리를 만드는 것이 아니라 메인 쿼리 자체를 갈아 끼웁니다. 그 결과 페이지네이션이 깨지고, is_single() 같은 조건 태그가 거짓말을 시작하며, 쿼리가 한 번 더 실행됩니다.

목록에 나오는 글을 바꾸고 싶다면 답은 pre_get_posts 입니다. 메인 쿼리를 실행되기 전에 수정하므로 추가 쿼리가 없고 조건 태그도 그대로 유효합니다. 단 가드가 필수입니다.

<?php
add_action( 'pre_get_posts', function ( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;   // ← 없으면 관리자 목록과 보조 쿼리까지 바뀐다
    }

    if ( $query->is_category() ) {
        $query->set( 'posts_per_page', 12 );
    }
} );

보조 쿼리를 가볍게 만드는 인자들

보조 쿼리는 화면마다 실행되므로 기본값을 그대로 쓰면 필요 없는 일을 합니다. 상황에 맞게 꺼 두면 됩니다.

보조 쿼리 점검 — 위 네 줄은 켜고, 아래 세 줄은 피한다

posts_per_page => -1 이 특히 위험합니다. 개발 중에는 글이 열 개뿐이라 잘 돌아가고, 콘텐츠가 쌓인 뒤에 운영에서만 느려집니다. 상한을 정하면 최악의 경우가 예측 가능해집니다.

같은 이유로 루프 안에서 또 쿼리를 도는 구조를 피합니다. 글 하나마다 쿼리가 하나씩 늘어나므로, 목록이 길어질수록 비용이 곱으로 커집니다.

쿼리와 성능의 관계를 더 다루는 글은 성능 최적화 아카이브에 있고, 실제 사이트에서 어떤 순서로 원인을 좁혀 가는지는 작업 과정에 공개돼 있습니다.

다음 회차

여기까지가 만드는 이야기였습니다. 남은 두 회차는 덜어 내는 이야기입니다. 다음 회차는 부모 테마가 싣는 자산 중 우리가 쓰지 않는 것을 내리는 절차와, 그때 함께 넘어오는 책임을 다룹니다.

이 주제의 다른 글

노하우 목록으로

테마 · 플러그인 실무

옛 콘텐츠가 새 디자인에서 깨지는 세 가지 이유

본문에 박힌 인라인 스타일, 사라진 플러그인의 숏코드 잔여물, 하드코딩된 폭. 새 디자인 시스템이 존중받지 못하는 지점은 대개 이 셋입니다.

디자이너 3분 읽기

테마 · 플러그인 실무

편집 가능한 영역을 디자인 전에 정합니다

CMS 가 표현할 수 없는 디자인은 배포된 뒤에도 계속 협상 대상으로 남습니다. 어디까지 편집자가 바꿀 수 있는지를 먼저 정하면 그 협상 자체가 사라집니다.

디자이너 3분 읽기

테마 · 플러그인 입문

업데이트가 멈춘 플러그인을 판별하는 기준

마지막 업데이트 날짜 하나로는 방치를 판정할 수 없습니다. 판별 신호 다섯 개를 함께 보고, 대체 불가라면 격리 조건이라도 걸어야 합니다.

기획자 · 운영 · 관리자 2분 읽기

₩270,000 · 신청하기