웹 UI 개편 — 사이드바 3단 구조

2026-07-28 · GPTPilots_Webs 전면 개편 + 백엔드 원문 API 신설. HTML 시안으로 여러 차례 확인받은 뒤 실제 코드로 옮김.

왜 바꿨나

기존은 한 방향 마법사였다: 온보딩 → 질문 → 추천목록 → 상세채팅 → 마이페이지. 처음부터 끝까지 순서대로 가야 하고, 중간에 다른 기능으로 못 간다. 게다가 5화면 중 3개가 목업이었고(온보딩·질문지·마이페이지), 화면2의 “자동추론”은 입력을 보지도 않고 고정 칩을 보여주는 가짜였다.

바뀐 구조

사이드바        │ 대화(메인)              │ 문서 원문
──────────────┼────────────────────────┼──────────────
+ 새 대화      │ 활성 문서 A · B · C  + │ [탭 A][탭 B][탭 C]
💬 대화        │                        │
👤 내 회사 프로필│  자유 대화             │  공고 원문 그대로
🎯 공고 추천    │  (문서 지정 없이도 가능) │
활성 문서 A·B·C │                        │  ⇹ 누르면 나란히 비교
[⇹ 나란히 비교] │  [입력창]              │
  • 메인이 자유 대화(ChatGPT/Claude 형태). 사이드바로 다른 기능 전환.
  • 활성 문서 슬롯 A·B·C(최대 3개) — 사이드바·대화 상단·문서 패널 어디서든 +로 담는다.
  • 오른쪽에 진짜 공고 원문이 뜬다. 2개 이상이면 나란히 비교.

설계에서 정한 것

활성 문서 상한 3개 — 비교 화면이 열로 쪼개지는데 4열부터는 원문 한 줄이 너무 좁아 읽을 수 없다. 넘으면 “하나를 비워주세요”로 안내.

슬롯 라벨은 배열 순서에서 파생 — 비우면 뒤가 앞으로 당겨지고, 그 순서가 곧 비교 화면의 열 순서라 사용자가 위치로 문서를 기억할 수 있다.

프로필은 한 페이지에 전부 펼침 — 단계별 마법사를 안 쓴 이유는, 사이드바로 아무 때나 드나드는 구조에서 진행 단계가 있으면 갇힌 느낌이 들고 한 항목만 고칠 때도 번거롭다.

문서 선택기는 화면 중앙 모달 — 트리거가 세 군데(사이드바/대화상단/문서패널)라 각각에 앵커를 맞추면 위치 계산만 늘고, 어디서 열든 같은 자리가 오히려 예측 가능하다.

디자인 토큰은 앱 것을 그대로 — 처음엔 임의 색을 썼다가 지적받고 src/index.css의 실제 토큰으로 교체. 특히 밝기 구조가 반대였다(실제는 사이드바 #f6f6f1 + 메인 #ffffff인데 시안은 그 반대). 폰트도 Playfair(제목)/Geist(본문)/JetBrains Mono로 맞춤.

아이콘은 lucide 단색 라인으로 통일 — 이모지를 쓰다가 “크기·색이 제각각”이라는 지적을 받고 전부 교체. 접힌 레일은 모든 항목 38×38 · 아이콘 18px · 무테, 채워진 주황은 로고 하나뿐이고 선택 상태만 accent 배경으로 구분.

백엔드 추가

GET /rfps/{doc_id}/content — 공고 원문(markdown) 제공. 없던 기능이라 신설.

  • PII 마스킹 적용(mask_text), LLM·임베딩 미경유라 비용 0
  • clean_markdown을 일부러 적용하지 않음 — 이 화면 목적이 “원문 확인”이라 목차·반복 헤더까지 원래 모습대로 보여줘야 한다(클리닝은 인덱싱 전용 변환)

라우트 순서 함정 (실제로 겪음)

@app.get("/rfps/{doc_id:path}")          # ← 이게 먼저면
@app.get("/rfps/{doc_id:path}/content")  # ← 여기 절대 도달 못 함

:path 변환기가 탐욕적이라 "…/content" 까지 doc_id로 삼켜 404가 난다. content 라우트를 단건 조회보다 먼저 등록해야 한다.

파일 구성

파일역할
lib/active-docs-context.tsx활성 문서 A·B·C 슬롯 상태
components/layout/app-sidebar.tsx사이드바(접기·기능·활성문서)
components/doc-panel.tsx원문 패널 + 나란히 비교
components/doc-picker.tsx+ 문서 선택 모달
pages/chat-page.tsx메인 자유 대화
pages/profile-page.tsx프로필 한 페이지 편집
App.tsx셸 + 라우팅(/chat /profile /recommendations)

기존 /rfp/:id 링크로 들어오면 그 공고를 활성 문서로 담고 /chat으로 넘긴다.

시안과 실제가 다른 부분 (미구현)

  • 비교 화면의 차이 자동 하이라이트 없음 — 시안에선 수동으로 칠한 것. 실제로 차이를 찾으려면 LLM 추가 호출이 필요해 보류.
  • 원문에 목차(섹션 점프)·인용 하이라이트 없음 — 섹션 파싱이 필요.
  • 대화는 문서 1개 기준/askdoc_id 하나만 받는다. 활성 문서가 여러 개여도 A 기준으로 답한다.
  • 안 쓰게 된 옛 페이지(onboarding-page questionnaire-page rfp-detail-page my-page top-nav)는 아직 삭제하지 않고 남겨둠.

관련