한눈에 보기: 워드프레스의 모든 콘텐츠는 MySQL 데이터베이스에 저장됩니다. 핵심 테이블 구조와 WP_Query·메타쿼리 사용법, $wpdb를 통한 직접 쿼리까지 이해하면 성능과 보안을 동시에 챙길 수 있습니다. 이 글에서는 wp_posts·메타 테이블 구조, 효율적인 쿼리 작성, prepare()를 통한 보안 처리까지 단계별로 정리했습니다.

1. 핵심 테이블

워드프레스는 여러 개의 테이블로 데이터를 나눠 저장합니다. 그중 가장 많이 다루는 건 wp_postswp_postmeta입니다.

  • wp_posts: 글, 페이지, 메뉴, 첨부파일까지 모두 저장하는 메인 테이블입니다. post_type 값에 따라 구분됩니다.
    • post_type='post': 블로그 글
    • post_type='page': 고정 페이지
    • post_type='attachment': 미디어 파일
  • wp_postmeta: 글에 연결된 추가 정보(메타데이터)를 key-value 형태로 저장합니다. 예: 상품 가격, 사용자 정의 필드.
  • wp_users / wp_usermeta: 사용자 계정과 그에 연결된 프로필·권한 정보.

즉, 실제 화면에 보이는 글·페이지·상품 등은 모두 wp_posts에 저장되고, 세부 옵션·추가 데이터는 wp_postmeta에 붙습니다.

핵심 요약: wp_posts가 본문, wp_postmeta가 세부 속성이라는 구조를 이해하면 대부분의 데이터 흐름이 명확해집니다.

2. WP_Query·메타쿼리

워드프레스는 데이터베이스를 직접 조회하지 않고, 보통 WP_Query 클래스를 사용합니다. 이 클래스는 SQL을 추상화하여 안전하게 데이터를 불러옵니다.

// 최신 글 5개 불러오기
$query = new WP_Query([
  'post_type' => 'post',
  'posts_per_page' => 5
]);

if ($query->have_posts()) {
  while ($query->have_posts()) {
    $query->the_post();
    the_title();
  }
}
wp_reset_postdata();

메타데이터 조건을 검색할 땐 meta_query를 사용합니다.

// 가격이 10000 이상인 상품 불러오기
$query = new WP_Query([
  'post_type' => 'product',
  'meta_query' => [[
    'key'     => 'price',
    'value'   => 10000,
    'compare' => '>=',
    'type'    => 'NUMERIC'
  ]]
]);

주의할 점은 메타쿼리가 많아질수록 성능이 떨어진다는 겁니다. 필요한 데이터는 커스텀 테이블로 분리하는 것도 고려해야 합니다.

핵심 요약: WP_Query는 안전성과 가독성을, meta_query는 유연성을 주지만 성능에는 유의해야 합니다.

3. $wpdb·prepare

더 세밀한 제어가 필요할 때는 글로벌 객체 $wpdb를 사용해 직접 SQL을 작성할 수 있습니다. 이때 반드시 prepare()를 활용해야 SQL 인젝션을 방지할 수 있습니다.

global $wpdb;

// 전체 게시글 수 구하기
$count = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_type='post'");

// 안전한 쿼리: prepare() 사용
$title = 'Hello World';
$result = $wpdb->get_results(
  $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE post_title = %s", $title)
);

prepare()는 바인딩된 값의 타입을 자동으로 처리해주므로 보안에 안전합니다. 문자열은 %s, 정수는 %d를 사용합니다.

또한, get_results(), get_row(), get_col(), get_var() 같은 메서드로 결과를 다양한 형태로 다룰 수 있습니다.

핵심 요약: 직접 쿼리를 쓸 땐 반드시 $wpdb->prepare()를 거쳐야 보안이 보장됩니다.

FAQ

  • Q. 직접 SQL을 쓰는 게 위험한 이유는? prepare 없이 사용자 입력을 그대로 쿼리에 넣으면 SQL 인젝션 공격에 노출됩니다.
  • Q. 메타쿼리 대신 커스텀 테이블을 써야 하는 경우는? 메타데이터가 수십만 건 이상 쌓여 성능이 느려질 때는 전용 테이블을 만드는 게 효과적입니다.
  • Q. WP_Query와 query_posts() 차이는? query_posts()는 메인 쿼리를 덮어쓰므로 권장되지 않습니다. WP_Query를 사용하고 필요하면 pre_get_posts 훅으로 제어하세요.
  • Q. $wpdb 사용 시 테이블 접두사 변경 문제는? 반드시 $wpdb->posts, $wpdb->postmeta처럼 객체 프로퍼티를 사용해야 합니다. 직접 wp_posts를 쓰면 접두사 커스터마이즈 환경에서 깨집니다.
  • Q. 성능 최적화 팁은? 필요한 필드만 SELECT하고, LIMIT/OFFSET을 활용하세요. 캐시(Transients, Object Cache)도 함께 고려해야 합니다.

출처

9. 「MySQL로 데이터 다루기: wp_posts·메타·쿼리 성능」

👉 다음 단계 학습 가이드