Word Cracker의 잡다한 정보 모음

XE에서 워드프레스로 마이그레이션하기

8

XE에서 워드프레스로 마이그레이션(이전)하기

XE에서 워드프레스로 이전하는 작업을 주말 동안 진행했습니다.

다행히 Happist님의 도움으로 생각보다 수월하게 이전 작업을 완료할 수 있었습니다.

저는 이번 작업을 통해 다음 항목을 워드프레스로 옮겼습니다.

  • 글(Post)
  • 댓글
  • 회원 리스트
  • 조회수
  • 카테고리
  • 댓글
  • 이미지(썸네일 생성)

본격적인 이전 작업을 하기 전에 먼저 phpMyAdmin에 접속하여 XE와 워드프레스 테이블을 비교, 분석하여 체계적인 계획을 세워서 진행하면 시행착오를 줄이고 시간을 절약할 수 있을 것입니다.

글 이전하기

글을 이전할 경우 XE의 xe_documents 테이블에 있는 컨텐츠를 워드프레스의 wp_posts 테이블로 복사하는 방식으로 진행했습니다. 이 두 테이블을 대강 비교해보면 다음과 같이 도표로 나타낼 수 있습니다.

XE와 워드프레스 테이블 비교

처음에 xe_documents 테이블의 구조를 wp_posts와 동일하게 구성한 다음 테이블 이름을 바꾸는 방법을 채택했습니다(즉, xe_documents를 wp_posts로 이름 변경). 이 경우 이전은 되지만 예상치 못한 몇 가지 오류가 발생했습니다. 그래서 처음부터 다시 시작하여 xe_documents의 컨텐츠를 wp_posts로 복사하는 방법으로 진행하니 제대로 되었습니다.

XE 사이트의 글 URL 구조가 http://www.example.com/category/1234 식으로 되어 있었습니다. 워드프레스 사이트에서도 그대로 URL을 유지하도록 이전했습니다. 이 경우 301 리디렉션을 사용할 필요가 없습니다.

특히 이전하려는 XE 사이트에 YouTube 동영상이 있는 카테고리가 있었는데, 이 카테고리 글에 포함된 YouTube는 글에 직접 삽입된 것이 아니라 다른 방법을 사용하여 추가된 것으로 보였습니다. XE를 사용해보지 않아서 정확한 내용은 모르겠지만, 사용자가 아마 별도의 필드에 YouTube 동영상 링크를 추가하면 본문에 YouTube가 표시되는 방식으로 작동하는 것으로 짐작되었습니다.

이 부분은 워드프레스에서 Advanced Custom Fields라는 플러그인을 사용하여 해결할 수 있었습니다.

글 슬러그가 깨지는 문제

글 ID를 글 slug에 복사하면 간단하지만, 글 슬러그에 글 제목이 표시되도록 하고 싶은 경우 글 제목을 글 slug에 복사해보면 인코딩이 맞지 않아서 글자가 깨집니다.

이 경우 다음과 같은 같은 코드를 만들어 테스트해보니 문제가 해결되었습니다.

add_action( 'the_post', 'wpse_94856_title_update' );

function wpse_94856_title_update( $post )
{
if ( empty ( $post->post_title ) )
return;

$temp_title = $post->post_title;
$new_title = urldecode($temp_title);
wp_update_post(
array (
'ID'         => $post->ID,
'post_name' => $new_title
)
);

// $post is passed by reference, so we update this property in real time
$post->post_name = $new_title;
}

글 목록이 새로고침되면 글 제목이 “XE에서 워드프레스로 마이그레이션하기!”이면 글 슬러그도 “XE에서 워드프레스로 마이그레이션하기!”와 같이 그대로 표시됩니다. 그런 다음 위 코드를 제거하고 목록을 새로 고침하면 “XE에서-워드프레스로-마이그레이션하기”처럼 제대로 글 slug가 업데이트됩니다. 중요한 것은 모든 글 목록을 한 번씩 로드해 주어야 위의 코드가 실행됩니다. (그럼 모든 글 목록을 한 페이지에 나열하는 코드를 하나 작성하면 되겠죠?)

