PatternsP4 본문

AI Chat

대화형 AI 표면 — 헤더·메시지 스레드·입력 + 대화 상태 매트릭스(빈·대기·생성 중·오류)와 스트리밍 시각 언어. 챗 전용 접근성(role=log·부분 텍스트 비낭독)을 갖춥니다.

마지막 업데이트 2026-06-14

데모#

상단 상태 컨트롤로 빈 화면·대기·생성 중·오류를 전환해 대화 매트릭스를 검수합니다. 추천 칩이나 입력으로 메시지를 보내면 생각 중 → 부분 텍스트 스트리밍 → 안착까지 실제로 재생됩니다(중단 가능). 실제 LLM 호출은 없습니다(UI Reference).

상태
기기
WIZ 어시스턴트대기 중
어시스턴트: 안녕하세요, WIZ 워크스페이스 어시스턴트입니다. 문서 검색·작성·요약을 도와드릴 수 있어요.
오후 2:10
나: 이번 분기 온보딩 프로젝트 회의록 3건 요약해줘.
오후 2:12
어시스턴트: 회의록 3건을 확인했어요. 공통 결론은 “신규 입사자 첫 주 완료율 개선”이고, 핵심 액션은 ① 체크리스트 자동화 ② 멘토 배정 ③ 2주차 피드백 세션입니다.
오후 2:12
나: 그중 ① 체크리스트 자동화 담당자랑 마감일만 표로 정리해줄래?
오후 2:14
어시스턴트: 정리했어요. 체크리스트 자동화는 김도현(플랫폼팀)이 담당하고 마감일은 6월 28일입니다. 선행 작업으로 HR 데이터 연동(이수아, 6월 21일)이 필요해요.
오후 2:14
AI Chat — 상태 매트릭스 + 스트리밍. Enter 전송 · Shift+Enter 줄바꿈

구성#

영역역할
헤더어시스턴트 정체성(Avatar·이름) + 현재 상태(상태 도트·라벨)
스레드role="log" 메시지 로그 — 어시스턴트 좌측 정렬+Avatar, 사용자 우측 primary 버블, 타임스탬프
빈 화면인사 + 추천 프롬프트 칩 — 막다른 길 대신 다음 행동 제시
생성 중thinking 도트 → 부분 텍스트 + 캐럿 스트리밍, 입력은 중단 버튼
오류FormMessage(error)(Tier 2) + 다시 시도
입력AI Chat Input — 전송/중단, Enter 전송·Shift+Enter 줄바꿈

상태#

대화는 행복 경로 하나가 아니라 상태 매트릭스로 다룹니다. 데모의 상태 컨트롤로 전환합니다.

상태트리거표현
빈 화면첫 진입, 0턴인사 + 추천 프롬프트 칩(클릭 시 전송)
대기입력 대기·응답 완료대화 스레드 + 입력 활성, 헤더 “대기 중”
생성 중전송 직후thinking 도트 → 부분 텍스트 스트리밍(캐럿) + 헤더 도트 펄스 + 스레드 aria-busy, 입력은 중단
오류응답 실패FormMessage(error)(Tier 2) + 다시 시도

“생각 중”은 독립 상태가 아니라 생성 중의 첫 페이즈입니다 — 부분 텍스트가 도착하면 같은 버블에서 도트가 텍스트로 교체되고, 중단하면 누적분이 잘린 채 확정됩니다.

메시지 위계 — 3-tier#

메시지 위계가 챗에서 어떻게 나타나는지.

Tier범위컴포넌트이 패턴에서
1 필드입력전송 버튼 비활성빈 메시지 전송 차단(AiChatInput 내장) — 토스트 대신 차단형
2 폼·제출한 번의 전송·응답FormMessage응답 생성 실패 — role="alert" + 다시 시도
3 페이지화면·세션Alert·Toast연결 끊김·서비스 점검 등 전역 장애(여기선 미사용)

적응형 동작#

컨테이너 폭버블
≥ 520px버블 최대폭 70% — 좌우 여백 확보
< 520px버블 최대폭 82cqw — 좁은 폭에서도 가독 유지

스레드는 컨테이너 쿼리로 자기 폭에 반응하며(뷰포트 아님), 새 메시지·스트리밍마다 자동으로 하단 스크롤합니다(포커스 이동 없음). 데모의 기기 컨트롤(데스크탑·태블릿·모바일)로 폭을 제약해 각 기기 레이아웃을 미리볼 수 있고, 터치 기기(태블릿·모바일)에서는 실제 기기처럼 스크롤바 거터를 숨깁니다.

접근성#

계약구현
메시지 로그메시지만 담는 role="log" + aria-live="polite" — 시간순 추가를 polite 전달(assertive는 읽던 내용을 끊어 부적합). 오류 alert·추천 칩은 로그 밖 형제로 둬 이중 낭독 방지
화자 구분각 버블에 보조기술 전용 화자 접두(“나:/어시스턴트:”) — 시각은 정렬·색, 스레드 내 Avatar는 장식이라 aria-hidden
스트리밍 낭독부분 텍스트 버블은 aria-hidden + 스레드 aria-busy="true" — 토큰마다 낭독(잼) 방지, 완성 메시지만 1회 낭독
생각 중도트는 aria-hidden, 진행은 aria-busy로 전달
오류 전달FormMessage(error)role="alert"로 즉시 낭독
입력aria-label="메시지 입력", Enter 전송·Shift+Enter 줄바꿈, 한글 조합 중 Enter 무시
포커스전송 후 입력창 포커스 유지 — 새 메시지가 포커스를 빼앗지 않음
모션thinking 도트·캐럿·펄스·메시지 등장은 transform/opacity만, prefers-reduced-motion에서 정지(텍스트·상태 라벨 유지)

사용 컴포넌트#

AiChatInput · Avatar · Button(다시 시도) · FormMessage(오류, Tier 2) · SegmentedButton(데모 컨트롤). 메시지 버블·스레드·추천 칩은 패턴 전용 표면이며 새 컴포넌트 없이 semantic 토큰으로 구성합니다. 실제 LLM 호출은 없습니다 — UI Reference입니다.