CQRS

명령·조회 책임 분리

Separate write and read models for different needs.

···
html
<div class="scene"><div class="title">COMMAND → PROJECTION → QUERY</div><div class="row cqrs"><div class="tile">WRITE<br><b id="write">0</b></div><div class="projection"><span class="pulse">→</span><small id="projection">pending</small></div><div class="tile">READ<br><b id="read">0</b></div></div><div class="muted" id="lag">Read model follows the write</div></div>
css
.scene{width:min(94vw,760px);height:min(86vh,320px);padding:clamp(10px,2.5vmin,18px);border:1px solid var(--line);border-radius:14px;background:var(--surface);color:var(--fg);font:500 clamp(11px,1.3vw,16px)/1.25 "Pretendard Variable",Pretendard,-apple-system,sans-serif;display:flex;flex-direction:column;gap:clamp(7px,1.6vmin,12px);overflow:hidden}.scene *{box-sizing:border-box}.title{font-weight:750;color:var(--accent)}.muted{color:var(--muted)}.mono{font-family:ui-monospace,monospace}.row{display:flex;align-items:center;justify-content:center;gap:clamp(5px,1.4vmin,12px);flex:1;min-height:0}.tile{border:1px solid var(--line);border-radius:8px;background:var(--bg);padding:clamp(6px,1.6vmin,12px);text-align:center;min-width:0}.on{border-color:var(--accent)!important;background:color-mix(in srgb,var(--accent) 12%,var(--surface))!important}.pulse{animation:pulse 1.6s infinite alternate}@keyframes pulse{to{border-color:var(--accent);transform:translateY(-3px)}}.cqrs .tile{flex:1}.cqrs b{font:700 1.8em ui-monospace,monospace;color:var(--accent)}.projection{display:grid;text-align:center;color:var(--accent)}.projection small{font-size:1em;color:var(--muted)}
js
let value=0,phase=0;function tick(){if(phase===0){value++;document.getElementById('write').textContent=value;document.getElementById('lag').textContent='Write committed; read still '+(value-1)}if(phase===1){document.getElementById('projection').textContent='applying';document.getElementById('lag').textContent='Projecting change...'}if(phase===2){document.getElementById('read').textContent=value;document.getElementById('projection').textContent='synced';document.getElementById('lag').textContent='Read model caught up'}phase=(phase+1)%3}tick();setInterval(tick,800)

CQRS uses distinct models for commands that change state and queries that read it. Changes to the write model are projected into a read-friendly form.

The demo commits a command before the read view updates after projection. If projection is asynchronous, the interface and failure handling must account for that lag.

When to use

Consider it when write rules and read shapes differ substantially or reads need separate scaling.

Open as page ↗