Skip to content

워크스페이스 분석 SSE 단절 대응 — 배너·폴백 폴링·진행 문구 TTL - #203

Merged
Jaeho-Site merged 3 commits into
devfrom
feat/workspace-stream-resilience
Aug 22, 2026
Merged

워크스페이스 분석 SSE 단절 대응 — 배너·폴백 폴링·진행 문구 TTL#203
Jaeho-Site merged 3 commits into
devfrom
feat/workspace-stream-resilience

Conversation

@Jaeho-Site

Copy link
Copy Markdown
Contributor

분석 상태는 SSE(/realtime/stream/me) 푸시로만 갱신되는데, 이 스트림이 죽으면:

  • 사용자는 아무것도 모른다useEventStream 이 연결 상태를 노출하지 않고 조용히 백오프 재연결만 했다.
  • 목록 갱신 경로가 0개다 — 목록 쿼리에 폴링이 없고 refetchOnWindowFocus 도 전역 비활성. 카드가 '분석 중' 배지로 새로고침 전까지 영구 고착.
  • 진행 문구도 고착된다 — 전역 progress Map 에 TTL 이 없어 종료 이벤트(DOC_STATE) 유실 시 '임베딩하는 중…' 이 영원히 남고, 같은 문서를 재분석하면 이전 세션 문구가 되살아난다.

라이브 면접 WS 는 상태 배너가 있는데 워크스페이스 SSE 만 이 대우를 못 받았다. 문서(frontend/CLAUDE.md §10)는 '폴링 fallback' 이 이미 있는 것처럼 기술돼 있었지만 실제로는 없었다.

무엇

  1. useEventStream 이 연결 상태를 반환 (connecting|open|closed). 끊긴 뒤 재시도 중에도 closed 를 유지해 배너가 깜빡이지 않는다. 언마운트 후 늦게 실패한 토큰 발급이 StrictMode 재마운트의 새 effect 상태를 오염시키지 않도록 cancelled 가드를 전 분기 통일.
  2. 단절 배너ConnectionBannerfeatures/interviewshared/ui 로 승격(문구 prop 화). 워크스페이스는 closed 일 때만 표시(최초 연결은 정상 부팅 구간이라 조용히), 면접 화면은 기존 문구 그대로 재사용.
  3. 폴백 폴링workspaceStreamHealth store: 스트림이 죽은 동안만 이력서·레포·자소서 목록 쿼리가 5s 폴링 (api-conventions §9 의 'SSE 우선, 끊기면 폴링 fallback' 규약을 실제로 구현). 워크스페이스 언마운트 시 idle 복귀 — 다른 화면에서 오폴링하지 않는다.
  4. 진행 문구 TTL — 90s 무갱신 항목을 15s 스위퍼가 걷어낸다(진행 이벤트는 분석 중 수 초 간격 — 90s 침묵 = 유실). 고착·부활 버그 제거.
  5. 문서 정정 — '폴링 fallback' 허위 기술과 'WebSocket 미사용' stale 기술(실제는 SSE+WS 병행)을 실구현에 맞게 갱신.

검증

  • 신규 테스트 11케이스: 상태 전이·언마운트 레이스 / TTL 만료·생존·구독 알림 / 폴링 스위치 / 배너 렌더.
  • npm run test 154/154, npm run build 성공(청크 +1.15kB), npm run lint 0.
  • 실서버 단절 시나리오는 FakeEventSource 단위 테스트로 대체 — TTL 90s 는 상수 하나로 조정 가능.

- 분석 상태 SSE 가 끊겨도 무통보였고 목록 갱신 경로가 0개라
  카드가 '분석 중'으로 영구 고착됐다 (focus refetch 전역 비활성 + 폴링 없음)
- useEventStream 이 연결 상태(connecting|open|closed)를 반환 — 끊긴 뒤
  재시도 중에도 closed 를 유지해 배너 깜빡임을 방지, 언마운트 후
  늦은 토큰 실패가 새 effect 를 오염시키지 않게 cancelled 가드 통일
- ConnectionBanner 를 shared/ui 로 승격(문구 prop 화)하고 워크스페이스는
  closed 일 때만 표시, 면접 화면은 기존 문구로 재사용
- workspaceStreamHealth store 신설 — 스트림이 죽은 동안만 이력서·레포·자소서
  목록 쿼리가 5s 폴백 폴링 (api-conventions §9), 워크스페이스 밖에선 idle
- 상태 전이·언마운트 레이스·폴링 스위치·배너 테스트 8케이스
- 전역 progress Map 에 만료가 없어 종료 이벤트(DOC_STATE) 유실 시
  '임베딩하는 중…' 문구가 영구 고착되고, 같은 문서를 재분석하면
  이전 세션 문구가 되살아났다
- 항목에 updatedAt 을 기록하고 90s 무갱신 시 15s 스위퍼가 걷어낸다
  (진행 이벤트는 분석 중 수 초 간격 — 90s 침묵은 유실로 판단)
- 스토어가 비면 스위퍼 정지 (set/clear/sweep 모두), 테스트 3케이스
- '폴링 fallback' 이 구현된 것처럼 기술돼 있었으나 실제로는 없었다 —
  이번에 도입된 단절 시 5s 폴백 폴링·연결 상태 반환으로 갱신
- §10 'WebSocket 미사용' 도 stale — SSE+WS 병행(라이브 면접 WS) 사실로 정정
@Jaeho-Site
Jaeho-Site merged commit 427d9bf into dev Aug 22, 2026
5 checks passed
@Jaeho-Site
Jaeho-Site deleted the feat/workspace-stream-resilience branch August 22, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant