워드프레스 – 루프 커스터마이징

일전에 워드프레스 루프에 대해 포스팅한 적이 있는데, 이는 테마를 만들 때 루프의 역할을 이해하고자 하는 목적이 있었다. 이번에는 루프가 어떻게 동작하는지 조금 더 자세히 들여다보고 루프를 입맛에 맞게 수정하는 방법들에 대해 살펴보도록 하겠다.

루프 기능을 커스터마이징하는 세 가지 방법

루프 기능은 크게 세 가지 방법으로 구현할 수 있는데 query_posts(), WP_Query(), get_posts()의 세 함수를 사용하는 방법이 있다. 사실 이 각각으로도 몇 개의 포스팅을 할 만큼 분량이 많기는 하지만 기본적인 수준에서 이해해보고자 하는 것이 이 글의 목적이다.

query_posts()

루프를 하나만 사용하고 반환되는 포스트들의 타입을 조정하고 싶다면 query_posts() 함수를 사용하면 된다. 이 함수를 사용하면 포스트 개수를 제한하거나 특정 카테고리/태그의 포스트를 제외하는 일을 할 수 있다.

참고 : http://codex.wordpress.org/Function_Reference/query_posts

WP_Query()

한 번에 여러 루프를 사용할 때 커스터마이징을 적용할 수 있는 강력한 도구이다. WP_Query()의 다른 인스턴스를 만들어서 루프를 여러 개로 만들고, 각각을 커스터마이징할 수 있다.

참고 : http://codex.wordpress.org/Class_Reference/WP_Query

get_posts()

get_posts() 함수는 테마의 어디서든 간단히 루프를 생성하는 방법이다. get_posts()는 query_posts()와 동일한 파라미터를 입력받아 사이드바, 푸터 등 어느 곳에서든 루프를 돌 수 있다.

query_posts()를 사용한 루프 커스터마이징

query_posts()는 워드프레스 루프에 대해 특정 카테고리를 제외하거나, 특정 카테고리만 포함하거나 하여 필터를 할 수 있고 개수를 제한할 수도 있다. query_post는 $query_string을 변경하므로, 사용후에는 wp_reset_query() 함수를 호출해서 쿼리를 복원해야 한다.

<?php
global $query_string;
$posts = query_posts($query_string.'&cat=-9'); // 특정 카테고리 빼기
if (have_posts()) : while (have_posts()) : the_posts();
...
endwhile; else:
...
endif;
wp_reset_query(); // 쿼리 복원
?>

조금 더 커스터마이징을 가미한다면 다음과 같은 형태도 가능하다.

$posts = query_posts($query_string.'&cat=-9,-8,-7&posts_per_page=3&order=ASC');

query_posts()를 사용할 때의 키는 원래의 쿼리를 전역변수인 $query_string에 저장해두고 루프가 끝난 후 리셋해준다는 점이다. 이는 쉽고 편리하기는 하지만 문제가 있다. query_posts()는 추가적인 DB 쿼리를 사용하기 때문에 is_page()나 is_single()과 같은 템플릿 태그에 영향을 끼칠 수 있다. 이러한 민감한 부분을 건드리지 않는 필요성은 WP_Query()를 통해 충족될 수 있다.

WP_Query()를 통한 커스터마이징

일단 코드부터 보자

<?php // Loop custominzed with WP_Query
$custom_query = new WP_Query('cat=-9');
while($custom_query->have_posts()) : $custom_query->the_post();
//...
endwhile;
wp_reset_postdata(); // 쿼리 복원
?>

이 방식은 전역 변수인 $query_string을 쓰지 않는다. 또한 커스터마이징하는 방법에서 여러 개의 조건은 &으로 묶을 수 있다.

이 방식의 위대함(?)은 WP_Query의 인스턴스를 원하는 만큼 만들어 그만큼의 루프를 하나의 페이지에서 여러 개 사용할 수 있다는 점이다.

다음 코드는 서로 다른 카테고리를 제외하면서 세 번의 루프를 도는 예를 보여준다.

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

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

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

WP_Query()를 사용하는 방법의 강점은 이 외에도 더 있지만, 조금 있다가 살펴보기로 한다.

get_posts()를 통해 루프를 커스터마이징하기

get_posts()는 멀티루프를 만드는 가장 안전한 방법이다. 이는 사실 while 구문을 사용하는 루프를 돌지 않고 별도의 쿼리를 만들어서 포스트를 구해온다.

<?php //additional loop via get_posts
global $post;
$args = array('category' => -9);
$custom_posts = get_query($args);
foreach ($custom_posts as $post) : setup_postdata($post);
//...
endforeach;
?>

이 때 다른 커스터마이징을 원한다면 다음과 같은 식으로 get_posts()에 넣을 파라미터를 변경할 수 있다.

$args = array('category'=>-7,-8,-9, 'numberposts'=>3, 'order'=>'ASC');

