위젯 없이 데이터 조회하기

위젯 없이 데이터 조회하기

위젯을 사용하지 않고 직접 데이터베이스에서 데이터를 조회하여 레이아웃에 표시하는 방법을 설명합니다.

📋 기본 개념

위젯을 사용하지 않고 직접 데이터를 조회하는 방법은 다음과 같은 장점이 있습니다:
- 성능 향상 (위젯 오버헤드 제거)
- 커스터마이징 자유도 증가
- 캐싱 전략의 직접 제어

🔧 기본 사용법

1. Context 객체를 통한 데이터 조회

<!-- 레이아웃 파일에서 -->
{@
$args = new stdClass();
$args->module_srl = 123; // 게시판 모듈 번호
$args->list_count = 5;   // 가져올 글 수
$args->page = 1;

$oDocumentModel = getModel('document');
$output = $oDocumentModel->getDocumentList($args);
$document_list = $output->data;
}

<!-- 데이터 출력 -->
<div class="recent-posts">
    <h3>최근 게시물</h3>
    <ul>
    <!--@foreach($document_list as $document)-->
        <li>
            <a href="{getUrl('','mid',$document->get('mid'),'document_srl',$document->get('document_srl'))}">
                {$document->get('title')}
            </a>
            <span class="date">{zdate($document->get('regdate'), 'Y-m-d')}</span>
        </li>
    <!--@end-->
    </ul>
</div>

2. 직접 DB 쿼리 사용

{@
// executeQuery를 사용한 직접 쿼리
$args = new stdClass();
$args->module_srl = 123;
$args->list_count = 10;

$output = executeQuery('layout.getRecentDocuments', $args);
$recent_docs = $output->data;
}

<div class="custom-recent-list">
<!--@foreach($recent_docs as $doc)-->
    <div class="post-item">
        <h4><a href="{getUrl('','mid',$doc->mid,'document_srl',$doc->document_srl)}">{$doc->title}</a></h4>
        <p class="meta">
            <span class="author">{$doc->nick_name}</span>
            <span class="date">{zdate($doc->regdate, 'Y.m.d')}</span>
            <span class="comments">댓글 {$doc->comment_count}</span>
        </p>
    </div>
<!--@end-->
</div>

📊 실전 예제

1. 게시판별 최신 글 탭형 출력

{@
// 여러 게시판의 최신 글을 한번에 조회
$board_list = array(
    array('srl' => 123, 'name' => '공지사항', 'mid' => 'notice'),
    array('srl' => 124, 'name' => '자유게시판', 'mid' => 'free'),
    array('srl' => 125, 'name' => 'FAQ', 'mid' => 'faq')
);

$tab_data = array();
foreach($board_list as $board) {
    $args = new stdClass();
    $args->module_srl = $board['srl'];
    $args->list_count = 5;
    $args->order_type = 'regdate';

    $oDocumentModel = getModel('document');
    $output = $oDocumentModel->getDocumentList($args);
    $tab_data[$board['mid']] = array(
        'name' => $board['name'],
        'list' => $output->data
    );
}
}

<div class="tab-recent-posts">
    <ul class="tab-nav">
    <!--@foreach($tab_data as $mid => $data)-->
        <li><a href="#tab-{$mid}" onclick="showTab('{$mid}')">{$data.name}</a></li>
    <!--@end-->
    </ul>

    <!--@foreach($tab_data as $mid => $data)-->
    <div id="tab-{$mid}" class="tab-content">
        <ul>
        <!--@foreach($data.list as $doc)-->
            <li>
                <a href="{getUrl('','mid',$mid,'document_srl',$doc->document_srl)}">
                    {cut_str($doc->title, 30, '...')}
                </a>
                <span class="date">{zdate($doc->regdate, 'm.d')}</span>
            </li>
        <!--@end-->
        </ul>
    </div>
    <!--@end-->
</div>

<script>
function showTab(mid) {
    // 모든 탭 숨기기
    var tabs = document.querySelectorAll('.tab-content');
    tabs.forEach(function(tab) {
        tab.style.display = 'none';
    });

    // 선택된 탭 보이기
    document.getElementById('tab-' + mid).style.display = 'block';
}

// 첫 번째 탭 기본 활성화
document.addEventListener('DOMContentLoaded', function() {
    var firstTab = document.querySelector('.tab-content');
    if(firstTab) firstTab.style.display = 'block';
});
</script>

2. 인기글과 최신 댓글 동시 출력

{@
// 인기글 조회 (조회수 기준)
$args_popular = new stdClass();
$args_popular->module_srl = 123;
$args_popular->list_count = 5;
$args_popular->order_type = 'readed_count';
$args_popular->period = 7; // 7일간

$oDocumentModel = getModel('document');
$popular_output = $oDocumentModel->getDocumentList($args_popular);
$popular_list = $popular_output->data;

// 최신 댓글 조회
$args_comment = new stdClass();
$args_comment->module_srl = 123;
$args_comment->list_count = 5;

$oCommentModel = getModel('comment');
$comment_output = $oCommentModel->getNewestCommentList($args_comment);
$comment_list = $comment_output->data;
}

