옵티미스틱 UI

Optimistic UI

서버 응답을 기다리지 않고 성공할 거라 가정해 화면을 먼저 바꾸는 패턴. 실패하면 그때 되돌립니다.

다른 이름: Optimistic updateOptimistic rendering
···
html
<div class="stage">
  <div class="pane"><div class="tag">✗</div>
    <button class="like" id="b1"><span class="ic">♥</span></button>
    <div class="spin" id="s1"></div>
  </div>
  <div class="pane"><div class="tag">✓</div>
    <button class="like" id="b2"><span class="ic">♥</span></button>
    <div class="check" id="s2">✓</div>
  </div>
</div>
css
.stage{width:94%;height:88%;display:flex;gap:6%}
.pane{position:relative;flex:1;border-radius:14px;border:1px solid var(--line);background:var(--surface);display:grid;place-items:center;gap:10px;overflow:hidden}
.tag{position:absolute;top:8px;left:10px;font:700 12px/1 monospace;color:var(--muted)}
.like{width:54px;height:54px;border-radius:50%;border:1px solid var(--line);background:var(--bg);display:grid;place-items:center}
.ic{font-size:22px;color:var(--muted);transition:color .1s}
.like.on .ic{color:var(--accent-2)}
.spin{width:14px;height:14px;border-radius:50%;border:2px solid var(--line);border-top-color:var(--accent);opacity:0}
.spin.show{opacity:1;animation:spin .6s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.check{font:700 14px/1 monospace;color:var(--accent-3);opacity:0}
.check.show{opacity:1}
js
const b1 = document.getElementById('b1'), s1 = document.getElementById('s1');
const b2 = document.getElementById('b2'), s2 = document.getElementById('s2');
function cycleSlow() {
  s1.classList.add('show');
  setTimeout(() => { b1.classList.add('on'); s1.classList.remove('show'); }, 1300);
  setTimeout(() => { b1.classList.remove('on'); }, 2600);
}
function cycleFast() {
  b2.classList.add('on');
  setTimeout(() => { s2.classList.add('show'); }, 120);
  setTimeout(() => { s2.classList.remove('show'); }, 900);
  setTimeout(() => { b2.classList.remove('on'); }, 2600);
}
cycleSlow(); cycleFast();
setInterval(() => { cycleSlow(); cycleFast(); }, 3000);

전통적인 방식은 요청 → 로딩 스피너 → 응답 → 화면 갱신입니다. 옵티미스틱 UI는 성공 확률이 매우 높은 동작(좋아요, 체크박스)에 한해 **요청과 동시에 화면부터 갱신**하고, 실패한 드문 경우에만 되돌리며 에러를 보여줍니다.

Doherty 임계값(→ doherty-threshold)과 맞닿아 있습니다 — 체감 지연이 0에 가까워지면 사용자는 앱이 "즉각 반응한다"고 느낍니다. Slack·Twitter/X의 좋아요·반응 버튼이 대표 사례입니다.

데모의 왼쪽은 스피너를 기다린 뒤 채워지고, 오른쪽은 누르자마자 채워진 뒤 조용히 서버 확인을 마칩니다.

언제 쓰나

실패 확률이 낮고 되돌리기 쉬운 동작(좋아요, 토글, 장바구니 담기)에 씁니다. 결제·삭제처럼 되돌리기 어려운 동작엔 쓰지 마세요.