사가는 여러 서비스가 참여하는 업무를 각자의 로컬 트랜잭션으로 나눕니다. 중간 단계가 실패하면 이미 끝난 단계에 대응하는 보상 작업을 실행합니다.
데모에서는 주문과 결제 뒤 배송이 실패해 결제 취소와 주문 취소가 역순으로 진행됩니다. 보상은 과거를 완전히 되돌리는 데이터베이스 롤백과 다르므로 멱등성과 재시도를 고려해야 합니다.
언제 쓰나
하나의 DB 트랜잭션으로 묶을 수 없는 서비스 간 업무 흐름에 사용합니다.
여러 서비스의 작업을 묶고 실패하면 앞선 작업을 보상합니다.
<div class="scene"><div class="title">SAGA: FORWARD / COMPENSATE</div><div class="row saga"><div class="tile" id="order">ORDER</div><span>→</span><div class="tile" id="payment">PAY</div><span>→</span><div class="tile" id="shipping">SHIP</div></div><div class="comp" id="comp">Order → Payment → Shipping</div></div>.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)}}.saga .tile{flex:1}.saga span{color:var(--accent)}.comp{border-left:3px solid var(--accent-3);padding:8px;background:var(--bg)}.fail{border-color:var(--accent-3)!important;color:var(--accent-3)}let step=0;const ids=['order','payment','shipping'];function tick(){ids.forEach((id,i)=>{const el=document.getElementById(id);el.classList.toggle('on',i===step%5);el.classList.toggle('fail',i===2&&step%5===2)});document.getElementById('comp').textContent=['Reserve order','Charge payment','Shipping failed','Refund payment','Cancel order'][step%5];step++}tick();setInterval(tick,800)사가는 여러 서비스가 참여하는 업무를 각자의 로컬 트랜잭션으로 나눕니다. 중간 단계가 실패하면 이미 끝난 단계에 대응하는 보상 작업을 실행합니다.
데모에서는 주문과 결제 뒤 배송이 실패해 결제 취소와 주문 취소가 역순으로 진행됩니다. 보상은 과거를 완전히 되돌리는 데이터베이스 롤백과 다르므로 멱등성과 재시도를 고려해야 합니다.
하나의 DB 트랜잭션으로 묶을 수 없는 서비스 간 업무 흐름에 사용합니다.