HTTP 캐시 제어

HTTP cache control

Cache-Control 지시문이 저장된 응답의 재사용 시점과 재검증을 결정합니다.

···
html
<div class="n-demo"><div class="n-head"><strong>CACHE FRESHNESS TIMELINE</strong><span>LIVE TRACE</span></div><div class="n-stage"><div class="cc"><div class="cc-label"><span>0s</span><span>max-age=60</span><span>90s</span></div><div class="cc-track"><div class="cc-fresh"></div><i id="cc-cursor"></i></div><div class="cc-result"><b id="cc-time">t = 20s</b><span id="cc-answer">CACHE HIT</span></div></div></div><div class="n-foot">tap to step · auto replay</div></div>
css
.n-demo{width:min(94vw,760px);height:min(88vh,324px);padding:clamp(9px,2.2vmin,18px);border:1px solid var(--line);border-radius:13px;background:var(--surface);display:flex;flex-direction:column;gap:clamp(5px,1.3vmin,10px);font:600 clamp(12px,2.4vmin,16px)/1.3 "Pretendard Variable",Pretendard,-apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo",sans-serif;overflow:hidden}.n-head,.n-foot{display:flex;justify-content:space-between;align-items:center;color:var(--muted)}.n-head strong{color:var(--accent)}.n-head span,.n-foot{font-size:12px}.n-stage{flex:1;min-height:0;position:relative;display:flex;align-items:center;justify-content:center;gap:clamp(4px,1vmin,10px)}.mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.n-box{padding:clamp(5px,1.5vmin,11px);border:1px solid var(--line);border-radius:8px;background:var(--bg);text-align:center}.n-on{border-color:var(--accent)!important;color:var(--accent)!important;background:color-mix(in srgb,var(--accent) 12%,var(--surface))!important}.n-muted{color:var(--muted)}@media(max-width:400px){.n-head span{display:none}}.cc{width:94%;display:grid;gap:13px}.cc-label{display:flex;justify-content:space-between;color:var(--muted);font-size:12px}.cc-track{height:25px;border:1px solid var(--line);border-radius:6px;background:var(--bg);position:relative}.cc-fresh{width:67%;height:100%;background:color-mix(in srgb,var(--accent) 28%,var(--bg));border-right:2px dashed var(--accent)}#cc-cursor{position:absolute;top:-7px;left:22%;width:5px;height:39px;background:var(--accent-3);border-radius:3px;transition:left .45s}.cc-result{display:flex;justify-content:space-between;gap:8px}.cc-result span{color:var(--accent)}
js
let step=0;function advance(){const times=[20,45,65,90],left=[22,50,72,96];document.getElementById('cc-cursor').style.left=left[step]+'%';document.getElementById('cc-time').textContent='t = '+times[step]+'s';document.getElementById('cc-answer').textContent=times[step]<=60?'CACHE HIT':'REVALIDATE';step=(step+1)%times.length}
const clickTarget=document.querySelector('.n-demo');if(clickTarget&&typeof advance==='function'){advance();const timer=setInterval(advance,1050);clickTarget.addEventListener('pointerdown',()=>{clearInterval(timer);advance()})}

서버는 Cache-Control 헤더로 응답을 얼마나 오래 새것으로 취급할지 알립니다. max-age 동안은 저장된 응답을 바로 쓸 수 있고, 만료 후에는 서버에 재검증하거나 새 응답을 받아야 합니다.

데모는 시간 커서가 신선도 경계를 넘을 때 캐시 히트가 재검증으로 바뀝니다. 개인화된 응답에는 공유 캐시 저장 가능 여부를 별도로 정해야 합니다.

언제 쓰나

정적 자산과 API 응답의 지연·원본 부하를 줄일 때 저장 범위와 만료 시간을 설계합니다.

페이지로 열기 ↗