get_posts()에는 보다 많은 파라미터 들이 있는데 이들은 Codex에서 확인해보면 된다.

워드프레스 루프

루프(Loop)는 워드프레스가 동작하는 가장 기본적인 원리이다. 루프는 다음과 같이 생겼다.

<?php
//The Loop
if (have_posts()) : while (have_posts()) : the_post();
...
endwhile; else;
...
endif;
?>

이는 일반적인 프로그래밍의 while 루프와 비슷하게 생겼는데, PHP에서 사용하는 while 루프의 문법을 그대로 따르고 있다. 루프를 돌기 이전에 표시할 포스트가 있는지 확인하고 매 포스트마다 반복적으로 the_post() 함수를 실행한다. 이 함수는 루프 속에서 동작하는 함수들에 대해 기본적으로 사용하는 포스트를 지정해주는 역할을 한다. 지정된 수만큼의 루프를 돌며 the_post()가 실행되다음에는 루프가 종료된다.

다음은 보다 구체적인 루프의 모습이다.

<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_posts(); ?>
<div class="post" id="post-<?php the_ID(); ?>">
<h2><a href="<?php the_permalink(); ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>

<?php echo get_post_meta($post->ID, 'PostThumb', true; ?>
<p class="meta">
<span>Posted on</span> <?php the_time('F js, Y'); ?> <span>by<span> <?php the_author(); ?>
</p>

<?php the_content('Read Full Article'); ?>

<p><?php the_tags('Tags: ', ', ', '<br />'); ?>
Posted in <?php the_category(', '); ?>
<?php comments_popup_link('No comments;', '1 Comment', '% Comments'); ?></p>

</div>

<?php endwhile; ?>

<?php next_posts_link('Older Entries'); ?> <?php previous_posts_link('Newer Entries'); ?>

<?php else : ?>

<h2>Nothing Found</h2>

<?php endif; ?>

위 코드를 분석하자면 다음과 같다.

  1. 먼저 작성된 포스팅이 있는지를 검사한다. 포스팅이 없다면 Nothing Found를 출력한다.
  2. while 문으로 루프를 시작한다. Setting > Read 에서 설정한 수만큼 루프를 돌게 된다.
  3. 각 포스팅에 대해서 머리글을 쓴다. 머리글에는 각 포스팅의 영구주소로 링크를 건다.
  4. get_post_meta()는 포스팅의 메타정보나 커스텀 필드를 가져올 수 있다. 이 예시에서는 <img /> 태그를 가져올 것으로 보인다.
  5. 포스팅된 날짜를 표시
  6. 포스팅 본문을 표시한 후, 부가 정보인 태그정보와 글이 발행된 카테고리 정보를 가져온다.
  7. 포스팅 아래쪽에는 코멘트 정보를 표시
  8. 다음글/이전글에 대한 링크를 표시하고
  9. 포스팅이 없는 경우에 대체 문구를 표시

그런데 이 루프는 그저 루프일 뿐인데 어떤 포스팅을 DB로부터 가져와야 하는지 어떻게 알까? 이미 워드프레스 루프는 쿼리스트링에 대해 알고 있다. 이 쿼리스트링을 실제로 확인하고 싶다면 $query_string 변수를 전역으로 변경하여 찍어볼 수 있다.

<?php global $query_string; echo $query_string; ?>

루프에서 일반적으로 사용하는 함수들은 다음과 같은 것들이 있다.

  • the_title() : 포스트의 제목을 출력
  • the_ID() : 포스트의 아이디를 출력
  • the_author() : 포스트의 작성자를 출력
  • the_category() : 포스트가 속한 카테고리를 출력

또한 루프 내부에서는 the_post() 함수가 반환하는 변수인 $post를 사용할 수 있다. 이 객체는 여러 포스트의 ‘raw’한 데이터들을 가지고 있다. 이 때 -> 연산자는 C의 구조체 멤버 접근 연산자와 비슷하게 생겼는데, 아마 객체의 멤버에 접근할 때 사용하는 것으로 보인다. (나는 PHP는 잘 모른다…)

  • $post->ID : 포스트의 ID
  • $post->post_content : 실제 컨텐츠
  • $post->post_modified : 포스트가 최종 수정된 시각의 타임 스탬프
  • $post->post_name : 포스트의 슬러그 정보

또한 루프외부에서도 몇 몇 함수를 사용하여 정보를 가져올 수 있다. 이 함수들은 현재 표시하는 포스트와는 별개의 정보를 다룬다. 그외 여러 함수들에 대해서는 (이런 함수들을 템플릿 태그라고 한다.) 맨 아래 링크를 참고한다.

  • wp_list_pages() : 정적 페이지로의 링크들을 리스팅한다.
  • next_posts_link() : 다음 페이지로의 링크
  • wp_tag_cloud() : 태그 클라우드는 간단히 함수로 만들 수 있다.
  • wp_permalink() : 포스트들의 영구주소를 구한다.

http://codex.wordpress.org/Template_Tags

또한 그외 함수들에 대해서는 이 곳(워드프레스 함수 레퍼런스)을 참고한다.

20081208 :: 테마변경

곰곰히 생각해보니 블로그 테마 바꾼지가 1년 반도 훨씬 넘은 것 같아서 급히 변경해보았습니다.  물론 제가 급히 만들어서 바꾼 건 아니구요. 구글링 잠깐해서 바로 설치했는데  꽤나 마음에 듭니다. 하지만 내년에는 꼭 제손으로 테마를 새로 만들고야 말겠어요. (올해중으로 이룰 수 있다면 너무나 좋으련만.. ㅠㅠ)

20080329 :: 워드프레스 2.5 RC2 가 나왔습니다.

* 글을 쓰고 바로 직후에 정식버전이 릴리즈 되었더군요. 관리자 페이지가 정말 깔끔하게 변신합니다. 아직 업그레이드하지 않은 워드프레스 사용자분들께 얼른 하시라고 추천하고 싶네요

 

워드 프레스 새 버전이 곧 나올 것 같습니다. 2.5RC2가 나왔더군요. 지난번 2.2 설치하다가 홀랑 날려먹은;; (엉엉) 기억이 나서 선뜻 용기가 나지는 않았습니다. 게다가 2.4 버전을 건너뛰고 2.5로 왔다는 것도 괜한 두려움을 만드는 소지가 있습니다(!) 소심한 저는 이번에도 과감히 일말의 백업(?)없이 2.5를 덜컥 본 블로그에 설치합니다.

음… 파일을 업로드하고, 업그레이드 (사실 업그레이드는 DB에 테이블들이 추가되는 것 정도를 말하는 것 같습니다.)를 마치고 났더니 세상에!!!! 블로그 외견상 아무런 변화가 없습니다!!! 실패했는 줄 알고 잠시 당황했으나, 지금 wireframe은 그냥 허접한 스킨 하나로 버티고 있지 뭡니까. 아무튼 떨리는 마음으로 어드민 페이지로 가기 위해 링크를 클릭한 순간!

깜짝 놀랐습니다. 어드민 페이지는 정말 완전히 확 달라졌거든요

확 달라진 어드민 페이지

아래가 어드민에 접속했을 때 어떻게 생겼는지에 대한 스크린샷입니다. 뭐 기존 버전 스크린샷이 없으니 뭐라 비교할 건덕지가 없어서 좀 그렇습니다만… (찍어둘 걸 그랬네요) 물론 평소에는 administrator 계정을 거의 사용하지 않고 편집자(Editor)계정을 사용합니다. (이것저것 신경쓰기 귀찮고 그냥 글만 쓴다는 주의랍니다.) 그래서인지 별다른 메뉴가 보이지 않습니다. 글을 작성하고, 관리하고, 댓글을 볼 수 있는 정도의 메뉴만 보입니다. 눈에 확 들어오도록 오렌지색의 바가 있고 거기에 큼지막하게 새 포스트를 쓰시라는 버튼이 달려있군요. 사실, 이 부분과 상단 메뉴의 위치가 약간 달라진 것을 제외하면 대시보드에서의 변화는 크게 눈에 띄지는 않습니다. 뉴스위젯이나 Incoming Link에 RSS 버튼이 달려있는게 보이는데, 저번 버전에서도 있었는지는 잘 기억이 안나네요..;;;

감동의 에디터 화면

에디터 화면은 조금 더 감동적입니다. TinyMCE의 새로운 버전으로 보이구요. 이전 버전에서 한글 글꼴이 적용되지 않아 큼지막한 바탕체로 포스트를 썼더야 했던 문제가 사라졌구요, 무엇보다 한글 한 글자만 쓴 이후에 스페이스바를 띄우면 글자가 앞으로 한 칸 밀려서 스페이스 바를 두 번씩 쳐줘야 했던 골치아픈 문제가 해결되었네요. (파이어폭스 RC 버전들을 사용중이라 그럴 수도 있습니다)

그 외에 업로드 하는 파일의 종류가 단순히 이미지 뿐만아니라 다른 각종 미디어 파일들도 가능해졌다는 점도 아주 칭찬해주고 싶구요, 기타 인터페이스 들이 너무나 깔끔해졌습니다. 글 쓰는 일이 즐거워지는 군요.

아무튼 이래저래 많이 편리해졌네요. 게다가 플러그인 화면에서는 관리자 화면 자체에서 해당 플러그인의 새 버전을 확인하고 ftp 로 업로드 하는 등의 절차없이 그자리에서 바로 플러그인을 설치할 수 있게 된 점도 멋집니다. 자 , 이제 2.5RC2에서 글을 두 개나 썼으니, 다른 버그들이 있는지 확인하러 가봐야겠군요!