<div class="sidebar-widgets">
    <!-- 인기글 -->
    <div class="widget popular-posts">
        <h3>이번 주 인기글</h3>
        <ul>
        <!--@foreach($popular_list as $doc)-->
            <li>
                <a href="{getUrl('','mid',$doc->get('mid'),'document_srl',$doc->get('document_srl'))}">
                    {cut_str($doc->get('title'), 25, '...')}
                </a>
                <span class="meta">
                    <span class="views">조회 {number_format($doc->get('readed_count'))}</span>
                    <span class="comments">댓글 {$doc->get('comment_count')}</span>
                </span>
            </li>
        <!--@end-->
        </ul>
    </div>

    <!-- 최신 댓글 -->
    <div class="widget recent-comments">
        <h3>최신 댓글</h3>
        <ul>
        <!--@foreach($comment_list as $comment)-->
            <li>
                <div class="comment-author">{$comment->getNickName()}</div>
                <div class="comment-content">
                    <a href="{getUrl('','mid',$comment->get('mid'),'document_srl',$comment->get('document_srl'))}#comment_{$comment->get('comment_srl')}">
                        {cut_str(strip_tags($comment->get('content')), 40, '...')}
                    </a>
                </div>
                <div class="comment-date">{zdate($comment->get('regdate'), 'Y.m.d H:i')}</div>
            </li>
        <!--@end-->
        </ul>
    </div>
</div>

3. 갤러리형 이미지 게시물

{@
// 이미지가 있는 게시물만 조회
$args = new stdClass();
$args->module_srl = 126; // 갤러리 게시판
$args->list_count = 8;
$args->order_type = 'regdate';

$output = executeQuery('layout.getDocumentsWithImages', $args);
$gallery_list = $output->data;
}

<div class="gallery-widget">
    <h3>최신 갤러리</h3>
    <div class="gallery-grid">
    <!--@foreach($gallery_list as $item)-->
        <div class="gallery-item">
            <a href="{getUrl('','mid',$item->mid,'document_srl',$item->document_srl)}">
                <!--@if($item->thumbnail)-->
                    <img src="{$item->thumbnail}" alt="{$item->title}" loading="lazy">
                <!--@else-->
                    <img src="/common/img/no-image.png" alt="이미지 없음">
                <!--@end-->
                <div class="overlay">
                    <h4>{cut_str($item->title, 20, '...')}</h4>
                    <p>{zdate($item->regdate, 'Y.m.d')}</p>
                </div>
            </a>
        </div>
    <!--@end-->
    </div>
</div>

<style>
.gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
}
.gallery-item {
    position: relative;
    overflow: hidden;
    border-radius: 8px;
}
.gallery-item img {
    width: 100%;
    height: 120px;
    object-fit: cover;
    transition: transform 0.3s ease;
}
.gallery-item:hover img {
    transform: scale(1.1);
}
.overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: linear-gradient(transparent, rgba(0,0,0,0.8));
    color: white;
    padding: 10px;
    transform: translateY(100%);
    transition: transform 0.3s ease;
}
.gallery-item:hover .overlay {
    transform: translateY(0);
}
</style>

📈 성능 최적화

1. 캐싱 활용

{@
$cache_key = 'recent_posts_' . $module_srl;
$cache_time = 300; // 5분

$cached_data = FileHandler::readFile('./files/cache/layout/' . $cache_key . '.cache');
if($cached_data && (time() - filemtime('./files/cache/layout/' . $cache_key . '.cache')) < $cache_time) {
    $recent_list = unserialize($cached_data);
} else {
    // 데이터 조회
    $args = new stdClass();
    $args->module_srl = $module_srl;
    $args->list_count = 10;

    $oDocumentModel = getModel('document');
    $output = $oDocumentModel->getDocumentList($args);
    $recent_list = $output->data;

    // 캐시 저장
    FileHandler::writeFile('./files/cache/layout/' . $cache_key . '.cache', serialize($recent_list));
}
}

2. 조건부 로딩

{@
// 특정 페이지에서만 데이터 로드
$current_mid = Context::get('mid');
$load_recent_posts = in_array($current_mid, array('index', 'main', 'home'));
}

<!--@if($load_recent_posts)-->
{@
// 최신 게시물 로드
$args = new stdClass();
$args->module_srl = 123;
$args->list_count = 5;

$oDocumentModel = getModel('document');
$output = $oDocumentModel->getDocumentList($args);
$recent_posts = $output->data;
}

<div class="recent-posts-widget">
    <!-- 위젯 내용 -->
</div>
<!--@end-->

💡 주의사항

  1. 메모리 사용량: 대량의 데이터 조회 시 메모리 사용량 주의
  2. 보안: 사용자 입력값을 직접 쿼리에 사용할 때 SQL 인젝션 방지
  3. 성능: 복잡한 쿼리는 캐싱 필수
  4. 유지보수: 코드 가독성을 위해 적절한 주석 추가

🔗 관련 문서