* 주의: 위의 코드는 충분한 테스트를 거치지 않았기 때문에 예상치 못한 문제가 발생할 수 있습니다. 조건문을 post type으로 지정하면 더 좋은 결과를 얻을 것 같습니다.

이 문제를 Stackoverflow에 문의했는데 아무도 답변을 안 해주어서 포기하고 있었는데, 갑자기 방법이 생각이 나서 테스트해보니 잘 되네요.

썸네일 문제

이미지는 XE에 있는 것을 그대로 유지하고 썸네일(특성 이미지)을 새로 생성했습니다. 썸네일은 Happist님께 문의하여 글에 포함된 첫 번째 이미지를 특성 이미지(Featured Image)로 변환해주는 플러그인을 사용하는 방식을 택했습니다.

참고로 글 중에 src=”./files/attach/images/…” 식으로 이미지가 추가되어 있는 글이 있을 수 있습니다. 이런 경우 가급적 전체 URL로 바꾼 후에 진행하면 더 좋은 결과를 얻을 수 있을 것 같습니다.

UPDATE wp_posts SET post_content = REPLACE(post_content, './files/attach/images', 'http://www.example.com/files/attach/images')

카테고리/태그 이전

XE 사이트의 글 URL 구조가 http://www.example.com/category/1234 식으로 되어 있었습니다. category 부분이 워드프레스에서 생각하는 카테고리와는 약간 차이가 있는 것처럼 보입니다. XE 사이트에서 대분류 > 소분류의 개념으로 되어 있는 것 같고, URL에는 소분류에 해당하는 슬러그가 표시되었습니다.

이 부분은 워드프레스로 이전했을 경우를 가정했을 때 어떻게 하는 것이 바람직할 지를 생각했습니다. 워드프레스의 고유주소 설정을 “카테고리/글ID” 형식으로 지정하면 본래 XE 사이트의 URL과 동일하게 된다는 점에 착안하여 카테고리는 XE에서 소분류에 해당하는 것만을 기준으로 이전했습니다.

카테고리와 태그는 워드프레스에서 다음 세 가지 테이블과 관련이 있습니다.

  • wp_terms
  • wp_term_relationships
  • wp_term_taxonomy

자세한 내용은 WordPress Codex 문서를 참고하면 도움이 됩니다.

어떻게 XE의 카테고리와 매칭시킬까를 고민했습니다. 저는 xe_modules 테이블의 module_srl을 기준으로 하여 카테고리 데이터를 워드프레스로 복사했습니다.

태그는 xe_tags 테이블에서 tag_srl을 기준으로 삼았습니다. 조금 의외인 점은 동일한 태그에 대하여 tag_srl이 여러 개인 경우가 있어서 태그를 이전한 후에 동일한 태그에 대하여 slug가 달라지게 되었습니다.

중복되는 태그의 슬러그를 동일하게 바꾸고 싶다면 두 가지 작업을 해주면 될 것 같습니다(테스트는 하지 않았지만 별 문제 없이 될 것 같습니다).

  • 동일한 태그를 가지는 중복된 tag_srl을 삭제합니다. 이 경우 가장 낮은 값을 유지하면 될 것입니다. 이 작업은 “Delete all Duplicate Rows except for One in MySQL?” 글에 소개된 SQL 쿼리를 응용하면 됩니다.
  • 그런 다음 글에 포함된 중복되는 태그의 tag_srl을 비교하여 가장 낮은 tag_srl로 통일하도록 합니다. (만약 가장 낮은 tag_srl이 삭제되어 글에 나타나지 않는다면 문제가 발생할 것도 같습니다.)

회원 리스트 이전

