대화 히스토리 — 세션 목록·삭제

2026-07-29 · 사이드바 UI 개편 이후 실사용 피드백으로 추가. 브랜치: GPTPilots_Webs feat/sidebar-chat-ui(push 완료).

지적받은 문제

사이드바에 있던 큰 “새 대화” 버튼과 “대화” 탭이 사실상 같은 동작(그냥 /chat 이동)이라 화면에 똑같은 게 두 번 보이는 게 이상하다는 피드백. 원래 설계(HTML 시안 단계)엔 “최근 대화” 목록도 있었는데, 실제 구현 때는 활성 문서(A·B·C) 기능만 만들고 대화 히스토리 자체는 빠뜨렸었음 — 그래서 “새 대화” 버튼이 진짜 “새로 시작”이라는 의미 없이 그냥 자리만 차지하고 있었던 것.

해결 — 진짜 세션 개념 도입

lib/chat-sessions-context.tsx 신설. 예전엔 대화 상태(useChat 훅)가 화면 컴포넌트 안에 있어서 세션이라는 개념 자체가 없었다(항상 “지금 이 대화 하나”만 존재). 이제 여러 개의 대화를 배열로 로컬 저장(localStorage)하고, 그중 하나를 “현재”로 가리키는 구조로 바꿈.

세션 1개 = { id, title, messages[], activeDocId, updatedAt }
  • 제목 자동 생성 — 첫 사용자 메시지를 28자로 잘라서 씀(클로드·챗지피티 방식)
  • “새 대화”는 이제 진짜 의미가 생김 — 빈 세션을 만들어 현재로 전환. 사이드바 맨 위 큰 버튼 대신, “최근 대화” 섹션 헤더 옆 작은 아이콘으로 압축
  • “대화” 탭은 그대로 둠 — 지금 보던 세션을 계속 보여주는 것뿐이라 새 대화 버튼과 역할이 겹치지 않게 됨

활성 문서 전환 시 동작도 같이 개선

예전(활성 문서 컨텍스트만 있던 시절)엔 활성 문서(A)가 바뀌면 대화를 그냥 초기화(reset())했음 — 하던 대화가 통째로 사라짐, 되돌아갈 방법 없음.

이제는:

  • 지금 세션이 아직 빈 상태(메시지 없음)면 → 그냥 문서만 갈아끼움(세션 안 늘림)
  • 지금 세션에 이미 대화 내용이 있으면 → 그 대화는 히스토리에 그대로 보존하고, 새 문서로 새 세션을 시작함

즉 이전엔 “활성 문서를 바꾸면 대화가 사라짐”이었는데, 이제는 “활성 문서를 바꾸면 지금 대화는 저장되고 새 대화가 시작됨”으로 바뀜 — 데이터 손실이 없어졌다는 게 핵심 개선점.

삭제 기능

각 “최근 대화” 항목에 마우스를 올리면 우측에 X 버튼이 나타남(활성 문서 슬롯의 비우기 버튼과 같은 상호작용 패턴). 지금 보고 있는 대화를 지우면 자동으로 다음으로 최근인 대화로 전환되고, 남은 대화가 하나도 없으면 첫 진입 화면으로 돌아감.

설계 판단 메모

  • 저장 위치는 localStorage(세션스토리지가 아니라 로컬스토리지) — 추천 캐시(공고 추천 — 로딩 개선(캐시·스트리밍·후보수))는 탭 닫으면 사라지는 세션스토리지를 쓰지만, 대화 히스토리는 브라우저를 껐다 켜도 남아있어야 “히스토리”라는 이름에 맞다고 판단해서 다르게 선택함. ⚠️ 브라우저 프로필/기기 간 동기화는 안 됨(서버 저장이 아니므로) — 다른 브라우저· 다른 컴퓨터에서는 히스토리가 안 보임. 여러 사람이 같이 쓸 계획이면 서버 쪽 저장으로 옮겨야 함.
  • 세션 상한 30개 — 무한정 쌓이지 않게 제일 오래된 것부터 버림. NDA 데이터를 다루는 서비스라 로컬에 무한정 쌓아두는 것도 좋지 않다고 판단.
  • 백엔드 확장 없이 프론트만으로 구현 — 대화 자체(메시지 내용)는 원래도 프론트가 들고 있던 것(백엔드 /ask는 매 요청마다 history[]를 통째로 받는 무상태 API)이라, 여러 세션을 저장하는 것도 순수 프론트 상태 관리만으로 충분했음. 백엔드 변경 없음.

관련