• 목록
  • 아래로
  • 위로
  • 3
  • title: 황금 서버 (30일)humit
  • 조회 수 512
라이선스 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();



이니스프리님 이니스프리 포함 1명이 추천

추천인 1

작성자
title: 황금 서버 (30일)humit 97 Lv. (32%) 757750/768320EXP

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

댓글 3

이니스프리
profile image

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

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

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


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

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

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

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


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

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


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

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

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


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

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

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

comment menu
2018.12.06. 14:28

신고

"이니스프리님의 댓글"

이 댓글을 신고 하시겠습니까?

title: 황금 서버 (30일)humit 작성자 → 이니스프리
profile image
네 일종의 파일 캐시라고 생각하시면 됩니다 ㅎㅎ
comment menu
2018.12.06. 18:47

신고

"humit님의 댓글"

이 댓글을 신고 하시겠습니까?

포인트 폭탄+ → humit
humit님 축하합니다.
추가로 200포인트만큼 포인트 폭탄+를 받았습니다.
comment menu
2018.12.06. 18:47

신고

"포인트 폭탄+님의 댓글"

이 댓글을 신고 하시겠습니까?

삭제

"포인트 폭탄+님의 댓글"

이 댓글을 삭제하시겠습니까?

권한이 없습니다.
번호 분류 제목 글쓴이 날짜 조회 수
56 코드 [JS] http를 https로 리디렉션! 3 Hanam09 Hanam09 18.12.30.08:36 583
55 코드 [PHP] 이미지를 원하는 크기(원본비율 유지)로 리사이즈 하여 출력 (원본 이미지는 수정하지 않습니다) 6 이니스프리 이니스프리 18.12.20.18:42 3668
54 코드 [아미나] 네이트 실시간 검색어 순위 위젯 (아미나 캐시 적용) 3 image 이니스프리 이니스프리 18.12.18.19:28 677
53 코드 [아미나] 출석 여부를 나타내는 메인화면 위젯 4 image 이니스프리 이니스프리 18.12.15.13:44 568
코드 [PHP] 간단한 캐싱 클래스 3 humit title: 황금 서버 (30일)humit 18.12.06.13:41 512
51 코드 [Python] 텔레그램을 이용한 게시판 새 글 알림봇 7 이니스프리 이니스프리 18.12.02.16:25 1919
50 코드 [아미나] 게시글을 작성하면 ID와 IP로 필터링하여 자동으로 랜덤 댓글을 남기기 (+랜덤 포인트) 7 image 이니스프리 이니스프리 18.11.18.06:20 466
49 코드 [PHP] 그누보드 자동 게시글 작성 - 일본기상협회의 우리나라 날씨를 크롤링한 후 파파고로 번역하여 글 작성 4 image 이니스프리 이니스프리 18.11.15.19:58 465
48 코드 [PHP] 기상청 RSS 시간별 예보 위젯 - cache 적용(?) 9 image 이니스프리 이니스프리 18.10.28.11:21 474
47 코드 [오토핫키] 브라우저를 열어 지난번과 동일한 폴더에 MZK를 다운받고 압축을 네이티브로 해제하는 스크립트 image 이니스프리 이니스프리 18.10.20.10:28 550
46 코드 [PHP] 기상청 중기예보를 캐러셀로 보여주는 위젯 (매우 허접합니다 ㅠㅠ) 10 image 이니스프리 이니스프리 18.09.28.20:39 447
45 코드 [오토핫키] 구글 드라이브의 공유링크를 이미지 호스팅을 위한 다이렉트 링크로 바꿔주는 스크립트 10 image 이니스프리 이니스프리 18.09.25.16:54 1232
44 코드 [오토핫키] 특정 사이트에 대한 ping 테스트 결과를 실행시간과 함께 로그 파일로 저장하는 스크립트 2 이니스프리 이니스프리 18.09.22.10:59 920
43 코드 [Python] 모 정부기관 사이트 파싱 후 PC 통신처럼 열람하고 싶은 게시글 번호를 입력하면 내용을 보여주는 소스 (허접) 4 이니스프리 이니스프리 18.09.14.23:31 458
42 코드 파이선 셸에서 실행하면...? 3 제르엘 title: 생일 케이크 (1년권)제르엘 18.07.22.23:54 447
41 코드 C언어 삼중자를 이용한 코드 humit title: 황금 서버 (30일)humit 18.07.22.22:49 362
40 코드 폰트를 자동 설치하는 코드 1 네모 네모 18.07.16.07:21 493
39 코드 잘못 쓰면 컴퓨터가 날아가는 코드 29 제르엘 title: 생일 케이크 (1년권)제르엘 18.07.08.22:36 806
38 코드 매우 특이한 버그 9 title: 대한민국 국기gimmepoint 18.06.05.19:56 510
37 내가 만든 merge sort 3 title: 대한민국 국기gimmepoint 18.05.17.21:27 318