연재의 마지막 회차입니다. 서버 시간을 재고, 쿼리를 나누고, 캐시를 계층별로 쌓았습니다. 남은 것은 브라우저가 내려받아 실행하는 부분이고, 이쪽은 성격이 조금 다릅니다 — 한 번의 실수가 아니라 누적으로 무거워집니다.
새 기능이 스크립트 하나를 더할 때마다 그 결정은 각각 합리적입니다. 문제는 총합이고, 총합을 보는 사람이 없으면 아무도 잘못하지 않은 채로 페이지가 무거워집니다. 예산은 그 총합에 이름을 붙이는 장치입니다.
무엇에 상한을 두나
구체적인 숫자는 사이트마다 다릅니다. 중요한 것은 값이 얼마인가가 아니라 값이 정해져 있는가입니다. 정하지 않으면 “조금 늘었네” 가 무한히 반복됩니다.
측정은 첫 화면 기준으로 합니다. 스크롤해야 나오는 이미지까지 합산하면 숫자가 커지기만 하고 판단이 어려워집니다. 그리고 앞 회차들과 같은 규칙 — 같은 URL, 같은 조건, 3회 중앙값입니다.
워드프레스 특유의 누수 — 전역 자산
워드프레스에서 예산이 새는 가장 흔한 경로는 모든 페이지에 자산을 등록하는 플러그인입니다. 문의 폼 스크립트가 블로그 글에도 실리고, 슬라이더 CSS 가 문의 페이지에도 실립니다. 각 플러그인은 자기 화면이 어디에 놓일지 모르므로 전역 등록이 안전한 기본값이고, 그 안전한 기본값이 모여 예산을 넘깁니다.
지금 무엇이 실리고 있는지부터 확인합니다.
add_action( 'wp_print_footer_scripts', function () {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
global $wp_scripts, $wp_styles;
error_log( 'JS : ' . implode( ', ', $wp_scripts->done ) );
error_log( 'CSS: ' . implode( ', ', $wp_styles->done ) );
}, 99 );
이 목록에서 이 페이지에 필요 없는 핸들을 골라 조건부로 내립니다. 무조건 지우지 않고 조건을 붙이는 것이 중요합니다 — 그 기능이 실제로 쓰이는 화면에서까지 사라지면 그것은 최적화가 아니라 고장입니다.
add_action( 'wp_enqueue_scripts', function () {
if ( is_singular( 'post' ) ) {
wp_dequeue_script( 'acme-contact-form' );
wp_dequeue_style( 'acme-contact-form' );
}
}, 100 );
예산은 지켜질 때만 예산입니다
문서에 적어 둔 상한은 한 달이면 잊힙니다. 재는 절차가 배포 경로 안에 있어야 살아남습니다. 자동화가 가능하면 빌드 단계에서 측정해 상한을 넘으면 실패시키고, 그렇지 않다면 릴리스 전 점검표의 한 줄로 둡니다.
그리고 예산의 요점은 거절이 아니라 교환입니다. 새 기능이 상한을 넘긴다면 “안 된다” 가 아니라 “무엇을 빼고 넣을 것인가” 를 묻습니다. 이 질문이 오가기 시작하면 자산 목록은 저절로 정리됩니다.
연재를 마치며
여덟 회차를 관통한 원칙은 하나였습니다. 재고 나서 고치고, 고친 뒤 다시 잰다. 구간을 나누고, 느린 쿼리와 중복 쿼리를 구분하고, 프라이밍으로 N+1 을 걷고, 캐시를 계층에 맞게 배치하고, 무효화 사건에 이름을 붙이고, 매 요청에 실리는 데이터를 감시하고, 마지막으로 자산의 총합에 상한을 두는 순서입니다.
워드프레스는 이 작업들을 전부 받아 주는 도구입니다. 느려지는 것은 도구의 한계가 아니라 어느 계층이 방치됐을 때이고, 그래서 대부분의 사이트에서 개선의 여지는 남아 있습니다.
직접 진행하기 어려운 범위 — 버전 업그레이드 · Redis 도입 · nginx 캐시 구성 · 보안 점검 — 을 한 건으로 맡기고 싶다면 최적화 지원 사업에 범위와 가격이 정리돼 있고, 우리가 어떤 순서로 재고 고치는지는 작업 과정에 절차 그대로 공개돼 있습니다.