RSS

월간 보관물: 1월 2013

워드프레스 루프 총 정리

워드프레스에서 루프를 이용하는 방법은 총 4가지이다.

  • 기본 루프
  • WP_Query를 이용하는 루프
  • query_posts()를 이용하는 루프
  • get_posts()를 이용하는 루프

첫 번째, 기본 루프는 별다른 조작없이 디폴트 쿼리를 실행해 보여준다. (참고 : 워드프레스의 루프는 어떻게 돌아가는가.) 대부분의 테마에서 가장 많이 사용된다. 템플릿 태그를 통해 콘텐츠 정보를 확인할 수 있다.

두 번째, WP_Query를 이용하는 루프는 다수의 인스턴스를 생성해 데이터를 활용하고자 할 때 주로 사용한다. 멀티 루프를 통해 각각의 콘텐츠를 사용자 입맛대로 출력할 때 유용하다. (참고 : 워드프레스 루프 만들기[1])

세 번째, query_posts()를 이용하는 루프는 기본 쿼리 자체를 변경하고자 할 때 사용한다. 주로 Single 루프에 사용된다. (참고 : 워드프레스 루프 만들기[2])

마지막 get_posts()를 이용하는 루프는 쉽고 간편하게 콘텐츠 데이터를 불러올 때 사용한다. 주로 멀티 루프에 사용된다. (참고 : 워드프레스 루프 만들기[3])

 
 

태그: , , ,

워드프레스 루프 만들기[3]

커스텀 쿼리를 만드는 가장 간단한 방법, get_posts()를 알아보자.

get_posts()는 내부적으로 WP_Query를 이용한다. 하지만 포스트와 관련된 모든 탬플릿 태크를 바로 사용할 수 는 없다. 탬플릿 태그와 관련된 전역 데이터가 자동으로 생성되지 않기 때문이다. 이를 위해서는 setup_postdata()를 호출해 값을 채워주는 과정이 필요하다.

그리고 get_posts()의 반환값이 배열이라는 점에 주의해야 한다. 리턴값을 받으려면 foreach를 통해 각각의 루프 코드를 받아야 한다. 아래 소스에서 확인해 보자.

<ul>
<?php
global $post;
$args = array( 'numberposts' => 5, 'offset'=> 1, 'category' => 1 );
$myposts = get_posts( $args );
foreach( $myposts as $post ) :	setup_postdata($post); ?>
	<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endforeach; ?>
</ul>

이 함수는 사이드바나 풋터에 관계없이 다중 루프를 구성하거나 간편하게 데이터를 가져올 때 주로 사용한다.

 
 

태그: , ,

워드프레스 루프 만들기[2]

커스텀 쿼리를 만드는 두 번째 방법을 알아보자. 바로 query_posts()다.

워드프레스 페이지가 호출되면 콘텐츠 정보가 전역변수인 $wp_query에 생성된다. 루프를 통해 데이터를 불러오더라도 기본 쿼리는 변경하지 않고 파라메터를 이용해 데이터를 조작한다. 하지만 이 기본 쿼리를 변경할 필요가 있을 때 사용하는 게 query_posts()이다.

query_posts()는 로우레벨 접근방식으로 기본 쿼리를 변경하는 장점이 있지만, 반대로 기본 쿼리를 변경하기 때문에  캐시가 지워져 성능에 영향을 미칠 수 있다. 재활용성과 데이터베이스 성능 저하를 고려해야 한다.

전역변수인 $wp_query를 변경하기 때문에 한 번 이상 호출하거나, 루프 내에서 호출하게 되면 메인 루프 내용이 달라져 잘못된 콘텐츠가 반환되므로 주의가 필요하다.

