한눈에 보기: 워드프레스의 모든 콘텐츠는 MySQL 데이터베이스에 저장됩니다. 핵심 테이블 구조와 WP_Query·메타쿼리 사용법, $wpdb를 통한 직접 쿼리까지 이해하면 성능과 보안을 동시에 챙길 수 있습니다. 이 글에서는 wp_posts·메타 테이블 구조, 효율적인 쿼리 작성, prepare()를 통한 보안 처리까지 단계별로 정리했습니다.
1. 핵심 테이블
워드프레스는 여러 개의 테이블로 데이터를 나눠 저장합니다. 그중 가장 많이 다루는 건 wp_posts
와 wp_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·메타·쿼리 성능」
👉 다음 단계 학습 가이드
- 쿼리 성능: 데이터 최적화는 「캐싱과 성능 최적화: Object Cache·CDN·크리티컬 CSS」에서 확인하세요.
- 보안: SQL Injection 방어는 「워드프레스 보안 기본기: Nonce·권한·XSS/SQLi 방어 루틴」에서 다룹니다.