※ 아직 초보이기 때문에 쿼리 부하나 사이트 속도에 관해서는 고려하지 않았습니다. 대형 사이트나 이용자가 많은 사이트를 운영 중이신 분들께는 아래의 모듈 수정 방법을 추천드리고 싶지 않습니다. 기존의 모듈이 이미 훌륭하기 때문에 꼭 필요한 분이 아닌 이상 기존의 모듈을 그대로 사용하시는 걸 추천드립니다.

 

※ 문제가 있거나 개선할 수 있는 부분이 있으시면 언제든지 말씀해주세요. 환영합니다.

 

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시간으로 잡아놓았습니다.

아래는 위젯 사용 이미지입니다.

 

20180730_2.jpg

 

다행히 제가 운영하는 사이트는 이용자도 적고 서버 사양도 넉넉한 편이라서 일 주일간 적용해본 결과 아직까지 큰 문제는 없는 것 같습니다.

그러나 좀 더 이용자가 많고 서버 사양이 넉넉치 않은 사이트라면 부담이 많이 갈 것 같습니다.

알아보니까 필드에서 count 하는 게 CPU 부하가 꽤 심하다고 하더군요...

  • profile

    살짝 이해가 안가는게... 기간범위는 컨텐츠확장위젯에서 제공되는 옵션 아닌가요??? 왠만한 상용 위젯에는 이 조건이 옵션으로 있구요...

  • profile ?
    제가 컨텐츠 확장위젯을 써보지 않아서 구체적으로 어떤 말씀인지 잘 이해를 못했습니다. 죄송합니다.
    기간에 따른 인기글 위젯이 기존에도 있지 않느냐를 말씀하시는 거라면... 그 기간 내에 게시된 게시글 중에서 가장 조회수가 높은 글들을 출력하기 때문에 사용자들이 특정 기간 전에 올라온 게시글을 많이 읽었다면 그 이전에 본 게시글은 위젯에 반영이 안됩니다. 그래서 위와 같이 조회 이력 모듈을 활용하여 제작해봤습니다.
    제가 질문을 잘 이해를 못해서... 한 번 컨텐츠 확장 위젯을 설치해보고 다시 말씀드리겠습니다. 죄송합니다.
  • profile

    제가 난독증이 있었나 보네요.

    그럼 혹시 특정 기간에 읽혀진 게시글 또는 추천된 게시글 이런 개념으로 접근 하신거군요?
    요것도 마켓에 판매되는 자료가 있긴 합니다.

    XE마켓에 찾아보니 지금은 자료가 내려간거 같네요.

    어쩐지 제가 처음에 이해가 안갔던 부분이 잘못 읽었던 것 같습니다.

    기간범위가 작성일자 기준이 아니고 읽혀지거나 추천되거나 하는 일시를 말씀 하시는 것 같네요.

     

    지금 가장 인기있는 게시글~ 요런 의미겠네요.

  • profile ?

    아 네 맞습니다.

    제가 운영하는 사이트는 커뮤니티 사이트가 아니어서 1~2년 전에 올라온 글들을 접속자들이 읽는 경우가 많은데, 기존에 있던 위젯으로 일간/주간/월간 조회 수가 많은 게시글을 출력하고자 하면 그 기간 내에 올라온 글들 중에서 조회수가 높은 글들을 출력하기 때문에 제가 원하던 것을 구현하기가 어려웠습니다.

    마켓에 판매되는 자료가 있다니 다행이네요. 더 안정적인 자료가 있으면 그걸 쓰는 게 더 나을 것 같습니다.

    아 그렇군요... 그러면 당분간은 조회 모듈을 활용하는 방법밖에는 없을 것 같습니다.


    네 말씀하신대로 작성일자 기준이 아니라 말 그대로 '조회한 일시'를 말씀드리고 싶었습니다. 감사합니다.