<?php
// retrieve one post with an ID of 5
query_posts( 'posts_per_page=3&paged='.$paged' );

// set $more to 0 in order to only get the first part of the post
global $more;
$more = 0;

// the Loop
while (have_posts()) : the_post();
	the_content( 'Read the full post »' );
endwhile;

wp_reset_query();
?>

query_posts( ‘posts_per_page=3&paged=’.$paged’)의 결과로 기본 추출된 포스트 콘텐츠가 변경된다. 즉, query_posts()가 없었다면 출력되었을 콘텐츠는 더 이상 나타나지 않는다.

query_post()는 $query_string을 변경하여 기본 쿼리를 변경하므로, 사용후에는 wp_reset_query() 함수를 호출해서 쿼리 복원을 해주는 게 좋다.

query_post()는 주로 single 루프의 결과값을 바꾸고 싶을 때 주로 사용한다. 포스트의 개수나 어떤 카테고리에서 제외하고픈 포스트나 테그등을 제한할 때 사용하면 좋다. 다중 루프에서도 사용할 수는 있지만, WP_Query를 사용하는 편이 낫다.

참고 : 파라메터 사용 법 : http://codex.wordpress.org/Function_Reference/WP_Query#Parameters

 
 

태그: , , ,

워드프레스 루프 만들기[1]

맛있는 음식이 매일매일 나오는 자판기가 있다. 처음엔 편하고 신경 쓸 게 없어서 좋지만, 사람의 호기심이란 게 그냥 가만있지 못한다. 이곳저곳을 살펴보다가 결국 뜯어보고 역으로 추적해본다. 그럼, 결론은 두 가지다.

  • 하나는 그 기계가 망가져서 회복불능상태가 된다. 선무당이 사람 잡는 꼴이다.
  • 다른 하나는 그 원천을 찾아내서 더 좋은 자판기를 만든다.

이를 워드프레스에 적용하면 첫 번째처럼 망가지는 일은 절대 없다. 오픈소스이기 때문에 늘 다시 받아 회복할 수 있다. 그러나 항상 두 번째처럼 성공하는 것은 아니다. 이리저리 찾다가 길을 잃고 헤매거나 포기하는 경우가 다반사다. 하지만 그것을 넘어서면 새로운 맛을 느끼고 더 좋은 자판기를 만들게 된다.

커스텀 쿼리가 그것이다. 워드프레스를 원하는 대로 다듬고 뽐낼 수 있는 내가 만든 자판기인 셈이다. 어떻게 구성되는지 알아보자.

처음으로 소개할 커스텀 쿼리는 WP_Query()의 인스턴스를 직접 조작하는 방법이다. 워드프레스 페이지가 호출되면,  $wp_query 전역변수에 포스트/페이지 관련된 메타 데이터가 저장된다. 기본 루프를 사용하면 별도의 조작 없이 템플릿 태그를 통해 $wp_query 정보를 이용할 수 있다. 그러나 원하는 데이터를 가져오는 데는 한계가 있다. 좀 더 상세하게 사용하기 위해서는 WP_Query()의 인스턴스를 직접 생성해 조작해야 한다. 커스텀 쿼리를 얼마나 잘 쓰느냐에 따라 워드프레스의 성능과 UI가 결정된다.

다음은 페이지에 5개의 포스트를 가져오는 커스텀 쿼리이다.

<?php

$myPosts = new WP_Query();

   $myPosts->query(‘posts_per_page=5’);

while ($myPosts->have_posts()) : $myPosts->the_post();

?>

<!– 필요한 작업 수행 –>

<?php endwhile; ?>

기본 쿼리와 비교해 보자. 기본 쿼리일 때는 전역 함수인 have_posts(), the_post()를 호출하여 WP_Query 클래스에 접근한다. 전역함수 내에서 $wp_query 인스턴스를 생성해 WP_Query 클래스 메소드를 호출하는 식이다. 다양한 활용을 위해선 query() 메소드의 파라메타 사용법에 익숙해져야 한다.

  • query()와 그 파라메터 설명 : http://codex.wordpress.org/Function_Reference/query_posts

$myPosts->query(‘posts_per_page=5’) 호출되면 WP_Query의 query메소드가 get_posts()를 호출하여 콘텐츠 정보를 메모리상에 올려놓는다.

function query( $query ) {
$this->init();
$this->query = $this->query_vars = wp_parse_args( $query );
return $this->get_posts();
}

WP_Query()는 기본 쿼리를 변경하지 않으므로 다중 루프에 맘껏 사용할 수 있다.

<?php // Loop 1
$first_query = new WP_Query('cat=-1'); // exclude category
while($first_query->have_posts()) : $first_query->the_post();
...
endwhile;
wp_reset_postdata();

// Loop 2
$second_query = new WP_Query('cat=-2'); // exclude category
while($second_query->have_posts()) : $second_query->the_post();
...
endwhile;
wp_reset_postdata();

// Loop 3
$third_query = new WP_Query('cat=-3'); // exclude category
while($third_query->have_posts()) : $third_query->the_post();
...
endwhile;
wp_reset_postdata();
?>
 
 

태그: , , ,

워드프레스의 루프는 어떻게 돌아가는가.

루프를 구성하는 최소한의 소스를 보자.

<?php

if (have_posts()) :

while (have_posts()) :

the_post();

// loop content (template tags, html, etc)

end while;

end if;

?>

콘텐츠가 있으면 루프를 돌려서 출력한다는 내용이다. 일반 프로그래밍에서 흔히 볼 수 있는 패턴이다. 하지만 어디서 어떻게 원본 데이터를 가져오는지에 대한 코드가 보이지 않는다. 즉, 매개 되는 변수가 없다. 아마도 내부에서 전역으로 사용되는 변수에 값이 담겨 있을 것 같다는 추축을 하게 된다. 답답함이 몰려올 것이다.

이 간단한 소스를 이해하기 위해서는 워드프레스의 동작 원리를 알아야 한다. 이전 포스팅(워드프레스 이해하기 – 어떻게 원하는 콘텐츠를 불러올까?)을 참고하자.

요청 페이지가 호출되면, 워드프레스는 이미 기본 쿼리 객체 내에서 get_posts() 메소드를 호출하여 콘텐츠 목록을 작성하고 전역 변수에 저장한다. 이때 WP_Query 객체의 $wp_query가 저장소 역할을 한다. 이게 핵심이다. 그 다음은 루프가 해당 목록을 출력한다.

the_post() 메소드의 정의를 보면 $wp_query 변수를 확인 할 수 있다.

function the_post() {

     global $wp_query;

     $wp_query->the_post();
}

 
 

태그: , , , ,

워드프레스 이해하기 – 어떻게 원하는 콘텐츠를 불러올까?


워드프레스는 최적화된 오픈 소스다. 유수의 뛰어난 프로그래머가 끊임없이 다듬고 또 많은 사용자에 의해 버그 리포팅이 된다. 소스는 더욱 정규화되고 단단해지지만, 코어 엔진이 어떻게 원하는 데이터를 던져 주는지 파악하기란 더욱 어려워 진다. 오픈 소스임에도 불구하고 말이다.

과연, 워드프레스는 어떤 방식으로 콘텐츠를 불러올까?

한 사용자가 나의 블로그에 접속하여 특정 태그 (Xdebug)를 클릭했다고 하자.

태그

웹 브라우저 URL이 다음과 같이 나온다.

https://guspark.wordpress.com/tag/xdebug

워드프레스는 해당 URL을 분석하고 아래와 같은 작업을 한다.

  1. 태그 페이지를 요청했군.
  2. 태그에 해당하는 템플릿을 준비하자.
  3. “xdebug”라는 태그가 첨부된 포스트를 찾아 출력하자.

세부적으로 알아보자.

1. 요청 URL을 해석해 콘텐츠를 선택하는 동작은 WP_Query 객체의 parse_query() 메소드가 수행한다. URL에서 쿼리 매개 변수를 추출한다. https://guspark.wordpress.com/tag/xdebug/와 https://guspark.wordpress.com?tag=xdebug/는 같다.(xdebug 값을 가진 태그를 추출)

2. 추출된 쿼리 매개변수를 MySQL 쿼리로 변환하여 콘텐츠를 가져온다. 이 과정에서는 WP_Query 객체의 get_posts() 메소드를 이용한다. get_posts()는 쿼리 매개변수를 모두 SQL문으로 변환한 후 MySQL에 쿼리를 직접 요청하여 원하는 콘텐츠를 추출한다.

3. 추출된 콘텐츠는 WP_Query 객체에 저장되어 워드프레스 루프에서 사용되고 필요 시 캐시로 저장된다.

4. 워드프레스는 쿼리 타입과 반환된 포스트의 개수를 근거로 테마에서 템플릿을 결정하며, 쿼리의 결과는 루프에 전달된다.

 

 
 

태그: , , ,

워드프레스 함수 사용법 익히기

인라인 설명서 사용법을 익혔다면 코어 함수의 정의와 사용법을 분석하는 데 많은 도움이 될 것이다. 하지만 실제 소스코드에 응용하기란 여간해선 쉽지 않다. 간단한 사용 예제를 볼 수 있다면 더할 나위 없이 좋으련만…하고 생각이 들었다면 제대로 짚었다.

코덱스 Function Reference에서 이러한 기능을 제공한다. 함수의 설명 및 예제코드까지 친절하게 보여준다. 코덱스로 들어가 get_posts() Function을 찾아보자.

함수레퍼런스

클릭해서 예제를 찾아보자. 필요로 하는 포스트를 불러오는 법에 대한 예제를 제공한다. 간단한 예제지만, 이런 방식으로 레퍼런스 자료를 활용하면 새로운 함수를 어떻게 자신의 코드에 적용할 수 있을지 쉽게 알 수 있게 된다.

사용예제

 

 

 
 

태그: , ,

워드프레스 코어 파일의 길잡이 – 인라인 설명서

무작정 워드프레스 코어를 디버깅하려다간 낭패를 보기 십상이다. 생소한 함수며 전역 변수, 함수 간 호출 관계, 용도 등 파악해야 할 사항들이 너무 많기 때문이다.

천리길도 한 걸음이란 말처럼 주요 함수들부터 차근차근 파악해야 한다. 친절하게도 대부분 코어 파일은 인라인 설명서가 있다. 해당 함수 바로 앞에 블록 주석 형식으로 상세한 설명이 들어간다.

/**

 * Retrieve list of latest posts or posts matching criteria.
 *
 * The defaults are as follows:
 *     ‘numberposts’ – Default is 5. Total number of posts to retrieve.
 *     ‘offset’ – Default is 0. See {@link WP_Query::query()} for more.
 *     ‘category’ – What category to pull the posts from.
 *     ‘orderby’ – Default is ‘post_date’. How to order the posts.
 *     ‘order’ – Default is ‘DESC’. The order to retrieve the posts.
 *     ‘include’ – See {@link WP_Query::query()} for more.
 *     ‘exclude’ – See {@link WP_Query::query()} for more.
 *     ‘meta_key’ – See {@link WP_Query::query()} for more.
 *     ‘meta_value’ – See {@link WP_Query::query()} for more.
 *     ‘post_type’ – Default is ‘post’. Can be ‘page’, or ‘attachment’ to name a few.
 *     ‘post_parent’ – The parent of the post or post type.
 *     ‘post_status’ – Default is ‘publish’. Post status to retrieve.
 *
 * @since 1.2.0
 * @uses $wpdb
 * @uses WP_Query::query() See for more default arguments and information.
 *
 * @param array $args Optional. Overrides defaults.
 * @return array List of posts.
 */

get_posts()의 인라인 설명서이다. 메소드의 요약 설명과 상세 설명, 버전 정보, 전역 변수 사용 정보, 상세 설명이 담긴 codex 페이지, 파라메터 및 리턴 값 정보 등이 등록되어 있다. 좀 더 자세한 정보는 Codex 사이트에 가면 예제까지 볼 수 있다.

자세히 보면

  •  이 버전은 1.2.0
  •  $wpdb와 WP_Query::query()를 전역으로 호출해서 사용
  •  자세한 코텍스 사이트는 http://codex.wordpress.org/Template_Tags/get_posts
  •   파라메터는 어레이를 옵셔널하게
  •   리턴값은 포스트에 대한 어레이를 반환 

인라인 설명서만으로도 코어 소스를 보는 데 많은 도움이 된다. get_posts() 메소드를 열어 인라인 설명서를 바탕으로 실제 코드를 분석하면 많은 도움이 될 것이다.

function get_posts($args = null) {

       $defaults = array(

             ‘numberposts’ => 5, ‘offset’ => 0,

             ‘category’ => 0, ‘orderby’ => ‘post_date’,

             ‘order’ => ‘DESC’, ‘include’ => array(),

             ‘exclude’ => array(), ‘meta_key’ => ”,

             ‘meta_value’ =>”, ‘post_type’ => ‘post’,

             ‘suppress_filters’ => true

       );

        $r = wp_parse_args( $args, $defaults );

       if ( empty( $r[‘post_status’] ) )

             $r[‘post_status’] = ( ‘attachment’ == $r[‘post_type’] ) ? ‘inherit’ : ‘publish’;

       if ( ! empty($r[‘numberposts’]) && empty($r[‘posts_per_page’]) )

             $r[‘posts_per_page’] = $r[‘numberposts’];

       if ( ! empty($r[‘category’]) )

             $r[‘cat’] = $r[‘category’];

       if ( ! empty($r[‘include’]) ) {

             $incposts = wp_parse_id_list( $r[‘include’] );

             $r[‘posts_per_page’] = count($incposts);  // only the number of posts included

             $r[‘post__in’] = $incposts;

       } elseif ( ! empty($r[‘exclude’]) )

             $r[‘post__not_in’] = wp_parse_id_list( $r[‘exclude’] );

        $r[‘ignore_sticky_posts’] = true;

       $r[‘no_found_rows’] = true;

        $get_posts = new WP_Query;

       return $get_posts->query($r);

 }

 
 

태그: , ,

영어의 완료시제 이해하기

영어의 시제를 완벽하게 이해해서 구사하기란 참 어렵다.

우리가 자유롭게 구사하는 조사를 경이롭게 바라보는 원어민의 입장도 이와 같으리라. 완료시제의 개념이 서지 않으면 화자의 의도를 정확하게 받아들이기 어렵고 영문 소설을 봐도 그 문장에 녹아있는 맛을 느끼기 어렵다.

현재와 과거 시제가 명확하게 구분되어 있는데, 도대체 왜 완료시제를 쓸까. 진지하게 고민했다. 예문을 통해 분석 해보았다. 한국어는 완료라는 개념을 사용하지 않기 때문에 문법적으로 설명하기가 매우 어려웠다. 하지만 완료를 사용할 때에 항상 기준 되는 시점이 있다는 걸 발견했다. 이게 핵심이다.

먼저 대화나 글 쓸 때 기준이 되는 시점을 생각해 보자. 거의 현재이거나 과거다. 현재가 당연해 보이지만 실생활에서는 과거 시제를 많이 쓴다. 시간이란 게 멈춰 서 있는 게 아니므로 경험한 순간 동시에 표현하기 어렵다. 밥을 먹었다, 옷을 입었다, 차를 탔다, 전철에서 내렸다, 친구와 카톡을 했다와 같이 사실관계를 표현한다.

현재 시제도 물론 사용한다. 이 장미꽃이 참 아름답다거나 철수의 가방이 파란색이다, 비가 온다, 가방이 무겁다, 사과가 맛있다는 등 사물의 상태를 나타낸다.

그럼 이 두 가지 기준으로 완료시제를 파악해보자.

현재를 기준으로 그 이전에 일어난 일을 설명하고자 할 때는 현재완료를 쓴다. 그 이전의 일이란 게 전혀 엉뚱한 게 아니라 현재와 관련이 있어야 한다. 즉, 과거의 일을 설명하는 데 과거시제를 쓰지 않는다는 거다. 말이 안 되는 것 같지만 이게 핵심이다. (과거 시제와 병행하기도 한다. 하지만 반드시 현재완료로 표현해야 할 때가 있다.) 한국인으로서 이것을 이해하기란 참 어렵다.

같은 개념으로 과거를 기준으로 그 이전에 일어난 일을 설명할 때는 과거완료를 쓴다. 과거의 과거, 흔히 대과거라고 부른다. 별 구분 없이 사용하는 우리로선 여전히 어렵다. 하지만 현재완료보단 쉽게 이해된다.

예문을 보자.

1. 현재 완료

The house is dirty. They haven’t cleaned it for weeks.

( 그 집은 더럽다. 그들이 몇 주 동안 청소하지 않았다. )

2. 과거 완료

The house was dirty. They hadn’t cleaned it for weeks.

(그 집은 더러웠다. 그들이 몇 주 동안 청소하지 않았었다.)

기준이 되는 시점이 현재인지 과거인지에 따라 그 이전에 일어났던 일을 설명하는 방법이 달라진다. 현재면 현재완료, 과거면 과거완료가 된다.

그러면 왜 과거 시제를 사용하지 않는가?

원어민은 과거란 말 그대로 과거이다. 현재와 상관이 없는 일이다. 일종의 단순한 서술이다. 하지만 완료란 말이 붙으면 기준 되는 시점까지 영향을 미치는 걸 내포한다. 다음 예문을 보면 더 확실하게 구분될 것이다.

1. 현재완료

Have you seen Tim this morning? (오늘 아침에 팀을 봤니?)

2. 과거

Did you see Time this morning? (오늘 아침에 팀을 봤니?)

둘 다 해석은 같지만 내포한 의미는 다르다. 전자는 물어보는 시점이 아침이고 후자는 오후나 저녁이다. 제시한 시간이나 기준의 완료 여부에 따라 완료형 사용이 결정된다. 아침에 출근해서 팀을 찾는 데 없으면 기준 시간이 지나지 않았으므로 완료형으로 묻는다. 오후가 되면 시점이 지났으므로 당연히 과거 시제를 사용한다.
[현재완료는 이런 모습]

위 그림은 현재완료를 가장 잘 설명하고 있다. 과거에 일어난 사건이 현재까지 영향을 미치고 있으며 아직 기준 시점이 지나가지 않았다.

 
댓글 남기기

게시자: 켬 2013/01/14 in Touching english

 

태그: , ,

워드프레스 실행쿼리 보기

워드프레스의 최적화된 소스를 제대로 분석하기란 쉽지 않다. 오픈소스지만 코어 해킹은 하지 않는 관행으로 통상 콘텐츠(테마)만 수정하게된다. 그러나 코어 소스를 파악하지 않은 채 주변(테마) 소스를 수정하려고 하면 여러 궁금증과 함께 답답함이 몰려온다. 특히, 데이터 셋에 어떤 쿼리가 요청되어 메모리가 채워지는지 궁금할 것이다.

프로그램 디버깅을 해본 경험이 있다면 일일이 쿼리를 찍어 보는 일이 상당히 귀찮고 번거롭다는 걸 안다. 하지만 워드프레스에서는 환경설정 파일과 디스플레이용 파일에 몇 줄의 코드만 추가하면 된다.

워드프레스의 환경설정 파일인 wp-config.php을 열어서 다음 한 줄을 추가하자.

define(“SAVEQUERIES”, true);

이 옵션을 활성화하면 데이터베이스 쿼리를 모두 전역변수에 저장해 페이지에 표시해 준다. 워드프레스가 웹 페이지를 생성할 때 호출하는 모든 쿼리를 보여줌으로써 원활한 디버깅을 할 수 있다. 테마나 플러그인 작업을 하는 중에 문제가 생기면 이 옵션을 사용하면 데이터베이스 호출 내역을 정확하게 파악할 수 있다.

자, 다음으로 요청한 쿼리를 출력할 적당한 파일을 찾아서 열어보자. 모든 페이지에 포함되는 footer.php가 괜찮을 것 같다. 아래 코드를 추가하자.

if (current_user_can(‘install_plugins’)) {
global $wpdb;
print_r($wpdb->;queries);
}

웹 페이지를 열어 디버깅 결과를 확인해보자.

define("SAVEQUERIES", true);

[define(“SAVEQUERIES”, true); 설정]

이 코드는 모두에게 열려있지는 않다. 단지 사이트 관리자가 로그인한 경우에만 출력된다. 디버깅이 끝나면 설정을 비활성화 해주는 걸 잊어선 안 된다. 불필요한 데이터가 보이기도 하지만, 해커에게 중요한 정보가 노출될 수 있기 때문이다.

define(“SAVEQUERIES”, false); /* 쿼리 디버깅 비활성화 */

쿼리 이외에 좀 더 자세한 사항들을 디버깅하고 싶다면, 즉 중단점을 걸어 더 상세하게 들춰보고 싶다면 Xdebug를 이용해야 한다. 이전에 올린 이클립스디버깅을 참고하기 바란다.

 
 

태그: , , ,