케이보드 마이그레이션 플러그인을 사용하여 그누보드 게시판 글들을 워드프레스 Kboard 게시판으로 이전한 글들이 워드프레스 검색 기능으로 검색되지 않는 문제로 며칠 동안 고생했습니다. 처음에는 KBoard(케이보드) 자체 검색 프로그램을 커스텀하여 통합 검색이 가능하다는 말을 듣고 삽질을 열심히 하여 검색이 가능하도록 만들었습니다. 하지만 엘리멘터 프로의 검색 결과(Search Results) 템플릿으로 구현된 검색 페이지에서 케이보드 게시글이 검색되지 않는 문제가 나타났습니다.
케이보드 글들이 엘리멘터의 검색 시스템으로 검색되도록 또 열심히 작업하여 겨우 성공할 수 있었습니다. 그러나 게시글이 너무 많아서 검색 속도고 너무 느렸습니다. 이 문제를 또 해결하느라 시간이 추가로 들었습니다.
케이보드 게시글이 워드프레스 검색 시스템이나 엘리멘터 검색 기능, 또는 커스텀 포스트 타입을 지원하는 검색 플러그인에서 검색이 되지 않는 경우 참고해보세요.
Kboard 게시글이 검색되지 않는 문제 (검색 옵션 일괄 변경)
워드프레스 케이보드 게시판에서 글을 작성하면 워드프레스 기본 검색 시스템과 검색 플러그인에서 검색이 됩니다.
하지만 마이그레이션 플러그인을 사용하여 그누보드나 XE, 제로보드 등에서 이전한 경우 워드프레스 검색 기능으로 검색이 안 될 수 있습니다.
kboard_list_where 필터를 사용하여 검색되도록 커스텀하기
이 문제에 대하여 Kboard 관계자는 kboard_list_where 필터를 사용하는 방법을 안내하고 있습니다.
kboard_list_where 필터를 사용하여 억지로 검색이 되도록 할 수는 있지만, 코드를 만드는 것이 쉽지 않고, 특히 힘들게 만든 코드를 적용해도 엘리멘터 페이지 빌더와 연동이 안 될 수 있습니다.
저는 이 필터를 사용하여 겨우 케이보드 게시글이 검색되도록 했지만, 엘리멘터 검색 결과 페이지와 연동이 되지 않았습니다.
원인을 파악하다
무슨 일이던 마찬가지겠지만 문제를 해결하려면 원인을 파악하는 것이 중요합니다. 증상에 대하여 일일이 대응하다 보면 소 뒷걸음질 치다 쥐 잡듯이 문제가 해결될 수도 있지만, 하나를 해결하면 또 다른 문제가 발생할 수 있습니다.
신규 글은 검색이 되지만, 다른 CMS의 게시판에서 이전한 글들은 검색이 되지 않는 것이 이상하여 DB에서 기존 글과 신규 글을 비교해 보았습니다. 둘 사이에는 한 가지 차이점이 있었습니다. 신규로 작성된 게시글은 wp_kboard_board_content 테이블에서 search 컬럼의 값이 "1"이었지만, 검색이 되지 않은 게시글들의 경우 search 컬럼 값이 "3"이었습니다.

search 값이 3일 경우 Kboard 플러그인 파일 소스를 체크해보니 deletePost() 함수가 실행되도록 되어 있었습니다.
if($post_id){
if($data['search'] == 3){
$this->deletePost($post_id);
}
else{
$this->updatePost($post_id, $data['member_uid']);
}
}
이 때문에 search = 3인 게시글들은 워드프레스 기본 검색 시스템에서 검색이 되지 않은 것으로 보입니다. (참고로 글 작성 시 비밀글 옵션을 체크하면 search 값이 2로 지정되는 것 같습니다.)
간단하게 DB에서 search = 3을 search = 1로 바꾸면 문제가 해결될 것이 아니겠는가? 이렇게 생각할 수 있을 것입니다. 저도 그렇게 생각했지만, 데이터베이스에서 일괄 변경한다고 해서 다시 검색되지는 않았습니다. 참고로 다음 SQL 쿼리를 실행하여 search = 3일 경우 일괄적으로 1로 변경할 수 있습니다.
UPDATE wp_kboard_content
SET search = 1
WHERE search = 3;
그리고 기존 글을 수동으로 업데이트하면 검색이 되었지만, DB에서 업데이트 날짜를 현재 날짜로 수정하면서 업데이트해도 마찬가지로 검색에 반영되지는 않았습니다.
이 문제를 검색해보니 지난 4월에 Kboard 포럼에 동일한 증상에 대하여 질문을 한 분이 계시네요.
이전 게시물을 kboard로 일괄 이전했는데, 통합 검색 옵션이 검색 제외로 들어왔습니다. (search = '3')
통합검색을 제목과 내용 검색으로 일괄 변경하려 합니다. (search = '1')
DB에서 wp_kboard_board_content 의 search를 1로 변경했는데 바로 적용되지 않고 일일히 글수정을 해줘야 합니다.
혹시 일괄 글 업데이트 등의 기능이 있을지요?
케이보드 담당자분은 여기에 대하여 SQL문을 사용하여 DB를 수정해 주어야 한다는 답변을 하고 있습니다.

