전에도 한번 이런 글(https://xetown.com/qna/559820)을 쓴 적이 있는데, 실패와 고난과 좌절의 연속이네요ㅠ

아직은 절반의 성공, 또는 절반의 실패쯤이라고 할 수 있는데,

반쯤은 하소연, 반쯤은 자랑 삼아 글 하나 남겨봅니다.

 

 

대댓글만 따로 불러내기 위해, 우선 댓글단에서 (대댓글이 아닌) 최상위 댓글만 모아서 리스트로 만들었었습니다.

일단 아래처럼 쿼리를 짜고, 게시판 스킨에 queries폴더를 만들어 그 안에 넣었죠.

 

원댓글 개수 구하는 쿼리,

<query id="getCommentCountByDepth0" action="select">
    <tables>
        <table name="comments_list" />
    </tables>
    <columns>
        <column name="count(*)" alias="count" />
    </columns>
    <conditions>
        <condition operation="equal" column="comments_list.document_srl" var="document_srl" filter="number" pipe="and" />
        <condition operation="equal" column="comments_list.depth" default="0" pipe="and" />
    </conditions>
</query>

그리고 리스트를 불러오는 쿼리도 만들어 넣었습니다.

<query id="getCommentPageListByDepth0" action="select">
    <tables>
        <table name="comments" alias="comments" />
        <table name="comments_list" alias="comments_list" />
    </tables>
    <columns>
        <column name="comments.*" />
        <column name="comments_list.depth" alias="depth" />
    </columns>
    <conditions>
        <condition operation="more" column="comments.status" var="status" pipe="and" />
        <condition operation="equal" column="comments_list.document_srl" var="document_srl" notnull="notnull" pipe="and" />
        <condition operation="equal" column="comments_list.comment_srl" var="comments.comment_srl" filter="number" pipe="and" />
        <condition operation="more" column="comments_list.head" default="0" pipe="and" />
        <condition operation="equal" column="comments_list.depth" default="0" pipe="and" />
    </conditions>
    <navigation>
        <index var="list_order" default="comments_list.head" order="desc" />
        <list_count var="list_count" default="list_count" />
        <page_count var="page_count" default="10" />
        <page var="page" default="1" />
    </navigation>
</query>

 

_comment.html 파일에서는 위에서 만든 최상위의 원댓글 리스트에 다음과 같이 commentItem()을 집어넣고(얘가 있어야 프로필 이미지 같은 걸 손쉽게 가져올 수 있거든요) 페이지네이션도 재정렬을 했습니다.

{@
    $oModuleModel = getModel('module');
    $comment_config = $oModuleModel->getModulePartConfig('comment',$module_info->module_srl);
    $query_path = $module_info->module.'/skins/'.$module_info->skin;

    $args = new stdClass();
    $args->document_srl = $oDocument->document_srl;
    $ccbd = executeQuery($query_path.'.getCommentCountByDepth0', $args);
    if(Context::get('cpage')):
        $cpage = Context::get('cpage');
    else:
        if(!$mi->cmt_lst):
            $cpage = 1;
        else:
            $cpage = (int)(($ccbd->data->count-1)/$comment_config->comment_count)+1;
        endif;
    endif;
    $args->list_count = $comment_config->comment_count; // 게시판 관리 페이지에서 설정한 페이지당 댓글 개수
    $args->page = $cpage;
    if(!$mi->cmt_pg):
        $args->page_count = 5;
    else:
        $args->page_count = $mi->cmt_pg;
    endif;

    $output = executeQuery($query_path.'.getCommentPageListByDepth0', $args);
    foreach($output->data as $key => $val):
        $oCommentItem = new commentItem();
        $oCommentItem->setAttribute($val);
        $comment_list[$val->comment_srl] = $oCommentItem;
    endforeach;

    if($output->total_page>1) $oDocument->comment_page_navigation = $output->page_navigation;
}

이렇게 만든 $comment_list 변수를 반복문으로 돌림으로써, 보통의 댓글단에서처럼 목록을 구성할 수 있게 됐습니다.

 

보통은 대댓글이 나오다가 중간 페이지가 넘어가고 그러잖아요?

그치만 이렇게 하면 페이지 나눔의 기준이 원댓글로 list_count되는 것이 장점인 것 같아요ㅎㅎ

즉, 목록이 최상위 댓글로만 이뤄졌다는 점이 일반 댓글 목록과 다른 점이죠.

여기까지는 무사히 성공!

 

그럼, 대댓글들은 어디로 가는가...

이른바 대댓글 접기, 또는 대댓글 감추기라고 하죠.

(1)대댓글 목록은 접어놓고, (2)원댓글 부분에 '답글(n)'처럼 보이게 링크를 만든 뒤, (3)링크를 클릭하면 대댓글 목록을 보게 할 수 있습니다.

 

우선 원댓글에 딸려 있는 대댓글들의 개수를 구하는 쿼리를 짜서 마찬가지로 새로 만든 quaries 폴더에 넣었습니다.

<query id="getDescendantCommentCount" action="select">
    <tables>
        <table name="comments_list" />
    </tables>
    <columns>
        <column name="count(*)" alias="count" />
    </columns>
    <conditions>
        <condition operation="equal" column="comments_list.head" var="comment_srl" filter="number" pipe="and" />
        <condition operation="more" column="comments_list.depth" default="1" pipe="and" />
    </conditions>
</query>

여기서 head는 원댓글의 comment_srl이기도 한데, parent_srl이 대댓글의 바로 직전 부모 댓글의 번호라면, head는 (댓글 depth와 상관없는) 최초의 시조 댓글의 번호더군요.

그래서 이걸로 count를 구하는 쿼리를 짜본 겁니다.

실사용할 때는 (원댓글의 head까지도 포함하기 때문에) 1을 뺄셈해줘서 사용하면, 원댓글에 딸린 전체 대댓글들의 개수가 됩니다.

 

그리고 이번에는 원댓글과 head를 공유하는 대댓글들만 모으는 리스트를 위해 쿼리 하나를 더 짰습니다.

<query id="getDescendantCommentList" action="select">
    <tables>
        <table name="comments" alias="comments" />
        <table name="comments_list" alias="comments_list" />
    </tables>
    <columns>
        <column name="comments.*" />
        <column name="comments_list.depth" alias="depth" />
        <column name="comments_list.head" alias="head" />
    </columns>
    <conditions>
        <condition operation="more" column="comments.status" var="status" pipe="and" />
        <condition operation="equal" column="comments_list.comment_srl" var="comments.comment_srl" filter="number" pipe="and" />
        <condition operation="equal" column="comments_list.head" var="comment_srl" filter="number" pipe="and" />
        <condition operation="more" column="comments_list.depth" default="1" pipe="and" />
    </conditions>
    <navigation>
        <index var="list_order" default="comments_list.comment_srl" order="asc" />
        <list_count var="list_count" default="list_count" />
        <page_count var="page_count" default="10" />
        <page var="page" default="1" />
    </navigation>
</query>

depth가 1 이상인 댓글만 수집하므로, head 번호가 같더라도 원댓글은 목록에서 빠지게 돼죠.

 

그리고 현재 이 쿼리로 만든 리스트는 _comment.html의 적당한 위치에 아래처럼 넣어서 잘 사용하고 있습니다.

{@
    $args = new stdClass();
    $args->comment_srl = $comment->comment_srl;
    $dcc = executeQuery($query_path.'.getDescendantCommentCount', $args); // $dcc->data->count로 자손 댓글의 개수를 표현하는 게 가능해집니다.
}

{@
    $args = new stdClass();
    $args->document_srl = $oDocument->document_srl;
    $args->comment_srl = $comment->comment_srl;
    $args->list_count = $dcc->data->count;
    $args->page = 1;
    $args->page_count = 5;

    $o_output = executeQuery($query_path.'.getDescendantCommentList', $args);
    $o_comment_list = [];
    foreach($o_output->data as $key => $val):
        $oCommentItem = new commentItem();
        $oCommentItem->setAttribute($val);
        $o_comment_list[$val->comment_srl] = $oCommentItem;
    endforeach;
    if($o_output->total_page>1):
        $oDoc->comment_page_navigation = [];
        $oDoc->comment_page_navigation = $o_output->page_navigation;
    endif;
}

이로써 $o_comment_list는 특정 $comment->comment_srl을 head값으로 가지는 대댓글들의 리스트가 됐습니다.

 

마지막으로 _comment_re.html이라는 파일을 하나 새로 만들어서 대댓글 리스트 출력을 담당하게 했습니다.

이렇게요.

<ul class="fdb_lst_ul {$mi->fdb_hide}">
    <block loop="$o_comment_list=>$k,$cmt">
    <li id="comment_{$cmt->comment_srl}" class="fdb_itm clear re bg{($cmt->get('depth'))%2}" style="margin-left:30px">
        <i class="fa fa-share fa-flip-vertical re"></i>... 블라블라~~

그리고 이 파일은 _comment.html 내에 include 시켜서 가져오게 했지요.

 

여기까지는 흡족할 정도로 매우 잘 됩니다.

include한 대댓글 리스트를 display: none 처리했다가 jQuery로 _comment.html 내에서 링크를 클릭하면 보이게끔 만들었구요.

        <block cond="$dcc->data->count>1">
            <a class="meta_re_tg re_comment" href="#" style="text-decoration: none; background-color: #735763; color: white; letter-spacing: -1px; padding: 6px 7px; border-radius: 3px; opacity: 0.6;">{$lang->re_cmt} ({$dcc->data->count})</a> // 얘를 클릭하면
        </block>
    </li>
    <div class="comment_re_container" cond="$dcc->data->count" style="display:none"><include target="_comment_re.html" /></div> // 얘가 보이게 돼죠
</block> // 얘는 원댓글의 반복문이 끝나는 지점이에요

(a태그 안의 텍스트는 '답글 (n)'으로 나오게 됩니다.)

 

...

 

여기까지, 아무런 무리 없이 잘 됩니다.

하지만!!!!!! 제가 계획했던 건 ...

처음에는 대댓글 리스트를 로드하지 않았다가, 원댓글에서 '답글 (n)'이라는 링크를 클릭하면 ajax로 대댓글 리스트를 불러오게 하는 것이었습니다.

 

근데 이게 도무지 되지를 않습니다.

현재까지 시도해본 방법은 다음과 같습니다.

일단 include 구문을 지우구요...

 

1. load()로 컨테이너 $('.comment_re_container') 안에 _comment_re.html 파일을 불러온다.

    => 파일 퍼미션 때문인지, 무엇 때문인지 실패 ㅡㅡ;;

2. append() 또는 html()로 '<include target="_comment_re.html" />'을 새로 불러온다.

    => _comment_re.html 코드들의 따옴표 문제 때문인지 역시 실패합니다. 그래서 따옴표를 재정리하는 노가다를 해봤는데, 이미 코드 안에 홑따옴표와 겹따옴표가 중복되는 지점들이 있어서 그냥 포기;;;

3. exec_json으로 'board.dispBoardContentCommentList' 액션을 활용한다.

    => 이 방법은 불러올 수 있는 항목들이 제한적인 데다, 가장 결정적으로는 댓글의 head 번호를 따올 수 없어서 대댓글 필터링조차 어려워 포기ㅠㅠ

 

아무튼 이런 실패를 겪고 있는 중입니다 으흐흐흐

구글링을 하다보니, 외부페이지(php)로 db 테이블을 갖고 오는 방법이 있다고 하던데 다음에는 이 방법으로 실패를(?) 해보려구요.

 

...

 

능력의 한계를 실감하는 깊은 밤이네요.

다음에 또 (실패) 소식 전하도록 하겠습니다~

윤삼

profile
아무래도 중급 초반 수준의 코딩 오타쿠인 것 같습니다.
  • profile

    제가 뭔가 테스트 해보고 말씀드리는건 아니고 그냥 꼼수로써 이런건 어떤가 해서 한번 아이디어 차원에서 말씀드리자면, 원래 게시판에서 대댓글까지 포함해서 댓글리스트가 어레인지 되어서 배열에 담겨 나오잖아요.
    그럼 대댓글이라는게 parent_srl 이 존재한다는 것이고 이게 존재한다면, style 에 display:none; 을 먹인다고 해 놓으면 일단 대댓글은 다 안보일 것입니다.(단, 대댓글 포함 댓글이 페이징 될 정도로 많다면 1페이지에 노출되는 기본 댓글수가 좀 뒤죽박죽 되는 경향은 있을듯 합니다. 단점)
    그리고 해당 댓글에는 id 값을 gg_{parent_srl값} 같은것으로 줘 놓고 함수를 하나 script 로 만드는데 function gg_show(id) { jQuery("#"+id).show(); } 이런식으로 해놓고 실제 부모 댓글에 a 링크를 하나 만들고 onclick 이벤트 해서 gg_show(gg_{parent_srl값}); 이런식으로 하면 보여지지 않을까요? 토글을 위해서 추가적으로 또 처리해 주면 될 것 같구요... 그냥 실제로 코딩도 안하고 입코딩을 해 보았습니다.
    잘 알지도 못하면서 건방지다고 욕하지는 말아 주세요 ㅠㅠ

  • profile profile
    욕이라니요 무슨;;;; ㅎㅎ
    제안하신 방법을 제일 먼저 생각해보긴 했었는데요. 말씀하셨던 것처럼 대댓글이 압도적으로 많거나 하는 경우 리스트 모양새가 일정치 않게 돼서 신경이 쓰이더라구요. 그래서 쿼리를 새로 짜서 시조 댓글과 자손 댓글을 따로 불러본 거구요.
    그나저나 깨알 같은 gg 시그니처ㅋㅋㅋㅋㅋ
  • profile
    "해결되는 징크스" 윤삼님의 징크스를 위하여 파봐야겠네요.
  • profile profile
    우왓 같이 고민해주신다니 정말로 영광입니다ㅠㅠ
    이게 된다면 그동안 몇몇 분들이 고민해오던 포털 사이트 같은 댓글-대댓글 메커니즘이 가능해질 거 같아요!
  • profile profile
    아하 이게 포털 사이트 방식인가요? 모듈로 따로 만들면 되긴 합니다.
  • profile profile
    대댓글을 2차까지만 허용해야 되는군요!
  • profile profile
    위에서 대댓글 리스트 가져오는 쿼리( getDescendantCommentList)에서 보시듯, 2차 댓글부터 전부 다 가져오는데, 정렬순서는 오래된 댓글부터 가져오게 했어요.

    음, 역시 모듈로 만드는 게 일반사용자 입장에서도 편하고 접근하기 쉽겠죠? ... 근데 그럴 공력까지는 없어서 슬퍼요ㅠㅠ 그 와중에 코어는 건드리기 싫고, 난감하다면 난감한 정신상태인 거죠ㅎㅎ
  • profile profile

    코어에 포함되지 않고 별도로설치한 어떤 모듈에다가 쿼리문 하나만 은근슬쩍 하나 끼워 넣으셔요 ;; 그리고 executeQueryArray('모듈명.쿼리명',$args); 이런식으로....

     

  • profile profile
    그렇게 해도 ajax로 대댓글 리스트를 불러올 수 있는 거겠죠? 스윽 한 번 끼워넣어 봐야겠어요.
  • ?
    모바일 api 함수쪽 보시면 _comment.html 파일을 ajax로 불러오는 함수가 있었던 걸로 기억하는데(목록에서 해당 함수로 댓글을 바로 불러오는 스킨을 본 적이 있습니다)그걸 응용해 보시면 어떨까요? 저도 분석을 제대로 해본 건 아니라서 가능한지는 모르겠습니다만...
  • ? profile
    오오오! 감사합니다~ 한번 찾아보겠습니다!!
  • ? profile

    감사합니다. 덕분에 exec_json으로 getBoardCommentPage을 사용해봤습니다.

    $(document).on('click', '.meta_re_tg', function(){
        var target = $(this).parent('li').next('.comment_re_container'),
        params = {
            document_srl : $('.rd').data('docsrl')
        };
        exec_json('board.getBoardCommentPage', params, function(data) {
            target.html(data.html);
        });
        target.fadeIn('slow');
        return false;
    });

     

    그리고 board.mobile.php에서 해당 함수를 보니 이렇습니다.

     

    $oTemplate = TemplateHandler::getInstance();

    $html = $oTemplate->compile($this->getTemplatePath(), "comment.html");

    $this->add("html", $html);

     

    여기서 두 가지 생각이 드네요.

    우선, 이렇게 했을 때 댓글 목록의 list_count와 list_order를 조작하기가 어렵더군요(개인적으로 이 부분을 손볼 생각이 있거든요).

    그리고, comment.html이 어디 있는 건지는 잘 모르겠는데, 이걸로는 보통의 게시판 스킨의 댓글단처럼 출력하기가 어렵더라구요;;; (코어 수정 없이 스크립트 내에서 다른 외부 파일을 삽입하는 걸로 후킹하는 방법이 있으면 좋으련만...)

     

    으으, 다른 방편을 알아봐야겠어요ㅜㅜ

  • profile
    아, 좀 더 살펴보니 comment.html은 m.skin 폴더의 모바일 스킨에 있는 파일이었군요.
    이걸 어떻게 해봐야겠어요~
    라자루스님, 감사합니다!