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();