Chainlit과 대화 UI: 사용자에게 보이는 운영 계약
Chainlit은 Python 대화 앱의 UI, 세션, 단계 표시를 구성하는 사용자 접점이다. 검색기, 모델 서버, 업무 권한 저장소와는 역할이 다르다.
도입 전 확인한 프로젝트 상태
2026-10-25 확인한 공식 문서는 Chainlit이 archived 상태이고 버그 수정, 보안 업데이트, 지원이 중단되었다고 안내한다. 따라서 Bookway 신규 운영의 기본 UI로 채택하지 않고, 책의 구조와 기존 시스템을 해석하는 대상으로 둔다. 계속 사용한다면 자체 유지보수, 취약점 대응 책임이 필요하다.
새 UI는 유지보수되는 웹 프레임워크와 API/SSE 조합 등으로 선택할 수 있다. 어떤 UI를 쓰든 아래 계약은 같다.
로그인, 세션
→ 질문 POST / request_id
→ 서버 인증, 권한 검사
→ 검색, 생성 이벤트 스트림
→ 최종 답, 출처, release_id
→ 피드백 / trace 연결Bookway의 화면과 서버 경계
| 화면 요소 | 서버의 책임 | 잘못된 처리 |
|---|---|---|
| 내 주문 조회 | 로그인 고객의 소유권 검사 | 입력한 고객 ID를 그대로 신뢰 |
| 생성 중 표시 | 요청, 취소, 완료 상태 | 연결 종료를 업무 취소로 간주 |
| 출처 카드 | 허용된 원문, 정확한 source ID | 내부 저장소 주소 직접 노출 |
| 반품 승인 | 고정 행동 초안, 만료 | 프론트에서만 승인 여부 검사 |
| 좋아요/오류 신고 | trace, release, 유형 연결 | 사용자 평가만으로 즉시 재학습 |
UI 세션은 서버 인증과 같지 않는다. 세션 ID가 유출되거나 다른 고객의 thread를 요청해도 서버가 접근을 거절해야 한다. 이전 대화 저장은 보존 기간, 삭제, 동의를 포함한다.
스트리밍과 실패 표시
LLM 토큰이 도착했다는 사실과 검증된 답이 완성됐다는 사실을 구분한다. 구조화된 JSON이 필요한 경로에서는 전체 파싱, 검증 후 확정 응답을 내는 편이 단순할 수 있다. 스트리밍 중 출력 가드레일을 적용한다면 조각 경계, 지연, 이미 전송한 정보의 회수 불가를 고려한다.
SSE/WebSocket 재연결은 새 환불 거래를 만들지 않는다. request ID로 이전 처리 상태를 조회하고, 외부 부작용은 업무 키로 중복 방지한다. 검색 장애는 “자료에 답이 없음”과 다르게 안내하며, 내부 예외, 비밀값은 브라우저로 보내지 않는다.
관측과 교체
사용자가 기다린 TTFT, 전체 시간, 이탈, 재요청을 앱 trace와 연결한다. Chainlit에서 다른 UI로 옮겨도 서비스 API와 thread, 출처 계약을 유지하면 검색, 생성 코드를 그대로 재사용할 수 있다. UI 변경과 프롬프트 변경을 한 release에 섞으면 회귀 원인을 좁히기 어렵다.