접속자 집계 기능 사용 시 홈페이지 로딩 오래걸리는 문제

접속자 집계 기능 사용 시 홈페이지 로딩 오래걸리는 문제

QA

접속자 집계 기능 사용 시 홈페이지 로딩 오래걸리는 문제

답변 2

본문

/common.php 의 기본 소스코드 중 방문자 접속 내역을 남기는 include_once(G5_BBS_PATH.'/visit_insert.inc.php'); 가 있습니다.

그누보드에 기본적으로 있는 이 기능을 사용 시 처음 홈페이지 로딩 때 오래걸리는 문제가 있습니다. (한번 접속 이후에는 빠르게 접속 가능. 캐시에 저장되서 그런듯?)

 

그리고 이것을 주석처리하면 이런 로딩 문제가 사라집니다. 

그누보드를 사용하는 많은 홈페이지가 있는데 유독 한 홈페이지에만 이런 문제가 있습니다. 

visit_insert.inc.php의 코드는 아래와 같습니다. (아마 수정되는 않은 기본 코드일 것 같습니다.)


<?php
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
 
// 컴퓨터의 아이피와 쿠키에 저장된 아이피가 다르다면 테이블에 반영함
if (get_cookie('ck_visit_ip') != $_SERVER['REMOTE_ADDR'])
{
    set_cookie('ck_visit_ip', $_SERVER['REMOTE_ADDR'], 86400); // 하루동안 저장
 
    $tmp_row = sql_fetch(" select max(vi_id) as max_vi_id from {$g5['visit_table']} ");
    $vi_id = $tmp_row['max_vi_id'] + 1;
 
    // $_SERVER 배열변수 값의 변조를 이용한 SQL Injection 공격을 막는 코드입니다. 110810
    $remote_addr = escape_trim($_SERVER['REMOTE_ADDR']);
    $referer = "";
    if (isset($_SERVER['HTTP_REFERER']))
        $referer = escape_trim(clean_xss_tags(strip_tags($_SERVER['HTTP_REFERER'])));
    $user_agent  = escape_trim(clean_xss_tags(strip_tags($_SERVER['HTTP_USER_AGENT'])));
    $vi_browser = '';
    $vi_os = '';
    $vi_device = '';
    if(version_compare(phpversion(), '5.3.0', '>=') && defined('G5_BROWSCAP_USE') && G5_BROWSCAP_USE) {
        include_once(G5_BBS_PATH.'/visit_browscap.inc.php');
    }
    $sql = " insert {$g5['visit_table']} ( vi_id, vi_ip, vi_date, vi_time, vi_referer, vi_agent, vi_browser, vi_os, vi_device ) values ( '{$vi_id}', '{$remote_addr}', '".G5_TIME_YMD."', '".G5_TIME_HIS."', '{$referer}', '{$user_agent}', '{$vi_browser}', '{$vi_os}', '{$vi_device}' ) ";
 
    $result = sql_query($sql, FALSE);
    // 정상으로 INSERT 되었다면 방문자 합계에 반영
    if ($result) {
        $sql = " insert {$g5['visit_sum_table']} ( vs_count, vs_date) values ( 1, '".G5_TIME_YMD."' ) ";
        $result = sql_query($sql, FALSE);
 
        // DUPLICATE 오류가 발생한다면 이미 날짜별 행이 생성되었으므로 UPDATE 실행
        if (!$result) {
            $sql = " update {$g5['visit_sum_table']} set vs_count = vs_count + 1 where vs_date = '".G5_TIME_YMD."' ";
            $result = sql_query($sql);
        }
 
        // INSERT, UPDATE 된건이 있다면 기본환경설정 테이블에 저장
        // 방문객 접속시마다 따로 쿼리를 하지 않기 위함 (엄청난 쿼리를 줄임 ^^)
 
        // 오늘
        $sql = " select vs_count as cnt from {$g5['visit_sum_table']} where vs_date = '".G5_TIME_YMD."' ";
        $row = sql_fetch($sql);
        $vi_today = $row['cnt'];
 
        // 어제
        $sql = " select vs_count as cnt from {$g5['visit_sum_table']} where vs_date = DATE_SUB('".G5_TIME_YMD."', INTERVAL 1 DAY) ";
        $row = sql_fetch($sql);
        $vi_yesterday = $row['cnt'];
 
        // 최대
        $sql = " select max(vs_count) as cnt from {$g5['visit_sum_table']} ";
        $row = sql_fetch($sql);
        $vi_max = $row['cnt'];
 
        // 전체
        $sql = " select sum(vs_count) as total from {$g5['visit_sum_table']} ";
        $row = sql_fetch($sql);
        $vi_sum = $row['total'];
 
        $visit = '오늘:'.$vi_today.',어제:'.$vi_yesterday.',최대:'.$vi_max.',전체:'.$vi_sum;
 
        // 기본설정 테이블에 방문자수를 기록한 후
        // 방문자수 테이블을 읽지 않고 출력한다.
        // 쿼리의 수를 상당부분 줄임
        sql_query(" update {$g5['config_table']} set cf_visit = '{$visit}' ");
    }
}
?>

 

 

