코드
2018.12.06 13:41

[PHP] 간단한 캐싱 클래스

조회 수 605 추천 수 1 댓글 3
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
Extra Form
라이선스 MIT

PHP를 이용해서 간단한 캐싱 클래스를 만들어보았습니다.

여기에선 간단하게 시간을 체크해서 캐시를 재설정할 수 있게 해놓았습니다.

redis 등과 같이 좀 더 고급 기술을 사용하진 않고 단순히 파일 캐싱을 구현하였습니다.

고급 기술을 사용하시거나 좀 더 많은 기능이 필요하실 경우 이미 만들어진 라이브러리를 사용하시는 것이 좋습니다.


참고로 제가 만든 카카오톡 봇의 경우 이 캐싱 클래스를 사용하고 있습니다.


<?php

class Cache
{
    // 실제 파일이 저장된 폴더
    private $real_file_dir;
    // 캐시 파일이 저장될 폴더
    private $cache_file_dir;
    // 캐시 만료 시간 (초 단위)
    private $timeout;

    public function __construct($real_dir, $cache_dir, $timeout)
    {
        $this->real_file_dir = $real_dir;
        $this->cache_file_dir = $cache_dir;
        $this->timeout = $timeout;

        // 캐시 폴더가 존재하지 않는 경우 폴더 생성
        if(!file_exists($cache_dir))
        {
            mkdir($cache_dir, 0777, TRUE);
        }
    }

    // 파일 출력 가져오기
    private static function _get_file_data($filepath, $render = FALSE)
    {
        if(!file_exists($filepath))
        {
            return NULL;
        }
        if($render === TRUE)
        {
            // PHP 코드를 실행한 결과를 반환
            ob_start();
            include $filepath;
            $content = ob_get_clean();
            return $content;    
        }
        else
        {
            // 그냥 파일을 읽어서 나온 결과를 반환
            return file_get_contents($filepath);
        }
    }

    // 캐시 파일 이름 생성 (기존 이름에서 확장자 부분을 제거하고 앞쪽에 cache_를 붙인다)
    private static function _convert_cache_filename($filename)
    {
        return 'cache_' . substr($filename, 0, strrpos($filename, '.'));
    }

    // 실제 파일이 위치한 경로
    private function _get_real_file_path($filename)
    {
        return $this->real_file_dir . '/' . $filename;
    }

    // 캐시 파일이 위치한 경로
    private function _get_cache_file_path($filename)
    {
        return $this->cache_file_dir . '/' . $filename;
    }

    // 실제 파일 출력 가지고 오기
    private function _get_real_file_data($filename)
    {
        return self::_get_file_data($this->_get_real_file_path($filename), TRUE);
    }

    // 캐시 파일 내용 가지고 오기
    private function _get_cache_file_data($filename)
    {
        return self::_get_file_data($this->_get_cache_file_path($filename), FALSE);
    }

    // 캐시 파일이 생성된 시간 가지고 오기
    private function _get_cache_time($filename)
    {
        $filepath = $this->_get_cache_file_path($filename);
        if(!file_exists($filepath))
        {
            return 0;
        }
        else
        {
            return filemtime($filepath);
        }
    }

    // 캐시 파일 생성하기
    private function _create_cache_file($filename)
    {
        $cache_filename = $this->_convert_cache_filename($filename);
        $cache_filepath = $this->_get_cache_file_path($cache_filename);

        $content = $this->_get_real_file_data($filename);

        $f = fopen($cache_filepath, "w");
        fwrite($f, $content);
        fclose($f);

        return $content;
    }

    // 캐시 파일들 삭제하기
    public function clear_cache()
    {
        $cache_files = glob($this->cache_file_dir . '/*');
        foreach ($cache_files as $file)
        {
            if(is_file($file))
            {
                unlink($file);
            }
        }
    }

    // 파일 내용 읽어오기. 캐싱이 된 경우 캐시 파일을, 실패한 경우에는 캐시 파일을 생성하고 해당 내용을 출력
    public function get_content($filename, $timeout = 0)
    {
        if($timeout === 0) $timeout = $this->timeout;
        $cache_filename = self::_convert_cache_filename($filename);

        $cache_time = $this->_get_cache_time($cache_filename);
        $current_time = time();

        // timeout이 초과한 경우 캐시 파일 재생성
        if($current_time - $cache_time > $timeout)
        {
            return $this->_create_cache_file($filename);
        }
        else
        {
            return $this->_get_cache_file_data($cache_filename);
        }
    }
}

// 60초 캐시 클래스 생성
$cache = new Cache(__DIR__ . '/real/file/path', __DIR__ . '/cache/file/path', 60);
// file.php를 캐싱해서 읽어오기 (기본 값 사용)
$result = $cache->get_content('file.php');
echo $result;

// file_10s.php를 캐싱해서 읽어오기 (10초)
$result = $cache->get_content('file_10s.php', 10);
echo $result;

