kim7549

[최적화] 영카트 카테고리 로딩 속도 2.7배 향상 및 메모리 최적화 팁 [get_shop_category_array]

안녕하세요. 영카트 기반 쇼핑몰을 운영하면서 카테고리 호출 속도가 점차 느려지는 문제를 해결하고자 쿼리 최적화를 진행해 보았습니다. 기존 영카트 방식의 계층 구조 호출이 가진 성능 한계를 개선한 결과와 코드를 공유합니다.

 

 

제 환경은

카테고리 테이블의

row는 863개이고

depth는 4단계입니다.

 

1. 기존 방식의 문제점: N+1 쿼리 발생

기존 함수는 1단 카테고리를 가져온 뒤, 그 개수만큼 다시 2단 쿼리를 날리고, 또 그 개수만큼 3단 쿼리를 날리는 '재귀적 쿼리 호출(N+1 Problem)' 방식을 사용합니다.

  • 카테고리 숫자가 많아질수록 DB 접속 횟수가 기하급수적으로 늘어납니다.

  • 매 단계마다 별도의 쿼리를 실행하므로 실행 시간과 메모리 점유율이 동반 상승합니다.

2. 최적화 핵심: "Single Query & Reference Tree"

개선된 코드는 **단 한 번의 쿼리(Single Query)**로 모든 카테고리 데이터를 가져온 뒤, PHP의 참조(Reference, &) 연산자를 이용해 메모리 상에서 즉시 계층 구조를 조립합니다.

3. 성능 비교 결과 (Benchmark)

로컬 환경에서 카테고리 호출 시 측정한 결과입니다. (수치는 환경에 따라 다를 수 있습니다.)

항목 기존 코드 (N+1 방식) 최적화 코드 (Single Query) 개선 효과
실행 시간 0.014194... 초 0.005279... 초 약 270% 빨라짐
메모리 사용 12.55 MB 7.09 MB 약 43% 절감
  • 시간: DB 왕복 횟수를 1회로 단축하여 응답 속도를 대폭 줄였습니다.

  • 메모리: 불필요한 반복문과 임시 객체 생성을 최소화하여 메모리 효율을 극대화했습니다.

4. 최적화된 코드 (무제한 Depth 대응)

이 코드는 카테고리가 3단을 넘어 4단, 5단으로 깊어져도 별도의 코드 수정 없이 자동으로 계층을 구성합니다.


> lib > shop.data.lib.php

function get_shop_category_array($is_cache=false){
    static $categories = array();
    
    // 영카트 표준 Hook 유지
    $categories = run_replace('get_shop_category_array', $categories, $is_cache);

    if( $is_cache && !empty($categories) ){
        return $categories;
    }

    // 단 한 번의 쿼리로 모든 카테고리 로드
    $sql = " SELECT * FROM {$g5['yc5_category_table']} 
             WHERE ca_use = '1' 
             ORDER BY ca_id ASC ";
    $result = sql_query($sql);

    $refs = array();
    $categories = array();

    while($row = sql_fetch_array($result)) {
        $row['url'] = shop_category_url($row['ca_id']);
        $ca_id = $row['ca_id'];
        $len = strlen($ca_id);
        
        // 현재 노드 구조 생성
        $node = array('text' => $row);
        $refs[$ca_id] = $node;

        if($len == 2) {
            // 1단 카테고리
            $categories[$ca_id] = &$refs[$ca_id];
        } else {
            // 부모 ID 추출 및 참조 연결 (무제한 Depth 대응)
            $parent_id = substr($ca_id, 0, $len - 2);
            if(isset($refs[$parent_id])) {
                $refs[$parent_id][$ca_id] = &$refs[$ca_id];
            }
        }
    }
    return $categories;
}

마치며

메인 페이지나 사이드바에서 카테고리 메뉴를 호출할 때 서버 부하가 느껴진다면 이 방식을 적용해 보시길 추천드립니다. 특히 모바일 환경이나 접속자가 많은 시간대에 더 큰 효과를 볼 수 있습니다.

1명이 반응했습니다
|

댓글 2개

와.이 정도면 정식 버전에
포함 되어야 하는거 아닙니까?

고맙습니다 !!!

함수의 재귀호출이 편할 수는 있는데.. 너무 많이 돌면.. 성능에 영향을 주죠.. ^^

댓글을 작성하시려면 로그인이 필요합니다.

영카트5 팁자료실

+
제목 글쓴이 날짜 조회
3일 전 조회 88
3일 전 조회 41
1주 전 조회 213
2주 전 조회 321
2개월 전 조회 684
2개월 전 조회 638
2개월 전 조회 683
3개월 전 조회 876
3개월 전 조회 1,068
3개월 전 조회 658
4개월 전 조회 820
4개월 전 조회 960
4개월 전 조회 775
4개월 전 조회 827
4개월 전 조회 861
4개월 전 조회 966
4개월 전 조회 793
5개월 전 조회 779
5개월 전 조회 942
5개월 전 조회 941
5개월 전 조회 816
5개월 전 조회 1,101
6개월 전 조회 1,139
6개월 전 조회 933
6개월 전 조회 995
6개월 전 조회 952
6개월 전 조회 1,067
6개월 전 조회 998
7개월 전 조회 1,049
7개월 전 조회 860