증분 정적 재생성

Incremental static regeneration

정적 페이지를 캐시해 두고 만료나 무효화 후 새 버전으로 교체합니다.

···
html
<section class="stage"><div class="heading">ISR <span class="hint">cached page refresh</span></div><div class="isr"><div class="clock"><div class="hand"></div><b>TTL</b></div><div class="versions"><div class="tile old">page v1</div><div class="arrow">→</div><div class="tile fresh">page v2</div></div><div class="visitors">visitors <span id="served">v1</span></div></div><div class="caption">Stale page can serve while regeneration runs</div></section>
css
.stage{width:min(94vw,780px);height:min(88vh,322px);padding:clamp(12px,3vmin,20px);border:1px solid var(--line);border-radius:16px;background:var(--surface);box-shadow:0 12px 36px #0001;display:flex;flex-direction:column;gap:clamp(7px,2vmin,14px);font:500 clamp(12px,3.5vmin,17px)/1.3 var(--font-sans,system-ui,sans-serif);overflow:hidden}.heading{display:flex;justify-content:space-between;align-items:center;gap:8px;font-weight:750;color:var(--accent)}.hint{color:var(--muted);font-size:clamp(12px,3.2vmin,14px);font-weight:500}.caption{margin-top:auto;color:var(--muted);font-size:clamp(12px,3.2vmin,14px)}.row{display:flex;gap:clamp(5px,1.5vmin,12px);align-items:center}.tile{padding:clamp(6px,1.8vmin,13px);border:1px solid var(--line);border-radius:9px;background:var(--bg);text-align:center;min-width:0}.arrow{color:var(--accent);font-weight:800}.stage [data-on]{transition:background .3s,border-color .3s,opacity .3s,transform .3s}.stage .on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,var(--surface));color:var(--accent)}.isr{flex:1;display:flex;align-items:center;justify-content:space-around;gap:8px}.clock{width:clamp(46px,12vmin,94px);aspect-ratio:1;border:3px solid var(--accent-3);border-radius:50%;display:grid;place-items:center;position:relative;color:var(--accent-3)}.hand{position:absolute;width:38%;height:2px;background:var(--accent-3);left:50%;top:50%;transform-origin:left;animation:spin 3s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.versions{display:flex;align-items:center;gap:5px}.fresh{opacity:.35}.visitors{border-left:2px solid var(--accent);padding-left:8px}.visitors span{display:block;font-weight:800;color:var(--accent)}.stage[data-step="2"] .fresh{opacity:1;border-color:var(--accent)}.stage[data-step="2"] .old{opacity:.4}.stage small,.stage button,.stage .cards b,.stage .phase b,.stage .pair b,.stage .tree-mini b{font-size:clamp(12px,3.2vmin,14px)!important}
js
const stage=document.querySelector(".stage"),served=document.getElementById("served");let step=0;function tick(){stage.dataset.step=String(step);served.textContent=step===2?"v2":"v1";step=(step+1)%3}tick();let timer=setInterval(tick,1000);stage.addEventListener("pointerdown",()=>{clearInterval(timer);tick()})

증분 정적 재생성(ISR)은 만들어 둔 페이지를 반복 제공하면서 정해진 조건에 따라 새 HTML을 생성합니다. 전체 사이트를 다시 빌드하지 않고 일부 경로만 갱신할 수 있습니다.

재생성 중 오래된 페이지를 제공할지, 새 페이지를 기다릴지는 프레임워크 설정에 따라 다릅니다. 데모는 오래된 버전을 내보내며 뒤에서 갱신하는 방식을 보여줍니다.

언제 쓰나

대부분 정적이지만 변경이 주기적으로 반영되어야 하는 목록·상세 페이지에 사용합니다.

페이지로 열기 ↗