회원 리스트의 경우 XE에서 일반 회원들이 글을 작성한 경우에 이전해주는 것이 좋을 듯 합니다. (그렇지 않으면 신규로 가입하는 회원에게 기존 회원의 ID가 부여되어 뜻하지 않게 신규 사용자가 기존 글의 작성자가 되는 문제가 발생할 것 같습니다.) 회원 정보를 이전시켜주더라도 문제는 usermeta 값을 설정하는 것은 엄두를 낼 수 없을 정도로 동일 사용자에 대하여 너무 많은 필드가 있기 때문에 모든 사용자에 대하여 ‘구독자’ 역할을 부여하는 것에 만족해야 했습니다.

xe_member의 회원 정보를 wp_users 테이블로 복사한 후에 xe_member 테이블에 두 개의 컬럼(meta_key, meta_value)를 만든 후에 xe_member 테이블에서 다시 wp_usermeta 테이블로 복사하는 방식으로 모든 사용자에 대하여 ‘구독자’ 역할을 부여했습니다.

UPDATE wp_usermeta SET meta_value = 'a:2:{s:10:"subscriber";b:1;s:15:"bbp_participant";b:1;}' where meta_value = 'a:1:{s:10:"subscriber";b:1;}'

추가 고려 사항

XE에서 게시판 형식으로 된 카테고리의 경우 워드프레스로 이전한 후에 List category posts와 같은 플러그인을 사용하여 리스트 형식으로 표시할 수 있습니다.

또는, 특정 카테고리의 템플릿 파일을 수정하여 게시판 형식으로 글을 표시하는 것도 가능합니다.

참고: XE의 특정 카테고리를 케이보드 게시판으로 이전하는 것도 가능할 것 같습니다. 저는 XE에서 워드프레스 글로 이전한 후에, 워드프레스의 특정 카테고리를 케이보드로 이전하는 작업을 해보니 의외로 카테고리에서 케이보드로 이전하는 것이 어렵지 않은 것을 느낄 수 있었습니다.

테스트 사이트 구성

저는 테스트 사이트를 구성하여 테스트 사이트에서 이전 테스트를 하고 완료한 후에 본래 사이트에 이전시켰습니다. 문제는 데이터 용량이 5GB가 넘어가서 테스트 사이트를 구성하느라 애를 먹었습니다. 파일을 다운로드받는 데 6시간이 걸렸고, 이것을 테스트 사이트에 올리는 데 또 그 정도의 소요되어 테스트 사이트를 준비하는 데 하루가 걸렸습니다.ㅎㅎ

그리고 DB의 크기도 150MB가 넘어가서 phpMyAdmin을 통해 Import하느라 조금 시간이 걸렸습니다. 데이터 용량이 워낙 크기 때문에 무제한 공간과 트래픽을 제공하는 iPage의 공유 호스팅을 사용했습니다. 공유 호스팅이라 SSH를 지원하지 않습니다. 처음에 DB를 분할하여 Import하는 데 40분 이상이 걸렸습니다. 중간에 모두 갈아엎고 새롭게 시도하기로 하고 DB를 모두 삭제하고 다시 Import해야 하는 상황이 발생했습니다. 시간이 제법 걸리기 때문에 시간을 절약하기 위해 DB를 FTP에 올려놓고 iPage에 연락하여 DB를 Import해 달라고 요청했습니다. 친절하게도 DB를 임포트해 주었지만 실제로 살펴보니 일부 테이블이 누락되어 있었습니다. (역시 공짜는 없는가 봅니다.ㅠㅠ) 그래서 어쩔 수 없이 수동으로 phpMyAdmin에 가져오기(Import)하여 테스트를 실시했습니다.

다만 아쉬운 점은 테스트 사이트에서 이전을 완료한 후에 실제 사이트로 DB를 옮기는 과정에서 조금 애를 먹었습니다. 실제 사이트가 카페24에서 호스팅되고 있었는데, DB 업로드 용량이 21MB 정도네요. 이 설정을 높여보려고 노력했지만 잘 안 되어 DB를 분할하여 이전을 시도했습니다. 하지만 이상한 오류가 나면서 실패했습니다. 어쩔 수 없이 테이블별로 나누어서 이전을 하는 바람에 시간이 제법 걸렸습니다. 또, 조회수가 저장된 테이블은 오류가 발생하여, 그 부분은 나머지 테이블을 옮긴 후에 해당 글 카운터 플러그인을 설치하고 다시 데이터를 이전하는 과정을 실시했습니다.

