생각 중 인디케이터

Thinking indicator

모델이 답을 내기 전 추론 과정을 샤머링 텍스트로 흘려 보여주고, 끝나면 "N초간 생각함"으로 접히는 영역.

다른 이름: Reasoning traceChain-of-thought disclosure
···
html
<div class="wrap">
  <div class="think" id="th">
    <button class="head" id="hd"><i class="chev">▸</i><span id="label">생각 중</span><span class="shine" id="shine"></span></button>
    <div class="body" id="body"><p id="ptxt">검색 결과를 비교하는 중…</p></div>
  </div>
</div>
css
.wrap{width:min(300px,92%)}
.think{border:1px solid var(--line);border-radius:12px;background:var(--surface);overflow:hidden}
.head{width:100%;display:flex;align-items:center;gap:7px;padding:9px 12px;border:0;background:none;cursor:pointer;color:var(--muted);font-size:12px;font-weight:600;text-align:left}
.chev{font-style:normal;font-size:10px;transition:transform .2s}
.think[data-open] .chev{transform:rotate(90deg)}
.shine{margin-left:auto;width:0;height:0}
.body{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s ease}
.think[data-open] .body{grid-template-rows:1fr}
.body p{overflow:hidden;min-height:0;margin:0;padding:0 12px;font-size:11px;color:var(--muted);line-height:1.6}
.think[data-open] .body p{padding-bottom:10px}
#label.shimmer{background:linear-gradient(90deg,var(--muted) 0%,var(--fg) 50%,var(--muted) 100%);background-size:200% auto;
  -webkit-background-clip:text;background-clip:text;color:transparent;animation:shim 1.6s linear infinite}
@keyframes shim{to{background-position:-200% 0}}
js
const th = document.getElementById('th'), label = document.getElementById('label'), ptxt = document.getElementById('ptxt');
const steps = ['후보 답변을 비교하는 중…', '근거를 다시 확인하는 중…', '결론을 정리하는 중…'];
th.setAttribute('data-open', '');
label.classList.add('shimmer');
let i = 0;
const iv = setInterval(() => { ptxt.textContent = steps[i % steps.length]; i++; }, 700);
setTimeout(() => {
  clearInterval(iv);
  label.classList.remove('shimmer');
  label.textContent = '4초간 생각함';
  th.removeAttribute('data-open');
  setTimeout(restart, 2200);
}, 2600);
function restart() {
  label.textContent = '생각 중';
  label.classList.add('shimmer');
  th.setAttribute('data-open', '');
  let j = 0;
  const iv2 = setInterval(() => { ptxt.textContent = steps[j % steps.length]; j++; }, 700);
  setTimeout(() => {
    clearInterval(iv2);
    label.classList.remove('shimmer');
    label.textContent = '4초간 생각함';
    th.removeAttribute('data-open');
    setTimeout(restart, 2200);
  }, 2600);
}

추론 모델은 최종 답을 내기 전에 중간 사고 과정을 토큰으로 생성합니다. 그 과정을 통째로 숨기면 대기 시간이 길게만 느껴지고, 통째로 최종 답과 같은 무게로 보여주면 정작 결론을 찾기 어려워집니다. 절충안이 이 패턴입니다 — 진행 중엔 요약 문구("검색 결과 비교 중…")가 흐릿하게 반짝이며 무언가 진행되고 있음을 보여주고, 끝나면 한 줄 요약("4초간 생각함")으로 접혀서 원하면 펼쳐 볼 수 있는 부가 정보가 됩니다.

타이핑 인디케이터와는 목적이 다릅니다 — 점 세 개는 "곧 시작한다"는 신호일 뿐 내용이 없지만, 생각 중 인디케이터는 실제 중간 추론 텍스트(짧더라도)를 담고 있어서 오래 걸리는 이유를 부분적으로 설명해 줍니다.

추론 내용을 펼쳤을 때는 실제 모델 출력을 보여주거나, 최소한 그 순서를 반영해야 합니다 — 진행 상황과 무관한 장식용 문구를 무작위로 띄우면 사용자가 나중에 "그때 그건 거짓이었다"는 걸 알아채고 신뢰가 깨집니다.

언제 쓰나

추론에 몇 초 이상 걸리는 모델·에이전트 흐름에 씁니다. 즉답이 가능한 짧은 질문에는 오히려 과장된 연출로 보입니다.