[기술컬럼] KBoard 게시글이 저절로 삭제된다? “유령 삭제” 현상의 원인과 완벽 해결 가이드

[기술컬럼] KBoard 게시글이 저절로 삭제된다? “유령 삭제” 현상의 원인과 완벽 해결 가이드

워드프레스 사이트를 운영하다 보면 아주 드물게, “내가 지우지도 않았는데 게시글이 사라졌다”는 미스터리한 제보를 받을 때가 있습니다.

로그를 봐도 뚜렷한 에러가 없고, 재현하려고 하면 멀쩡한 이 현상.

KBoard 소스 코드 분석과 최신 웹 최적화 트렌드를 기반으로 이 ‘유령 삭제’ 현상의 3가지 핵심 원인과 해결책을 공개합니다.

 

원인 1. 범인은 ‘속도 최적화 플러그인’의 “링크 미리 불러오기(Preload)”

최근 제보된 가장 황당하면서도 치명적인 원인입니다. 혹시 WP-Rocket, Breeze, Flying Pages 같은 캐시/속도 최적화 플러그인을 사용 중이신가요?

🔍 발생 메커니즘

  1. 최신 최적화 플러그인에는 사용자가 링크에 마우스를 올리기만 해도(Hover) 해당 페이지를 미리 로딩하여 속도를 높이는 Link Preloading 기능이 있습니다.
  2. KBoard의 삭제 버튼은 전통적인 <a> 태그(링크) 방식으로 되어 있습니다. (?action=kboard_file_delete…)
  3. 관리자가 게시판 목록을 보다가 무심코 삭제 버튼 위로 마우스 커서가 스쳐 지나갑니다.
  4. 클릭하지 않았는데도 플러그인은 “사용자가 이 링크를 방문할 것”이라고 예측하여 백그라운드에서 삭제 URL을 호출해 버립니다.
  5. 결과: 클릭 없이 게시글이 삭제됩니다.

✅ 해결책

  • 사용 중인 캐시/속도 최적화 플러그인 설정에서 Preload Links (또는 Preload on Hover) 기능을 비활성화 하세요.
  • 이 기능만 꺼도 미스터리한 삭제 현상의 90%는 사라집니다.

 

원인 2. 좀비처럼 연결된 ‘답글 삭제’ 로직 (코드 분석 결과)

두 번째 가능성은 KBoard 내부의 ‘답글 연쇄 삭제’ 로직과 데이터베이스(DB) 오류의 콜라보레이션입니다.

🔍 코드 분석 (KBContent.class.php)

KBoard는 부모 글이 삭제되면 그 밑에 달린 답글도 함께 삭제되도록 설계되어 있습니다.

// KBContent.class.php 의 deleteReply 메소드
public function deleteReply($parent_uid){
    // 부모 UID를 가진 모든 글을 조회하여 강제 삭제
    $results = $wpdb->get_results("SELECT * FROM ... WHERE `parent_uid`='$parent_uid'");
    foreach($results as $row){
        $content->remove(false); // 자식 글 삭제 실행
    }
}

문제는 어떤 이유(DB 충돌, 엑셀 대량 등록 실수 등)로 인해 서로 관련 없는 게시글들의 parent_uid가 특정 번호로 잘못 묶여버리는 경우입니다. 이때 그 ‘숙주’가 되는 글 하나를 지우면, parent_uid로 잘못 연결된 수십, 수백 개의 멀쩡한 글들이 ‘답글’로 인식되어 순식간에 함께 삭제됩니다.

✅ 해결책

  • phpMyAdmin 등 DB 관리 툴에서 kboard_board_content 테이블을 확인하세요.
  • parent_uid 컬럼에 비정상적으로 많은 글이 묶여 있는지 무결성을 체크해야 합니다.

 

원인 3. 워드프레스 ‘휴지통’ 청소부의 오해

KBoard는 워드프레스 기본 검색에 노출되기 위해 wp_posts 테이블에도 데이터를 동기화합니다. 하지만 WP-OptimizeWP-Sweep 같은 DB 정리 플러그인이 KBoard가 생성한 포스트를 “연결되지 않은 고아 데이터(Orphaned Post)”로 오인하여 청소해버리는 경우가 있습니다.

✅ 해결책

  • DB 정리 플러그인을 돌릴 때는 kboard 포스트 타입은 제외하거나, 자동 청소 스케줄링을 주의해서 설정해야 합니다.

 

🛡️ 범인 추적을 위한 특급 처방, 삭제 로그 남기기

원인을 확실히 잡고 싶다면, 누가 언제 삭제했는지 기록을 남기는 것이 최선입니다. 아래 코드를 테마의 functions.php 파일에 추가하면, 게시글이 삭제될 때마다 범인을 기록해 줍니다.

/* KBoard 삭제 로그 기록 (functions.php에 추가) */
add_action('kboard_document_delete', 'my_kboard_delete_tracker', 10, 4);
function my_kboard_delete_tracker($content_uid, $board_id, $content, $board){
    $user = wp_get_current_user();
    $time = current_time('mysql');
    $ip = $_SERVER['REMOTE_ADDR'];
    $url = $_SERVER['REQUEST_URI'];
    
    // 로그 내용 : [시간] 글번호 | 삭제자ID | IP | 요청URL
    $log = "[{$time}] UID:{$content_uid} (Board:{$board_id}) | User:{$user->user_login} | IP:{$ip} | URL:{$url}\n";
    
    // wp-content/uploads/kboard_delete_log.txt 파일에 저장
    $upload_dir = wp_upload_dir();
    $logfile = $upload_dir['basedir'] . '/kboard_delete_log.txt';
    file_put_contents($logfile, $log, FILE_APPEND);
}

이제 /wp-content/uploads/kboard_delete_log.txt 파일을 확인해보세요.

만약 내가 클릭하지도 않았는데 로그가 쌓인다면?

“원인 1번(플러그인 프리로드)”이 확실합니다.

 

KBoard의 버그가 아니라, 너무 똑똑해진 최적화 플러그인의 과잉 친절이거나 데이터 꼬임일 확률이 높습니다. 위 3가지만 점검하시면 귀신의 장난 같던 삭제 현상은 멈출 것입니다.