웹 개발 시 브라우저 캐시로 인해 최신 데이터가 표시되지 않거나, 반대로 캐시되지 말아야 할 민감한 데이터가 캐시되는 문제가 발생할 수 있습니다. 상황에 따른 적절한 캐시 제어 방법을 알아보겠습니다.
<?php
// 모든 캐시 비활성화
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
// 민감한 데이터 출력
echo json_encode(['user_data' => $sensitive_data]);
?>
<?php
// 1년간 캐시 (정적 리소스용)
$expire_time = 60 * 60 * 24 * 365; // 1년
header('Cache-Control: public, max-age=' . $expire_time);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expire_time) . ' GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime(__FILE__)) . ' GMT');
// CSS, JS, 이미지 파일 등 출력
readfile('style.css');
?>
<?php
$data = ['timestamp' => time(), 'content' => 'some data'];
$etag = md5(serialize($data));
header('ETag: "' . $etag . '"');
// 클라이언트의 ETag와 비교
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === '"' . $etag . '"') {
header('HTTP/1.1 304 Not Modified');
exit;
}
header('Content-Type: application/json');
echo json_encode($data);
?>
<?php
$file_path = 'data.json';
$last_modified = filemtime($file_path);
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $last_modified) . ' GMT');
// 클라이언트의 If-Modified-Since와 비교
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
$client_modified = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
if ($client_modified >= $last_modified) {
header('HTTP/1.1 304 Not Modified');
exit;
}
}
readfile($file_path);
?>
<?php
function getAssetUrl($file) {
$version = filemtime($file);
return $file . '?v=' . $version;
}
// HTML에서 사용
?>
<link rel="stylesheet" href="<?php echo getAssetUrl('css/style.css'); ?>">
<script src="<?php echo getAssetUrl('js/app.js'); ?>"></script>
<?php
session_start();
// 로그인한 사용자는 캐시 비활성화
if (isset($_SESSION['user_id'])) {
header('Cache-Control: private, no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
} else {
// 비로그인 사용자는 짧은 캐시 허용
header('Cache-Control: public, max-age=300'); // 5분
}
echo $content;
?>
<?php
function sendApiResponse($data, $cache_duration = 0) {
header('Content-Type: application/json');
if ($cache_duration > 0) {
header('Cache-Control: public, max-age=' . $cache_duration);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cache_duration) . ' GMT');
} else {
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
}
echo json_encode($data);
}
// 사용 예시
sendApiResponse($user_data, 0); // 캐시 안함
sendApiResponse($static_data, 3600); // 1시간 캐시
?>
<?php
class CacheControl {
public static function noCache() {
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
}
public static function longCache($seconds = 86400) {
header('Cache-Control: public, max-age=' . $seconds);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $seconds) . ' GMT');
}
public static function privateCache($seconds = 300) {
header('Cache-Control: private, max-age=' . $seconds);
}
}
// 사용 예시
CacheControl::noCache(); // 관리자 페이지
CacheControl::longCache(604800); // 정적 리소스 (1주일)
CacheControl::privateCache(600); // 사용자별 데이터 (10분)
?>
no-cache, no-store
설정