// 캐시 삭제
$cache->clear_cache();



Who's humit

profile

Study For Us Hosting 1기 모니터링 관리자 (16.12.01 ~ 17.01.08.)

C++, Python, PHP를 주로 사용하며 알고리즘, DL, 해킹 쪽에 관심이 있습니다.

휴학생입니다.

티스토리 블로그 : http://humit.tistory.com/

카카오톡 봇 : http://pf.kakao.com/_Efrbu/chat

지식인 프로필 : https://kin.naver.com/profile/jhjang1005

  • profile
    이니스프리 2018.12.06 14:28

    요새 그러지 않아도 캐시에 관심이 많았는데 좋은 스크립트 올려주셔서 감사합니다 ^-^

    올려주신 스크립트가 일종의 파일캐시(디스크캐시)인 것이죠?

    덕분에 파일캐시의 구조에 대해 조금이나마 이해하게 되었네요~


    그누보드가 세션 등 처리에 있어 상대적으로 캐시 친화적이지 않고

    게다가 XE/라이믹스에는 슈퍼캐시 모듈이 있기 때문에,

    양자 간에 TTFB나 감당할 수 있는 동접자 수에서 차이가 발생하고

    그러한 결과 간접적으로 SEO에서도 불이익이 발생한다고 알고 있네요 ㅠㅠ


    제가 Redis를 사용해보려고 했는데 그누보드/아미나 최신버전에 PHP 7 환경에서

    제대로 작동하는 공개된 플러그인이 아마도 없는 것 같더군요 ㅜㅜ


    만약 글이 자주 올라오지 않는 환경에서 최신글 위젯 등을 효율적으로 캐싱하려면

    캐시 만료시간을 아주 길게 잡는 대신에

    새 글을 작성하면 캐시를 갱신하는 방식으로 사용하면 되겠죠?


    좋은 자료 올려주신 덕분에 열심히 공부해보겠습니다~

    humit 님께 항상 감사드립니다 :)

    날씨가 쌀쌀하지만 즐겁고 뜻깊은 휴가 되세요~!

  • profile
    title: 황금 서버 (30일)humit 2018.12.06 18:47
    네 일종의 파일 캐시라고 생각하시면 됩니다 ㅎㅎ
  • ?
    포인트 폭탄+ 2018.12.06 18:47
    humit님 축하합니다.
    추가로 200포인트만큼 포인트 폭탄+를 받았습니다.

List of Articles
번호 분류 제목 글쓴이 날짜 조회 수
78 코드 폰트를 자동 설치하는 코드 1 네모 2018.07.16 830
77 코드 파이썬을 이용한 텔레그램 새 글 알림 (허접합니다) 4 이니스프리 2017.11.19 2376
76 코드 파이선 셸에서 실행하면...? 3 제르엘 2018.07.22 499
75 코드 클라이언트단에서 이미지 리사이징 6 file 네모 2018.05.06 1069
74 코드 컴퓨터의 uuid 얻기 5 title: 황금 서버 (30일)humit 2018.01.28 1097
73 코드 잘못 쓰면 컴퓨터가 날아가는 코드 29 제르엘 2018.07.08 964
72 자료 이게 팔릴까 - Xe/라이믹스 에러페이지 [2017-10-04] 3 file title: 열려라 맛스타의 자물쇠TVJ 2017.10.04 671
71 코드 유튜브에 약간의 기능을 추가 해주는 크롬 확장 프로그램. 11 file Hanam09 2018.01.26 942
70 코드 엑셀파일 불러서 히스토그램 그려주는 함수 국내산라이츄 2017.08.03 723
69 코드 엑셀 읽어서 그래프 그려주는 함수 1 국내산라이츄 2017.08.03 1423
68 코드 아주 간단한 기초 C++ 6 제르엘 2018.04.21 477
67 자료 소셜XE / 기존 통합 로그인 스킨 V2.2 2 file NoYeah 2017.06.28 905
66 코드 세린서버에서 시도중인 백업 스크립트 입니다. 4 NoYeah 2017.06.27 744
65 코드 새 글 자동 댓글 스크립트 (AutoHotkey) 9 이니스프리 2017.11.26 3451
64 코드 사이트 서버 이전 (또는 미러링 사이트 구축) 쉽게하는 스크립트 1 NoYeah 2018.01.14 858
63 코드 브라우저 언어에 따라 다른 폴더를 사용하는 PHP 코드 4 file 네모 2017.10.10 639
62 코드 미완성 받아쓰기 (C) title: 대한민국 국기gimmepoint 2018.04.20 380
61 코드 매우 특이한 버그 9 title: 대한민국 국기gimmepoint 2018.06.05 569
60 자료 링크 파싱 애드온용 스킨 (트위터 스타일) 3 file SNAX 2017.10.03 516
59 코드 도박 중독자를 위한 광고 차단 규칙 file 제르엘 2020.08.21 288
Board Pagination Prev 1 2 3 4 Next
/ 4