WordPress 성능 최적화를 위한 고급 가이드
게시 됨: 2022-03-11오늘날 WordPress는 인터넷의 30% 이상을 차지합니다. 사용하기 쉽고 믿을 수 없을 정도로 인기가 높으며 곧 출시될 예정입니다.
그러나 WordPress는 느릴 수 있습니다. 어떻게 최적화합니까?
WordPress를 조정하고 최적화하는 방법에 대한 많은 기사가 있습니다. 사실, WordPress 자체는 WordPress 최적화에 대한 강력한 가이드를 제공합니다.
대부분의 경우 이러한 기사와 튜토리얼은 캐시 플러그인 사용, CDN(콘텐츠 전송 네트워크)과의 통합, 요청 최소화와 같은 매우 기본적이면서도 유용한 개념을 다룹니다. 이러한 팁은 매우 효과적이고 필요하기까지 하지만 결국 근본적인 문제를 해결하지 못합니다. 대부분의 느린 WordPress 사이트는 잘못되거나 비효율적인 코드의 결과입니다.
따라서 이 기사는 주로 개발자와 WordPress 개발 회사에 많은 WordPress 성능 문제의 근본적인 원인을 해결하는 데 도움이 될 수 있는 몇 가지 지침을 제공하는 것을 목표로 합니다.
WordPress는 개발자가 종종 간과하는 많은 성능 지향 기능을 제공합니다. 이러한 기능을 활용하지 않는 코드는 게시물 가져오기와 같은 가장 간단한 작업의 속도를 늦출 수 있습니다. 이 문서에서는 느린 WordPress 성능 뒤에 숨겨진 몇 가지 근본적인 문제를 해결하는 네 가지 가능한 솔루션에 대해 자세히 설명합니다.
게시물 가져오기
WordPress는 데이터베이스에서 모든 종류의 게시물을 가져올 수 있는 가능성을 제공합니다. 이렇게 하는 세 가지 기본 방법이 있습니다.
query_posts()
함수 사용: 이는 매우 직접적인 접근 방식이지만, 문제는 메인 쿼리를 오버라이드(override)하여 불편을 초래할 수 있다는 점입니다. 예를 들어, 게시물을 가져온 후(예:footer.php
내부) 어느 시점에서 어떤 종류의 페이지를 다루고 있는지 확인하려는 경우 문제가 될 수 있습니다. 사실, 공식 문서에는 원래 쿼리를 복원하기 위해 추가 함수를 호출해야 하므로 이 함수의 사용을 권장하지 않는 메모가 있습니다. 또한 기본 쿼리를 교체하면 페이지 로딩 시간에 부정적인 영향을 미칩니다.get_posts()
함수 사용: 이것은query_posts()
와 거의 비슷하게 작동하지만 기본 쿼리를 수정하지 않습니다. 반면에get_posts()
는 기본적으로suppress_filters
매개변수가true
로 설정된 쿼리를 수행합니다. 특히 코드에서 쿼리 관련 필터를 사용하는 경우 불일치가 발생할 수 있습니다. 페이지에서 예상하지 못한 게시물이 이 기능에 의해 반환될 수 있기 때문입니다.WP_Query
클래스 사용: 제 생각에는 이것이 데이터베이스에서 게시물을 검색하는 가장 좋은 방법입니다. 기본 쿼리를 변경하지 않으며 다른 WordPress 쿼리와 마찬가지로 표준 방식으로 실행됩니다.
그러나 데이터베이스와 상호 작용하기 위해 사용하는 방법이 무엇이든 고려해야 할 다른 사항이 있습니다.
쿼리 제한
쿼리가 가져와야 하는 게시물 수를 항상 지정해야 합니다.
이를 달성하기 위해 우리는 posts_per_page
매개변수를 사용합니다.
WordPress는 해당 매개변수에 대해 가능한 값으로 -1을 표시할 수 있습니다. 이 경우 시스템은 정의된 조건을 충족하는 모든 게시물을 가져오려고 시도합니다.
응답으로 몇 가지 결과만 얻을 수 있다고 확신하더라도 이는 좋은 방법이 아닙니다.
첫째, 우리는 단지 몇 가지 결과만 되찾는 것에 대해 확신할 수 없습니다. 그리고 가능하더라도 제한을 설정하지 않으면 데이터베이스 엔진이 일치하는 항목을 찾기 위해 전체 데이터베이스를 스캔해야 합니다.
반대로 결과를 제한하면 데이터베이스 엔진이 데이터를 부분적으로만 스캔할 수 있으므로 처리 시간이 단축되고 응답이 빨라집니다.
성능에 부정적인 영향을 줄 수 있는 WordPress가 기본적으로 수행하는 또 다른 작업은 고정 게시물을 가져오고 쿼리에서 찾은 행 수를 계산하는 것입니다.
그러나 종종 우리는 그 정보가 실제로 필요하지 않습니다. 이 두 매개변수를 추가하면 해당 기능이 비활성화되고 쿼리 속도가 빨라집니다.
$query = new WP_Query( array( 'ignore_sticky_posts' => true, 'no_found_rows' => true ) );
쿼리에서 게시물 제외
때로는 쿼리에서 특정 게시물을 제외하고 싶을 때가 있습니다. WordPress는 post__not_in
매개변수를 사용하여 이를 달성하는 매우 직접적인 방법을 제공합니다. 예를 들어:
$posts_to_exclude = array( 1, 2, 3 ); $posts_per_page = 10; $query = new WP_Query( array( 'posts_per_page' => $posts_per_page, 'post__not_in' => $posts_to_exclude ) ); for ( $i = 0; $i < count( $query->posts ); $i++ ) { //do stuff with $query->posts[ $i ] }
그러나 이것은 매우 간단하지만 내부적으로 하위 쿼리를 생성하기 때문에 최적이 아닙니다. 특히 대규모 설치에서는 응답이 느려질 수 있습니다. 몇 가지 간단한 수정으로 PHP 인터프리터가 처리를 수행하도록 하는 것이 더 빠릅니다.
$posts_to_exclude = array( 1, 2, 3 ); $posts_per_page = 10; $query = new WP_Query( array( 'posts_per_page' => $posts_per_page + count( $posts_to_exclude ) ) ); for ( $i = 0; $i < count( $query->posts ) && $i < $posts_per_page; $i++ ) { if ( ! in_array( $query->posts[ $i ]->ID, $posts_to_exclude ) ) { //do stuff with $query->posts[ $i ] } }
내가 거기에서 무엇을 했는가?
기본적으로 데이터베이스 엔진에서 일부 작업을 제거하고 대신 PHP 엔진에 맡겼습니다. PHP 엔진은 동일한 작업을 수행하지만 메모리에서 훨씬 더 빠릅니다.
어떻게?
먼저 쿼리에서 post__not_in
매개변수를 제거했습니다.
쿼리가 결과적으로 원하지 않는 일부 게시물을 가져올 수 있으므로 posts_per_page
매개변수를 늘렸습니다. 그렇게 하면 내 응답에 원치 않는 게시물이 있더라도 최소한 $posts_per_page
에 원하는 게시물이 있을 것입니다.
그런 다음 게시물을 반복할 때 $posts_to_exclude
배열 내부에 없는 게시물만 처리합니다.
복잡한 매개변수화 피하기
이러한 모든 쿼리 방법은 카테고리별, 메타 키 또는 값별, 날짜별, 작성자별 등 게시물을 가져올 수 있는 다양한 가능성을 제공합니다.
이러한 유연성은 강력한 기능이지만 매개변수화는 복잡한 테이블 조인과 값비싼 데이터베이스 작업으로 변환될 수 있으므로 주의해서 사용해야 합니다.
다음 섹션에서는 성능 저하 없이 유사한 기능을 계속 달성할 수 있는 우아한 방법을 간략하게 설명합니다.
WordPress 옵션 최대한 활용하기
WordPress 옵션 API는 데이터를 쉽게 로드하거나 저장할 수 있는 일련의 도구를 제공합니다. WordPress가 제공하는 다른 메커니즘(예: 게시물 또는 분류)이 지나치게 복잡한 작은 정보를 처리하는 데 유용합니다.

예를 들어 인증 키나 사이트 헤더의 배경색을 저장하려는 경우 옵션이 바로 우리가 찾고 있는 것입니다.
워드프레스는 이를 처리할 수 있는 기능을 제공할 뿐만 아니라 가장 효율적인 방식으로 처리할 수 있도록 합니다.
일부 옵션은 시스템이 시작될 때 직접 로드되기 때문에 더 빠른 액세스를 제공합니다(새 옵션을 생성할 때 자동 로드 여부를 고려해야 함).
예를 들어 백엔드에 지정된 속보를 표시하는 캐러셀이 있는 사이트를 고려하십시오. 우리의 첫 번째 본능은 다음과 같이 메타 키를 사용하는 것입니다.
// functions.php add_action( 'save_post', function ( $post_id ) { // For simplicity, we do not include all the required validation before saving // the meta key: checking nonces, checking post type and status, checking // it is not a revision or an autosaving, etc. update_post_meta( $post_id, 'is_breaking_news', ! empty ( $_POST['is_breaking_news'] ) ); } ); // front-page.php $query = new WP_Query( array( 'posts_per_page' => 1, 'meta_key' => 'is_breaking_news' ) ); $breaking_news = $query->posts[0] ?: NULL;
보시다시피 이 접근 방식은 매우 간단하지만 최적은 아닙니다. 특정 메타 키가 있는 게시물을 찾으려는 데이터베이스 쿼리를 수행합니다. 비슷한 결과를 얻기 위해 옵션을 사용할 수 있습니다.
// functions.php add_action( 'save_post', function ( $post_id ) { // Same comment for post validation if ( ! empty ( $_POST['is_breaking_news'] ) ) update_option( 'breaking_news_id', $post_id ); } ); // front-page.php if ( $breaking_news_id = get_option( 'breaking_news_id' ) ) $breaking_news = get_post( $breaking_news_id ); else $breaking_news = NULL;
기능은 예제마다 약간 다릅니다.
코드의 첫 번째 부분에서는 게시물의 게시 날짜와 관련하여 항상 최신 속보를 받습니다.
두 번째는 새 게시물이 속보로 설정될 때마다 이전 속보를 덮어씁니다.
그러나 우리는 한 번에 하나의 속보 게시물을 원하기 때문에 문제가 되지 않습니다.
그리고 결국 무거운 데이터베이스 쿼리(메타 키가 있는 WP_Query
사용)를 더 우수하고 성능이 뛰어난 접근 방식인 간단하고 직접적인 쿼리( get_post()
호출)로 변경했습니다.
약간의 변경을 가하고 옵션 대신 임시를 사용할 수도 있습니다.
과도기는 유사하게 작동하지만 만료 시간을 지정할 수 있습니다.
예를 들어 속보의 경우 오래된 게시물을 속보로 사용하지 않기 때문에 장갑처럼 적합하며 해당 속보를 변경하거나 제거하는 작업을 관리자에게 맡기면 관리자가 수행하는 것을 잊어버릴 수 있습니다. 그것. 따라서 두 가지 간단한 변경으로 만료 날짜를 추가합니다.
// functions.php add_action( 'save_post', function ( $post_id ) { // Same comment for post validation // Let's say we want that breaking news for one hour // (3600 = # of seconds in an hour). if ( ! empty ( $_POST['is_breaking_news'] ) ) set_transient( 'breaking_news_id', $post_id, 3600 ); } ); // front-page.php if ( $breaking_news_id = get_transient( 'breaking_news_id' ) ) $breaking_news = get_post( $breaking_news_id ); else $breaking_news = NULL;
영구 캐싱 활성화
WordPress에는 기본적으로 개체 캐싱 메커니즘이 있습니다.
예를 들어 옵션은 해당 메커니즘을 사용하여 캐시됩니다.
그러나 기본적으로 해당 캐싱은 영구적이지 않습니다. 즉, 단일 요청 기간 동안만 지속됩니다. 모든 데이터는 더 빠른 액세스를 위해 메모리에 캐시되지만 해당 요청 중에만 사용할 수 있습니다.
영구 캐싱을 지원하려면 영구 캐시 플러그인을 설치해야 합니다.
일부 전체 페이지 캐시 플러그인에는 영구 캐시 플러그인이 포함되어 있지만(예: W3 Total Cache) 다른 플러그인은 포함되어 있지 않으므로 별도로 설치해야 합니다.
파일, Memcached 또는 다른 메커니즘을 사용하여 캐시된 데이터를 저장할지 여부는 플랫폼 아키텍처에 따라 다르지만 이 놀라운 기능을 활용해야 합니다.
"이것이 그렇게 훌륭한 기능이라면 왜 WordPress는 기본적으로 이 기능을 활성화하지 않습니까?"라고 물을 수 있습니다.
주된 이유는 플랫폼의 아키텍처에 따라 일부 캐시 기술은 작동하고 다른 캐시 기술은 작동하지 않기 때문입니다.
예를 들어 분산 서버에서 사이트를 호스팅하는 경우 외부 캐시 시스템(예: Memcached 서버)을 사용해야 하지만 웹 사이트가 단일 서버에 있는 경우 파일 시스템을 사용하여 비용을 절약할 수 있습니다. 캐시합니다.
고려해야 할 한 가지는 캐시 만료입니다. 이것은 영구 캐싱 작업의 가장 일반적인 함정입니다.
이 문제를 올바르게 해결하지 않으면 사용자는 변경 사항이 표시되지 않거나 변경 사항을 적용하는 데 너무 오래 걸린다고 불평할 것입니다.
때때로 우리는 성능과 역동성 사이에서 절충점을 찾는 자신을 발견하게 될 것입니다. 그러나 이러한 장애물에도 불구하고 영구 캐싱은 거의 모든 WordPress 설치가 활용해야 하는 것입니다.
AJAX 가장 빠른 방법
AJAX를 통해 웹 사이트와 통신해야 하는 경우 WordPress는 서버 측에서 요청을 처리할 때 일부 추상화를 제공합니다.
백엔드 도구를 프로그래밍하거나 프론트엔드에서 양식 제출을 프로그래밍할 때 이러한 기술을 사용할 수 있지만 꼭 필요한 경우가 아니면 피해야 합니다.
그 이유는 이러한 메커니즘을 사용하려면 wp-admin
폴더에 있는 일부 파일에 대해 게시 요청을 해야 하기 때문입니다. WordPress 전체 페이지 캐싱 플러그인의 대다수(전부는 아님)는 게시 요청이나 관리자 파일 호출을 캐시하지 않습니다.
예를 들어 사용자가 홈페이지를 스크롤할 때 더 많은 게시물을 동적으로 로드하는 경우 캐시되는 이점을 얻을 수 있는 다른 프런트 엔드 페이지를 직접 호출하는 것이 좋습니다.
그런 다음 브라우저에서 JavaScript를 통해 결과를 구문 분석할 수 있습니다.
예, 우리는 필요한 것보다 더 많은 데이터를 보내고 있지만 처리 속도와 응답 시간 면에서 우리가 이기고 있습니다.
WordPress가 느리다는 고정관념을 깨십시오.
이것은 개발자가 WordPress를 코딩할 때 고려해야 하는 몇 가지 조언에 불과합니다.
때때로 우리는 플러그인 또는 테마가 다른 플러그인과 함께 있어야 할 수도 있고, 공통 데이터베이스로 수백 또는 수천 개의 다른 사이트를 제공하는 호스팅 회사에서 우리 사이트를 제공할 수도 있다는 사실을 잊습니다.
우리는 플러그인이 어떻게 작동해야 하는지에 초점을 맞출 뿐, 해당 기능을 어떻게 처리하는지 또는 효율적인 방법으로 수행하는지에 대해서는 관심이 없습니다.
위로부터 WordPress의 성능 저하의 근본 원인은 좋지 않고 비효율적인 코드임이 분명합니다. 그러나 WordPress는 전체 플랫폼의 속도를 저하시키지 않으면서 훨씬 더 성능이 뛰어난 플러그인과 테마를 구축하는 데 도움이 되는 다양한 API를 통해 필요한 모든 기능을 제공합니다.