※ 아직 초보이기 때문에 쿼리 부하나 사이트 속도에 관해서는 고려하지 않았습니다. 대형 사이트나 이용자가 많은 사이트를 운영 중이신 분들께는 아래의 모듈 수정 방법을 추천드리고 싶지 않습니다. 기존의 모듈이 이미 훌륭하기 때문에 꼭 필요한 분이 아닌 이상 기존의 모듈을 그대로 사용하시는 걸 추천드립니다.
※ 문제가 있거나 개선할 수 있는 부분이 있으시면 언제든지 말씀해주세요. 환영합니다.
XE에서 인기 게시글 위젯이 존재하기는 하지만, 아쉽게도 이러한 위젯들은 전체 조회 수를 기준으로 인기글을 조회합니다. 그래서 특정 기간동안 이용자들이 조회한 인기 게시글을 볼 수 없습니다.
물론 주간 / 월간 인기글 위젯도 존재하나 이는 특정 기간에 올라온 게시 날짜의 글들만을 기준으로 인기글을 조회하는 것이기에 완전한 인기글 위젯으로 보기는 어렵죠.
이를 어떻게 해결할까 고민하다가 운이 좋게도 sejin7940님께서 남겨주신 댓글(https://xe1.xpressengine.com/forum/22734346 )과 날아라님께서 제작하신 사이트 운영관리모듈의 게시글 조회 모니터링에서 아이디어를 얻었습니다. sejin7940님과 날아라님께 감사드립니다.
참고로 사이트 운영관리모듈은 꽤 많은 포인트를 지불해야 다운로드가 가능하지만 그만큼의 가치를 충분히 하는 것 같습니다. 활용도도 정말 좋고요. 포인트 때문에 망설이신다면 다운로드 받으시는 걸 적극 추천합니다.
게시글 조회 모니터링은 사용자가 어떠한 게시글을 읽었는지 DB에 기록합니다. 그런데 여기서 한 가지 문제가 되는 것은 최근 사용자가 읽은 게시글이 이미 다른 사용자가 읽은 게시글일 경우 이전에 읽었던 이력을 지우고 새롭게 읽은 내역으로 업데이트한다는 것입니다.
또한 이 모듈은 회원가입이 된 사용자의 글 읽은 내역만 기록된다는 특징이 있는데, 제가 운영하는 사이트는 비회원 이용자 활동이 중심이어서 이 부분도 같이 수정을 했습니다.
sitemanagement.controller.php 파일 252번째 줄의 triggerUpdateReadedCountBefore 함수 수정
function triggerUpdateReadedCountBefore(&$obj){ //문서 조회기록 있는지 확인 $args = new stdClass(); $args->document_srl = $obj->document_srl; //$doc_read_history = executeQuery('sitemanagement.docRead_get',$args)->data['1']; // Pass if read count is increaded on the session information if(isCrawler() || $_SESSION['readed_document'][$args->document_srl]) return false; //회원정보 구함 $logged_info = Context::Get('logged_info'); /*if($logged_info) $args->member_srl = $logged_info->member_srl;*/ // 2018-04-11 비회원만 조회 기록 if(!$logged_info){ //db처리 /*if($doc_read_history){ executeQuery('sitemanagement.docRead_update',$args); // 2018-04-11 문서 조회기록 있으면 업데이트되는 기능 삭제 }else{*/ //추가 변수정리 $args->module_srl = $obj->variables['module_srl']; $args->title = $obj->variables['title']; executeQuery('sitemanagement.docRead_insert',$args); //문서 조회기록 없으면 db입력 //} } }
그러면 게시글 조회 모니터링에 사용자가 조회한 게시글의 이력이 남습니다.
그 다음 위젯을 만들기 위해 DB에서 뽑아오는 쿼리 xml을 짰습니다.
쿼리의 효율이나 서버 부하 문제는 고려 못했습니다. 혹시 문제가 되는 부분이라면 말씀해주시면 감사하겠습니다.
<query id="getBestReadDocuments" action="select"> <tables> <table name="sitemanagement_doc_read" /> </tables> <columns> <column name="document_srl" /> <column name="title" /> <column name="count(*)" alias="count" /> </columns> <conditions> <condition operation="notin" column="sitemanagement_doc_read.module_srl" default="0" pipe="and" /> <condition operation="in" column="sitemanagement_doc_read.module_srl" var="module_srl" filter="number" notnull="notnull" pipe="and" /> <condition operation="more" column="sitemanagement_doc_read.regdate" var="regdate" default="curdate()" filter="number" notnull="notnull" pipe="and" /> </conditions> <groups> <group column="sitemanagement_doc_read.document_srl" /> </groups> <navigation> <index var="sort_index" default="count" order="desc" /> <list_count var="list_count" default="8" /> <page_count var="page_count" default="1" /> <page var="page" default="1" /> </navigation> </query>
마지막으로 이를 위젯에 적용해봤습니다. 위젯 코드는 공개가 어려울 것 같아서 추가한 부분만 올려놓겠습니다.
$obj->regdate에 인기글을 추출하고자 하는 특정 기간만큼을 저장하시면 됩니다.
지금으로부터 일 주일 전까지의 인기글을 추출한다면
$obj->regdate = date("Ymdhis", strtotime('-1 week')); 이런 식으로 활용하시면 될 것 같습니다.
아래는 30일 동안의 인기글을 추출한 것입니다.
{@ $obj->regdate = date("Ymdhis", strtotime('-1 month')); $month_read_document_list = executeQueryArray('widgets.content_box.getBestReadDocuments', $obj); }
서버 부하가 꽤 될 것 같아서 위젯 캐시 시간은 굉장히 길게 6시간으로 잡아놓았습니다.
아래는 위젯 사용 이미지입니다.
다행히 제가 운영하는 사이트는 이용자도 적고 서버 사양도 넉넉한 편이라서 일 주일간 적용해본 결과 아직까지 큰 문제는 없는 것 같습니다.
그러나 좀 더 이용자가 많고 서버 사양이 넉넉치 않은 사이트라면 부담이 많이 갈 것 같습니다.
알아보니까 필드에서 count 하는 게 CPU 부하가 꽤 심하다고 하더군요...
살짝 이해가 안가는게... 기간범위는 컨텐츠확장위젯에서 제공되는 옵션 아닌가요??? 왠만한 상용 위젯에는 이 조건이 옵션으로 있구요...