이전 후 카테고리/태그/댓글 개수가 제대로 표시되지 않는 경우

XE에서 워드프레스 이전하고 카테고리와 태그가 포함된 글 개수가 제대로 표시되지 않고 모두 “0”으로 표시되는 문제가 발생했습니다. 이 경우 다음 코드를 실행하면 카테고리/태그 개수가 올바르게 표시됩니다.

<?php
include("wp-config.php");
if (!mysql_connect(DB_HOST, DB_USER, DB_PASSWORD)) {  die('Could not connect: ' . mysql_error());  }
if (!mysql_select_db(DB_NAME)) {  die('Could not connect: ' . mysql_error());  }

$result = mysql_query("SELECT term_taxonomy_id FROM ".$table_prefix."term_taxonomy");
while ($row = mysql_fetch_array($result)) {
$term_taxonomy_id = $row['term_taxonomy_id'];
echo "term_taxonomy_id: ".$term_taxonomy_id." count = ";
$countresult = mysql_query("SELECT count(*) FROM ".$table_prefix."term_relationships WHERE term_taxonomy_id = '$term_taxonomy_id'");
$countarray = mysql_fetch_array($countresult);
$count = $countarray[0];
echo $count."<br />";
mysql_query("UPDATE ".$table_prefix."term_taxonomy SET count = '$count' WHERE term_taxonomy_id = '$term_taxonomy_id'");
}

$result = mysql_query("SELECT ID FROM ".$table_prefix."posts");
while ($row = mysql_fetch_array($result)) {
$post_id = $row['ID'];
echo "post_id: ".$post_id." count = ";
$countresult = mysql_query("SELECT count(*) FROM ".$table_prefix."comments WHERE comment_post_ID = '$post_id' AND comment_approved = 1");
$countarray = mysql_fetch_array($countresult);
$count = $countarray[0];
echo $count."<br />";
mysql_query("UPDATE ".$table_prefix."posts SET comment_count = '$count' WHERE ID = '$post_id'");
}
?>
출처: wpbeginner

스크립트를 실행한 후 삭제하도록 합니다.

마치며

이번 작업을 하면서 MySQL의 활용법에 대해 배울 수 있는 계기가 되었습니다. 책을 통해 익힌 내용을 실전에 적용하는 방법을 익힌 것이 큰 성과라면 성과라 할 수 있습니다. 또, 워드프레스 구조에 대해 조금 더 알 수 있는 기회가 된 것 같습니다.

추가

제로보드에서 워드프레스로 이전하려는 경우에는 제로보드에서 XE로 먼저 변환한 다음에 워드프레스로 이전을 시도하면 됩니다. 제로보드에서 XE로 바꾸는 방법은 구글 검색을 통해 쉽게 확인이 가능합니다.

아래 댓글에도 나와 있듯이 기본적으로 다음과 같은 프로세스를 따르게 됩니다.

  1. export table data to SQL statements
  2. if necessary, modify SQL statements to allow import
  3. import modified SQL statements to new database
  4. run table transformation (DDL) scripts on new database
  5. append data in transformed table to existing table

마찬가지 방식으로 XE나 워드프레스의 특정 카테고리를 케이보드(Kboard) 게시판으로 이전이 가능합니다. 직접 이전을 실시해보면 몇 가지 고려해야 할 사항이 발생하는데, 그런 경우 SQL에 대해 조금 알면 도움이 될 것입니다.

DB 작업은 위험하기 때문에 반드시 백업을 실시한 다음에 진행하시기 바랍니다.

이런 작업에 어려움을 겪는 경우 여기에서 서비스(유료)를 의뢰하실 수 있습니다.

참고할 만한 사이트:

유용한 앱:

Related Posts

Comments