코드
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포인트만큼 포인트 폭탄+를 받았습니다.

  1. [JS] http를 https로 리디렉션!

    Date2018.12.30 Category코드 ByHanam09 Views674
    Read More
  2. 이게 팔릴까 - Xe/라이믹스 에러페이지 [2017-10-04]

    Date2017.10.04 Category자료 Bytitle: 열려라 맛스타의 자물쇠TVJ Views672
    Read More
  3. [아미나] 출석 여부를 나타내는 메인화면 위젯

    Date2018.12.15 Category코드 By이니스프리 Views666
    Read More
  4. [PHP] 그누보드 자동 게시글 작성 - 일본기상협회의 우리나라 날씨를 크롤링한 후 파파고로 번역하여 글 작성

    Date2018.11.15 Category코드 By이니스프리 Views657
    Read More
  5. html 초보가 만든 자소서

    Date2018.04.21 Category코드 Bytitle: 대한민국 국기gimmepoint Views652
    Read More
  6. Git 저장소에서 자동으로 받아 업데이트하는 쉘 스크립트

    Date2017.09.16 Category코드 ByNoYeah Views651
    Read More
  7. [Python/Telegram] Studyforus 알림봇 (댓글, 스티커 파싱)

    Date2020.05.15 Category코드 By이니스프리 Views649
    Read More
  8. AdBlock 접근 방지 애드온 v0.1

    Date2017.10.05 Category자료 By네모 Views649
    Read More
  9. [PHP] 기상청 중기예보를 캐러셀로 보여주는 위젯 (매우 허접합니다 ㅠㅠ)

    Date2018.09.28 Category코드 By이니스프리 Views647
    Read More
  10. Cmd 에서 서비스 시작 / 종료하기

    Date2018.02.18 Category코드 ByProjectSE Views644
    Read More
  11. 브라우저 언어에 따라 다른 폴더를 사용하는 PHP 코드

    Date2017.10.10 Category코드 By네모 Views639
    Read More
  12. Gentelella 레이아웃에 사용가능한 가격 테이블 위젯입니다.

    Date2017.07.03 Category자료 ByNoYeah Views638
    Read More
  13. [아미나] 게시글을 작성하면 ID와 IP로 필터링하여 자동으로 랜덤 댓글을 남기기 (+랜덤 포인트)

    Date2018.11.18 Category코드 By이니스프리 Views634
    Read More
  14. [Bootstrap] xeACE 레이아웃

    Date2017.09.17 Category자료 Bytitle: 은메달도다 Views633
    Read More
  15. [JS]클라이언트에서 Ip를 얻어보자

    Date2019.01.21 Category코드 ByHanam09 Views625
    Read More
  16. 경험치 현황 위젯

    Date2017.06.28 Category자료 ByNoYeah Views622
    Read More
  17. [PHP] 간단한 캐싱 클래스

    Date2018.12.06 Category코드 Bytitle: 황금 서버 (30일)humit Views605
    Read More
  18. [XE / Rhymix] Bootstrap 패널 위젯 스타일

    Date2017.08.09 Category자료 Bytitle: 은메달도다 Views603
    Read More
  19. [1.8a] Bootstrap 'Panel' 위젯 스타일

    Date2017.08.09 Category자료 Bytitle: 은메달도다 Views602
    Read More
  20. 매우 특이한 버그

    Date2018.06.05 Category코드 Bytitle: 대한민국 국기gimmepoint Views569
    Read More
Board Pagination Prev 1 2 3 4 Next
/ 4