접속자 집계 기능은 필요한데 이 문제에 대해 아시는 분이 계실까요?

이 질문에 댓글 쓰기 :

답변 2

다양한 원인이 있을수 있는데.. 코드 최적화를 한번 해보시는것도 아래의 코드를 참고해 보시면 어떠실지요..

 

 

1.  방문자 집계 코드 최적화

<?php
if (!defined('_GNUBOARD_')) exit;

// 하루에 한 번만 IP 기록 (쿠키 확인)
if (get_cookie('ck_visit_ip') != $_SERVER['REMOTE_ADDR']) {
    set_cookie('ck_visit_ip', $_SERVER['REMOTE_ADDR'], 86400);
    
    // 방문자 테이블에 기록
    $remote_addr = escape_trim($_SERVER['REMOTE_ADDR']);
    $referer = isset($_SERVER['HTTP_REFERER']) ? escape_trim(clean_xss_tags(strip_tags($_SERVER['HTTP_REFERER']))) : '';
    $user_agent = escape_trim(clean_xss_tags(strip_tags($_SERVER['HTTP_USER_AGENT'])));
    
    // browscap 사용 시 브라우저 정보 수집 (선택적)
    $vi_browser = '';
    $vi_os = '';
    $vi_device = '';
    
    // 방문자 정보 삽입 (단일 쿼리로 처리)
    $sql = "INSERT INTO {$g5['visit_sum_table']} (vs_count, vs_date) 
            VALUES (1, '".G5_TIME_YMD."')
            ON DUPLICATE KEY UPDATE vs_count = vs_count + 1";
    sql_query($sql);
    
    // 간단한 방문자 정보만 저장 (로그는 별도 처리)
    $sql = "INSERT INTO {$g5['visit_table']} 
            (vi_ip, vi_date, vi_time, vi_referer, vi_agent) 
            VALUES ('{$remote_addr}', '".G5_TIME_YMD."', '".G5_TIME_HIS."', '{$referer}', '{$user_agent}')";
    sql_query($sql);
    
    // 통계 업데이트 (한 번에 처리)
    $sql = "SELECT 
                (SELECT vs_count FROM {$g5['visit_sum_table']} WHERE vs_date = '".G5_TIME_YMD."') AS today,
                (SELECT vs_count FROM {$g5['visit_sum_table']} WHERE vs_date = DATE_SUB('".G5_TIME_YMD."', INTERVAL 1 DAY)) AS yesterday,
                (SELECT MAX(vs_count) FROM {$g5['visit_sum_table']}") AS max_count,
                (SELECT SUM(vs_count) FROM {$g5['visit_sum_table']}") AS total";
    $row = sql_fetch($sql);
    
    $visit = '오늘:'.$row['today'].',어제:'.$row['yesterday'].',최대:'.$row['max_count'].',전체:'.$row['total'];
    sql_query("UPDATE {$g5['config_table']} SET cf_visit = '{$visit}'");
}
?>

 

 

 

2. 비동기로

<?php
if (!defined('_GNUBOARD_')) exit;

// 쿠키 확인만 동기적으로 처리
if (get_cookie('ck_visit_ip') != $_SERVER['REMOTE_ADDR']) {
    set_cookie('ck_visit_ip', $_SERVER['REMOTE_ADDR'], 86400);
    
    // 방문자 정보는 자바스크립트로 비동기 처리
    add_event('tail_sub', 'visit_async_record');
}

// 비동기 처리 함수
function visit_async_record() {
?>
<script>
(function() {
    // 페이지 로드 완료 후 비동기적으로 방문자 기록
    window.addEventListener('load', function() {
        setTimeout(function() {
            var xhr = new XMLHttpRequest();
            xhr.open('POST', '<?php echo G5_BBS_URL ?>/visit_record.ajax.php');
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.send('token=<?php echo get_session_token() ?>');
        }, 100);
    });
})();
</script>
<?php
}
?>

 

 

visit_record.ajax.php

 

 

<?php
include_once('./_common.php');
include_once(G5_LIB_PATH.'/connect.lib.php');

// CSRF 토큰 확인
if (!get_session_token_value()) {
    die('Invalid request');
}

// 방문자 정보 기록
$remote_addr = escape_trim($_SERVER['REMOTE_ADDR']);
$referer = isset($_SERVER['HTTP_REFERER']) ? escape_trim(clean_xss_tags(strip_tags($_SERVER['HTTP_REFERER']))) : '';
$user_agent = escape_trim(clean_xss_tags(strip_tags($_SERVER['HTTP_USER_AGENT'])));

// 방문자 통계 업데이트
$sql = "INSERT INTO {$g5['visit_sum_table']} (vs_count, vs_date) 
        VALUES (1, '".G5_TIME_YMD."')
        ON DUPLICATE KEY UPDATE vs_count = vs_count + 1";
sql_query($sql);

// 방문자 상세 정보 기록
$sql = "INSERT INTO {$g5['visit_table']} 
        (vi_ip, vi_date, vi_time, vi_referer, vi_agent) 
        VALUES ('{$remote_addr}', '".G5_TIME_YMD."', '".G5_TIME_HIS."', '{$referer}', '{$user_agent}')";
sql_query($sql);

// 통계 갱신
$sql = "SELECT 
            (SELECT vs_count FROM {$g5['visit_sum_table']} WHERE vs_date = '".G5_TIME_YMD."') AS today,
            (SELECT vs_count FROM {$g5['visit_sum_table']} WHERE vs_date = DATE_SUB('".G5_TIME_YMD."', INTERVAL 1 DAY)) AS yesterday,
            (SELECT MAX(vs_count) FROM {$g5['visit_sum_table']}") AS max_count,
            (SELECT SUM(vs_count) FROM {$g5['visit_sum_table']}") AS total";
$row = sql_fetch($sql);

$visit = '오늘:'.$row['today'].',어제:'.$row['yesterday'].',최대:'.$row['max_count'].',전체:'.$row['total'];
sql_query("UPDATE {$g5['config_table']} SET cf_visit = '{$visit}'");

echo 'success';
?>

경험상으론 하루의 처음이라고 하신거 봐서는 visit_insert.inc.php보다는 db_table.optimize.php 의 optimize 쿼리때문인거 같다는 생각이 듭니다..

 

모든 접속자 아이디가 다 첫접속이 느린거면 visit쪽에 인덱스를 잡으시거나 윗분말씀 처럼 비동기로 처리, 그게 아니면 db_table.optimize.php 를 체크해보세요

 

답변을 작성하시기 전에 로그인 해주세요.
QA 내용 검색
질문등록
전체 473
© SIRSOFT
현재 페이지 제일 처음으로