코드
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 코드 [PHP] 이미지를 원하는 크기(원본비율 유지)로 리사이즈 하여 출력 (원본 이미지는 수정하지 않습니다) 6 이니스프리 2018.12.20 7693
77 코드 [Python] Selenium을 이용하여 특정 element를 캡처하는 스크립트 2 file 이니스프리 2019.07.03 5886
76 코드 [파이썬] Requests를 사용한 네이버 카페 크롤링 - 일정수 이상의 리플이 달린 게시글만 텔레그램 알림 3 file 이니스프리 2019.11.17 4162
75 코드 [Python] 텔레그램을 이용한 게시판 새 글 알림봇 7 이니스프리 2018.12.02 3483
74 코드 새 글 자동 댓글 스크립트 (AutoHotkey) 9 이니스프리 2017.11.26 3451
73 코드 파이썬을 이용한 텔레그램 새 글 알림 (허접합니다) 4 이니스프리 2017.11.19 2376
72 코드 [Python] 싸이월드 미니홈피 백업 스크립트 1 이니스프리 2019.11.07 2162
71 코드 [Python] url 주소로부터 IP 주소 알아내기 title: 황금 서버 (30일)humit 2020.02.20 2047
70 코드 [오토핫키] 특정 사이트에 대한 ping 테스트 결과를 실행시간과 함께 로그 파일로 저장하는 스크립트 2 이니스프리 2018.09.22 1909
69 코드 [오토핫키] 구글 드라이브의 공유링크를 이미지 호스팅을 위한 다이렉트 링크로 바꿔주는 스크립트 10 file 이니스프리 2018.09.25 1670
68 코드 엑셀 읽어서 그래프 그려주는 함수 1 국내산라이츄 2017.08.03 1423
67 코드 [Python] 네이버 모바일 이미지 검색에서의 이미지 파일을 멀티스레드로 다운받고 1개의 파일로 병합 11 file 이니스프리 2019.07.12 1374
66 코드 [아미나] Dropbox API를 이용한 이미지 호스팅 보드스킨 12 file 이니스프리 2019.07.13 1369
65 코드 [Python-Gnuboard] 파이썬으로 구현한 그누보드 자동 글쓰기 함수 1 file 이니스프리 2021.04.08 1205
64 코드 [Python] 휴일지킴이 약국을 크롤링하여 Folium 지도에 마커로 표시하는 PyQt 윈도우 앱 7 file 이니스프리 2021.03.13 1140
63 코드 [Python] 네이버 실시간 검색어 3 title: 황금 서버 (30일)humit 2020.01.23 1120
62 코드 컴퓨터의 uuid 얻기 5 title: 황금 서버 (30일)humit 2018.01.28 1097
61 자료 [Autohotkey] 매분 정각에 전체화면을 캡쳐하는 스크립트 4 file 이니스프리 2020.05.22 1095
60 코드 [Python] PIL을 이용한 Animated GIF의 리사이징 file 이니스프리 2019.11.03 1095
59 코드 클라이언트단에서 이미지 리사이징 6 file 네모 2018.05.06 1069
Board Pagination Prev 1 2 3 4 Next
/ 4