자식 테마로 화면 하나를 고치려 할 때 처음 부딪히는 질문은 언제나 같습니다. 이 화면은 지금 어느 파일이 그리고 있는가. 여기에 추측으로 답하면 아무도 읽지 않는 파일을 만들어 놓고 “왜 안 바뀌지” 를 반복하게 됩니다. 워드프레스는 이것을 규칙으로 정해 두었고, 그 규칙은 확인할 수 있습니다.
계층은 마법이 아니라 후보 목록입니다
워드프레스는 들어온 주소를 해석해 화면의 종류를 먼저 정합니다. 단일 글인가, 고정 페이지인가, 카테고리 아카이브인가, 검색 결과인가. 종류가 정해지면 구체적인 이름부터 일반적인 이름 순서로 후보 파일 목록을 만들고, 그중 실제로 존재하는 첫 번째 파일에서 멈춥니다.
목록의 맨 아래는 언제나 index.php 입니다. 그래서 테마는 index.php 하나만 있어도 동작하고, 파일을 더 만드는 것은 더 좁은 화면에만 적용되는 예외를 추가하는 일입니다. 이 순서를 이해하면 “어디에 파일을 만들어야 하나” 가 저절로 풀립니다 — 바꾸고 싶은 범위만큼만 좁은 이름을 고르면 됩니다.
자식 테마의 위치도 같은 규칙 안에 있습니다. 후보 이름이 같다면 자식 테마의 파일이 언제나 부모보다 먼저 잡힙니다. 부모의 single.php 를 자식으로 복사해 두면 그 순간부터 화면은 자식 파일이 그리고, 부모 파일은 손대지 않은 채로 남습니다. 자식 테마의 존재 이유가 정확히 이것입니다.
추측하지 말고 경로를 찍습니다
어떤 파일이 선택됐는지는 한 줄로 확인됩니다. template_include 는 최종 결정이 난 직후에 실행되는 필터라, 여기서 값을 찍으면 지금 이 화면이 실제로 쓰는 파일의 절대 경로가 나옵니다.
<?php
add_filter( 'template_include', function ( $template ) {
if ( current_user_can( 'manage_options' ) ) {
error_log( '[template] ' . $template );
}
return $template;
}, PHP_INT_MAX );
우선순위를 크게 잡은 데에는 이유가 있습니다. 플러그인이 뒤에서 템플릿을 바꿔치기하는 경우가 있어서, 가장 마지막 값을 봐야 실제로 그려지는 파일을 알 수 있습니다. 권한 조건을 붙인 것은 이 코드가 실수로 운영에 남더라도 방문자 요청마다 로그를 쌓지 않게 하기 위해서입니다.
더 가벼운 방법도 있습니다. body_class() 가 붙여 주는 클래스에는 화면의 종류가 그대로 담겨 있어서, 브라우저에서 body 태그만 봐도 single · archive · category-seo 같은 힌트가 나옵니다. 종류를 알면 후보 목록도 알 수 있습니다.
자주 어긋나는 세 지점
첫째, 고정 페이지에 페이지 템플릿이 지정돼 있으면 그것이 이깁니다. page-{슬러그}.php 를 만들었는데 반영되지 않는다면, 편집 화면의 템플릿 선택이 다른 파일을 가리키고 있는 경우가 대부분입니다. 계층보다 명시적 지정이 우선한다는 뜻입니다.
둘째, is_home() 과 is_front_page() 는 다릅니다. 최신 글 목록을 첫 화면으로 두면 둘이 같은 화면을 가리키지만, 첫 화면에 고정 페이지를 지정하는 순간 갈라집니다. 글 목록은 home.php 가, 첫 화면은 front-page.php 가 담당합니다. 이 둘을 혼동하면 “홈만 수정이 안 되는” 상태가 됩니다.
셋째, 커스텀 포스트 타입과 택소노미는 자기 이름이 붙은 파일을 먼저 찾습니다. archive-{타입}.php · single-{타입}.php · taxonomy-{택소노미}.php 가 그것입니다. 이 파일이 없으면 일반 아카이브로 떨어지므로, 화면이 “왜 다른 목록과 똑같이 생겼지” 라면 파일 이름부터 확인합니다.
테마 구조를 넓게 다루는 글은 테마 · 플러그인 아카이브에 모여 있고, 이미 운영 중인 사이트의 테마 구조를 정리하고 싶다면 최적화 지원 사업에 구조 점검이 포함돼 있습니다.
다음 회차
고칠 파일을 찾았으니 이제 스타일을 붙일 차례입니다. 그런데 자식 테마에서 가장 흔한 좌절이 바로 여기서 나옵니다 — “CSS 가 안 먹는다”. 다음 회차는 그 원인인 로드 순서이고, 결론을 미리 말하면 !important 는 답이 아닙니다.