phpMyAdmin 등 MySQL 클라이언트 툴에서 SQL 쿼리를 사용하여 일괄적으로 수정하는 경우에는 검색 색인에 포함되지 않을 것 같습니다.
글을 수동으로 업데이트하면 색인에 추가되는 것으로 보아서 글을 업데이트할 때 어떤 메커니즘에 의해 검색되도록 바뀌는 것으로 보입니다.
이를 알기 위해서는 케이보드 플러그인을 분석해야 하지만 쉽지 않습니다. 이와 관련해서는 /wp-content/plugins/kboard/class 디렉터리 아래의 KBContent.class.php 파일을 분석하면 힌트를 얻을 수 있을 것입니다.
여러 가지 코드를 만들어 테스트해보았지만, 게시글이 너무 많아서 실행 도중에 504 Gateway Timeout 에러가 발생하였습니다. 서버 리소스를 충분히 크게 늘려도 마찬가지 증상이 나타났습니다.
최종적으로는 모든 게시판 글에 대하여 Kboard 자체 함수인 updateContent() 함수를 실행하도록 코드를 작성했습니다. 실행은 100개씩 나누어서 진행되도록 하여 504 Gateway Timeout 에러나 메모리 제한 크기 초과로 인한 치명적인 오류가 발생하지 않도록 했습니다.
검색 옵션 일괄 변경하는 코드는 다음과 같습니다.
<?php
/*
Plugin Name: KBoard Update with KBContent
Description: Update all KBoard posts using KBContent class and set member_uid to 0.
Version: 2.2
Author: Your Name
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly.
}
// Include KBoard classes if not already included
if (!class_exists('KBContent')) {
include_once WP_CONTENT_DIR . '/plugins/kboard/class/KBContent.class.php';
}
function kboard_update_posts_with_kbcontent($batch_size = 100) {
global $wpdb;
$table_name = $wpdb->prefix . 'kboard_board_content';
// Get the last processed ID
$last_processed_id = get_option('kboard_update_last_id', 0);
$start_time = time();
$time_limit = 300; // 5 minutes execution time limit
$updated_count = 0;
while (true) {
$posts = $wpdb->get_results($wpdb->prepare(
"SELECT * FROM $table_name WHERE uid > %d ORDER BY uid ASC LIMIT %d",
$last_processed_id,
$batch_size
));
if (empty($posts)) {
break; // No more posts to process
}
foreach ($posts as $post) {
$content = new KBContent();
$content->initWithUID($post->uid);
if ($content->uid) {
// Update the 'update' field, ensure 'search' is set to 1, and set 'member_uid' to 0
$data = array(
'update' => date('YmdHis', current_time('timestamp')),
'search' => '1',
'member_uid' => 0
);
$result = $content->updateContent($data);
if ($result !== false) {
$updated_count++;
echo "Updated KBoard post UID: {$content->uid}<br>";
} else {
echo "Failed to update KBoard post UID: {$content->uid}<br>";
}
} else {
echo "Skipped invalid KBoard post UID: {$post->uid}<br>";
}
$last_processed_id = $post->uid;
flush();
// Check if we're approaching the time limit
if (time() - $start_time > $time_limit) {
break 2; // Break both foreach and while loops
}
}
// Update the last processed ID
update_option('kboard_update_last_id', $last_processed_id);
wp_cache_flush();
$wpdb->queries = array();
}
echo "<br>Total updated posts in this session: {$updated_count}<br>";
echo "Last processed ID: {$last_processed_id}<br>";
// Check if we've processed all posts
$remaining_posts = $wpdb->get_var("SELECT COUNT(*) FROM $table_name WHERE uid > $last_processed_id");
if ($remaining_posts == 0) {
echo "All posts have been processed!<br>";
delete_option('kboard_update_last_id');
} else {
echo "There are still approximately {$remaining_posts} posts to process.<br>";
}
}
// Create a menu item in the admin panel
function kboard_update_menu() {
add_management_page(
'KBoard Update',
'KBoard Update',
'manage_options',
'kboard-update',
'kboard_update_page'
);
}
add_action('admin_menu', 'kboard_update_menu');
// Display the update page
function kboard_update_page() {
?>
<div class="wrap">
<h1>KBoard Update</h1>
<p>This will update all KBoard posts using the KBContent class and set member_uid to 0.</p>
<form method="post" action="">
<?php wp_nonce_field('kboard_update_action', 'kboard_update_nonce'); ?>
<input type="submit" name="update_kboard_posts" class="button button-primary" value="Start/Resume Updating KBoard Posts">
<input type="submit" name="reset_update_process" class="button button-secondary" value="Reset Update Process" onclick="return confirm('Are you sure you want to reset the update process? This will start over from the beginning.');">
</form>
<div id="update-results">
<?php
if (isset($_POST['update_kboard_posts']) && check_admin_referer('kboard_update_action', 'kboard_update_nonce')) {
kboard_update_posts_with_kbcontent();
}
if (isset($_POST['reset_update_process']) && check_admin_referer('kboard_update_action', 'kboard_update_nonce')) {
delete_option('kboard_update_last_id');
echo "Update process has been reset. You can now start from the beginning.";
}
?>
</div>
</div>
<?php
}
여기서 고려해야 할 사항이 있습니다. 상기 코드에서는 업데이트 날짜를 현재 날짜로 업데이트합니다. 업데이트 날짜를 유지하고 싶은 경우 상기 코드를 적절히 변경하세요.
코드를 실행하기 전에 반드시 백업을 확실히 하시기 바랍니다.
검색 속도가 느린 문제
케이보드 게시글이 검색이 되도록 문제를 수정했지만, 문제가 완전히 해결된 것은 아니었습니다. 보통의 경우 문제가 없지만, 게시글 개수가 16만 개가 넘다 보니 검색에 시간이 제법 걸리는 또 다른 문제가 발생했습니다.

콘텐츠가 너무 많아서 검색 시 딜레이가 발생하는 경우 검색 색인을 만들면 빠르게 검색이 가능합니다.
Ajax Search 플러그인 등을 비롯한 여러 가지 검색 플러그인을 사용해도 검색 속도가 개선되지 않았습니다.
이 경우 Relevanssi라는 플러그인을 사용하면 검색할 게시물을 색인화하여 검색 속도를 획기적으로 높일 수 있습니다.
이 플러그인은 Elementor와 호환이 안 되었지만, 지금은 호환이 잘 되는 것 같습니다. 엘리멘터의 테마 빌더로 만든 검색 결과 템플릿을 사용할 때 검색 시 딜레이가 심했지만 이 플러그인을 사용하니 검색 속도가 크게 개선되었습니다.
Elementor Pro의 Theme Builder를 이용하면 검색 결과 페이지를 비롯한 헤더, 푸터, 카테고리 페이지 등 사이트의 거의 모든 섹션을 코딩 작업 없이 엘리멘터 빌더로 만들 수 있습니다.

Relevanssi 검색 색인 플러그인을 사용하면 검색 속도를 위해 기본적으로 3글자 이상 검색이 가능합니다. 고급 인덱싱 설정(Advanced indexing settings)에서 최소 단어 길이(Minimum word length)를 2자로 설정하는 것이 가능합니다.

블로그 포스트나 게시판 글 등이 너무 많아서 검색 속도가 느린 경우 이 플러그인의 사용을 고려해보시기 바랍니다.
댓글 남기기