컴포넌트 합성

Component composition

작은 컴포넌트를 props와 children으로 조합해 큰 UI를 만듭니다.

···
html
<div class="scene"><div class="pieces"><span id="titlePiece">TITLE</span><span id="badgePiece">BADGE</span><span id="bodyPiece">BODY</span></div><div class="frame"><div class="slot" id="titleSlot">title slot</div><div class="slot" id="badgeSlot">badge slot</div><div class="slot" id="bodySlot">children slot</div></div><div class="label" id="status">assembling shared card</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}.pieces{display:flex;gap:5px;justify-content:center}.pieces span{border:1px solid var(--accent);border-radius:5px;color:var(--accent);padding:.2em .35em;font:700 clamp(12px,3vmin,14px) ui-monospace,monospace}.pieces span.used{opacity:.65}.frame{flex:1;min-height:75px;margin:6px 0;border:2px solid var(--line);border-radius:9px;padding:clamp(5px,2vmin,10px);display:grid;grid-template-columns:1fr auto;grid-template-rows:1fr 1fr;gap:5px}.slot{border:1px dashed var(--line);border-radius:5px;display:grid;place-items:center;color:var(--muted);font-size:clamp(12px,3vmin,15px)}.slot.filled{border-style:solid;border-color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,var(--surface));color:var(--fg)}#bodySlot{grid-column:1/3}.label{text-align:center;font-size:clamp(12px,3vmin,15px)}
js
let step=0;const parts=[["titlePiece","titleSlot","PROJECT"],["badgePiece","badgeSlot","ACTIVE"],["bodyPiece","bodySlot","One reusable card, many contents"]];function tick(){step=(step+1)%4;parts.forEach(([piece,slot],i)=>{document.getElementById(piece).classList.toggle("used",i<step);document.getElementById(slot).classList.toggle("filled",i<step);document.getElementById(slot).textContent=i<step?parts[i][2]:["title slot","badge slot","children slot"][i]});document.getElementById("status").textContent=step===3?"card assembled":"assembling shared card"}tick();setInterval(tick,760)

컴포넌트 합성은 한 컴포넌트가 다른 컴포넌트를 렌더하고, children 슬롯에 자식 UI를 전달해 구조를 만드는 방법입니다. 새 화면을 만들 때 공통 틀과 바뀌는 내용을 나누면 중복을 줄일 수 있습니다.

데모는 제목·배지·본문 조각이 카드 슬롯에 차례로 들어가 하나의 결과를 만드는 모습을 보여줍니다. 추상화가 과하면 작은 수정도 여러 파일을 거쳐야 하므로 실제 반복되는 구조에서 추출합니다.

언제 쓰나

여러 화면에 공통 카드·레이아웃 틀이 있고 내용만 달라질 때 사용합니다.

페이지로 열기 ↗