Suspense 데이터 읽기

Suspense data reading

렌더 중 데이터가 아직 준비되지 않으면 가까운 fallback을 보여주고 준비되면 내용을 공개합니다.

···
html
<div class="scene"><div class="title">SUSPENSE BOUNDARY <span id="status">pending</span></div><div class="card"><div id="skeleton"><i></i><i></i><i></i></div><div id="content"><b>Result ready</b><p>Three rows resolved together</p><div class="dots">● ● ●</div></div></div><div class="progress"><span id="progress"></span></div></div>
css
.scene{width:min(94vw,800px);height:min(86vh,320px);position:relative;overflow:hidden;display:flex;flex-direction:column;justify-content:space-between;border:1px solid var(--line);border-radius:14px;background:var(--surface);padding:clamp(9px,2.4vmin,20px);font:500 clamp(15px,4vmin,18px)/1.3 var(--font-sans,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif)}.scene b,.scene strong{font-weight:700}.label{color:var(--muted)}.code{font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.pill{border:1px solid var(--line);border-radius:8px;padding:.4em .65em;background:var(--bg)}.active{border-color:var(--accent)!important;color:var(--accent)!important;background:color-mix(in srgb,var(--accent) 10%,var(--surface))!important}.title{display:flex;justify-content:space-between;font-weight:700}.title span{color:var(--accent)}.card{height:65%;display:grid;place-items:center;border:1px dashed var(--line);border-radius:9px;margin-top:10px}.card>div{width:70%;text-align:center}.card p{margin:.4em 0}.dots{color:var(--accent)}#skeleton i{display:block;height:clamp(10px,3vmin,18px);border-radius:4px;background:var(--line);margin:9px auto}#skeleton i:nth-child(2){width:75%}#skeleton i:nth-child(3){width:50%}#content{display:none}.progress{height:4px;background:var(--line);margin-top:8px}.progress span{display:block;width:0;height:100%;background:var(--accent);transition:width .3s}
js
let n=0;function tick(){const ready=n%4>=2;document.getElementById("skeleton").style.display=ready?"none":"block";document.getElementById("content").style.display=ready?"block":"none";document.getElementById("status").textContent=ready?"resolved":"pending";document.getElementById("progress").style.width=(ready?100:(n%4+1)*25)+"%";n++}tick();setInterval(tick,700)

Suspense는 렌더 중 대기하는 자식 UI를 경계로 감쌉니다. 데이터 소스가 Suspense를 지원하면 준비될 때까지 fallback을 보여줄 수 있습니다.

데모는 카드의 스켈레톤이 데이터가 도착하며 실제 행으로 교체되는 과정을 보여줍니다. Effect 안에서 시작한 임의의 fetch만으로는 Suspense가 자동 작동하지 않습니다.

언제 쓰나

코드 분할이나 Suspense 지원 데이터 소스의 로딩 경계를 설계할 때 사용합니다.

페이지로 열기 ↗