STAGE 13 · Lv.64
AJAX & REST API 엔드포인트
wp_ajax 액션, wp_localize_script, nonce 보안, register_rest_route, WP_REST_Response, 스키마 정의까지 WordPress의 비동기 통신을 완전 마스터합니다.
WordPress AJAX의 두 가지 방식
admin-ajax.php vs REST API
WordPress에서 비동기 통신을 구현하는 방법은 크게 두 가지입니다. 전통적인 admin-ajax.php 방식과 현대적인 REST API 방식입니다. 둘 다 여전히 유효하며, 상황에 따라 적절한 방식을 선택합니다.
admin-ajax.php: WordPress 초기부터 사용된 방식으로, wp-admin/admin-ajax.php 파일을 통해 AJAX 요청을 처리합니다. 구현이 간단하고 nonce 기반 보안이 내장되어 있습니다.
REST API: WordPress 4.7부터 코어에 포함된 방식으로, RESTful 원칙을 따릅니다. URL 구조가 명확하고, JSON 기반이며, 외부 서비스와의 통합에 유리합니다.
| 비교 항목 | admin-ajax.php | REST API |
|---|---|---|
| URL 구조 | admin-ajax.php?action=xxx | /wp-json/namespace/route |
| HTTP 메서드 | 주로 POST | GET, POST, PUT, DELETE |
| 인증 | Nonce 기반 | Nonce, Cookie, OAuth, App Password |
| 캐싱 | 어려움 | HTTP 캐싱 가능 |
| 외부 접근 | 제한적 | 완전 지원 |
| 권장 사용처 | 관리자 내부 기능 | 프론트엔드, 모바일 앱, 외부 연동 |
admin-ajax.php 방식 구현
단계별 구현 가이드
admin-ajax.php 방식은 3단계로 구현합니다: ① JavaScript에서 AJAX 요청 전송, ② PHP에서 요청 처리, ③ nonce를 이용한 보안 처리.
1
PHP: 스크립트 등록 및 localize - AJAX URL과 nonce를 JavaScript에 전달
2
JavaScript: AJAX 요청 전송 - fetch 또는 jQuery.ajax로 요청
3
PHP: AJAX 핸들러 - nonce 검증 후 데이터 처리 및 응답
// ========== 1단계: 스크립트 등록 및 데이터 전달 ==========
add_action('wp_enqueue_scripts', function() {
wp_enqueue_script(
'map-ajax',
MAP_PLUGIN_URL . 'public/js/ajax.js',
['jquery'],
MAP_VERSION,
true
);
// JavaScript에서 접근 가능한 데이터 전달
wp_localize_script('map-ajax', 'mapAjax', [
'url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('map_ajax_nonce'),
]);
});
// ========== 2단계: JavaScript AJAX 요청 ==========
// public/js/ajax.js
// 방법 1: Fetch API (권장)
async function loadPosts(page = 1) {
const formData = new FormData();
formData.append('action', 'map_load_posts');
formData.append('nonce', mapAjax.nonce);
formData.append('page', page);
try {
const response = await fetch(mapAjax.url, {
method: 'POST',
body: formData,
});
const data = await response.json();
if (data.success) {
document.getElementById('posts-container').innerHTML = data.data.html;
} else {
alert(data.data.message || '오류가 발생했습니다.');
}
} catch (error) {
console.error('AJAX 오류:', error);
}
}
// 방법 2: jQuery (레거시)
jQuery(function($) {
$('#load-more').on('click', function() {
$.ajax({
url: mapAjax.url,
type: 'POST',
data: {
action: 'map_load_posts',
nonce: mapAjax.nonce,
page: 2
},
success: function(response) {
if (response.success) {
$('#posts-container').append(response.data.html);
}
}
});
});
});
// ========== 3단계: PHP AJAX 핸들러 ==========
// 로그인 사용자용 + 비로그인 사용자용 모두 등록
add_action('wp_ajax_map_load_posts', 'map_ajax_load_posts');
add_action('wp_ajax_nopriv_map_load_posts', 'map_ajax_load_posts');
function map_ajax_load_posts() {
// 1. Nonce 검증
if (!check_ajax_referer('map_ajax_nonce', 'nonce', false)) {
wp_send_json_error(['message' => '보안 검증 실패'], 403);
}
// 2. 입력값 정리
$page = absint($_POST['page'] ?? 1);
// 3. 데이터 조회
$query = new WP_Query([
'post_type' => 'post',
'posts_per_page' => 6,
'paged' => $page,
]);
if (!$query->have_posts()) {
wp_send_json_error(['message' => '더 이상 글이 없습니다.']);
}
// 4. HTML 생성
ob_start();
while ($query->have_posts()) {
$query->the_post();
echo '<div class="post-card">';
echo '<h3>' . get_the_title() . '</h3>';
echo '<p>' . get_the_excerpt() . '</p>';
echo '</div>';
}
$html = ob_get_clean();
wp_reset_postdata();
// 5. 성공 응답
wp_send_json_success([
'html' => $html,
'total_pages' => $query->max_num_pages,
'current' => $page,
]);
}
AJAX 보안 체크리스트
1. Nonce 검증: 모든 AJAX 요청에서 nonce를 검증하세요. CSRF 공격을 방지합니다.
2. 권한 체크: 관리자 전용 기능이라면
3. 입력값 정화: $_POST, $_GET 값을 절대 그대로 사용하지 마세요. sanitize_* 함수로 정화합니다.
4. wp_ajax_nopriv: 비로그인 사용자에게 필요한 경우에만 등록하세요. 관리 기능은 wp_ajax_만 사용합니다.
2. 권한 체크: 관리자 전용 기능이라면
current_user_can()으로 권한을 확인하세요.3. 입력값 정화: $_POST, $_GET 값을 절대 그대로 사용하지 마세요. sanitize_* 함수로 정화합니다.
4. wp_ajax_nopriv: 비로그인 사용자에게 필요한 경우에만 등록하세요. 관리 기능은 wp_ajax_만 사용합니다.
🔒
여기까지는 미리보기입니다
AJAX & REST API 엔드포인트
무료 가입하면 이어서 볼 수 있고, 강의를 완료할 때마다 XP와 레벨이 쌓입니다.
Google로 3초 만에 시작 →🧵 Threads로 시작무료 공개 강의 둘러보기 (Lv.1~3)무료 가입하면 이어서 볼 수 있고, 강의를 완료할 때마다 XP와 레벨이 쌓입니다.