Skip to content

라이브 면접 렌더 경로 메모화 — 델타 1토큰당 리렌더를 변경분만으로 축소 - #202

Merged
Jaeho-Site merged 3 commits into
devfrom
perf/live-interview-render
Aug 22, 2026
Merged

라이브 면접 렌더 경로 메모화 — 델타 1토큰당 리렌더를 변경분만으로 축소#202
Jaeho-Site merged 3 commits into
devfrom
perf/live-interview-render

Conversation

@Jaeho-Site

Copy link
Copy Markdown
Contributor

꼬리질문 델타는 토큰 단위로 초당 수십 건 도착하는데, 프론트 렌더 경로가 이를 증폭시켰다.

  • useLiveInterviewuseMemo 가 하나도 없어 델타 1토큰마다 정렬(O(n log n))·병합·items 배열/객체 전체 재생성을 반복했고, 반환 콜백 4개도 렌더마다 새 함수였다.
  • frontend/src 전체에 React.memo 가 0건 — 델타 1토큰마다 InterviewStage 서브트리 전체(웹캠 비디오, 답변 컴포저, 아바타)가 리렌더되고, 기록 드로어를 열면 버블 N개 전원이 리렌더됐다. 버블마다 mutation·오디오 훅이 붙어 있어 비용이 메시지 수에 비례한다.
  • FeedbackReport 는 매 렌더 새 highlightTerms 배열을 만들어 HighlightedText 8곳의 useMemo([terms])항상 미스 — Set 생성·sort·RegExp 재컴파일이 반복됐다.

무엇

  1. useLiveInterview 메모화 — 정렬·병합·파생값을 useMemo 로, 콜백을 useCallback(구조 분해한 mutate/refetch deps)으로. 핵심은 baseItems(델타 무관) / items(델타 오버레이) 2단 분리: 델타 1건당 스트리밍 중인 메시지 1개만 새 객체가 된다. 낙관적 항목에 델타가 붙지 않는 전제(id 없음)는 주석으로 명시.
  2. React.memo 7개 — QuestionBubble·AnswerBubble·ConversationThread·StageQuestion·WebcamSelfView·AnswerComposer·InterviewerAvatar. 1의 참조 안정화가 전제라 같은 PR 이다.
  3. FeedbackReport·InterviewTranscript — highlightTerms useMemo, 트랜스크립트 정렬 useMemo 호이스트.

측정 (계측 테스트로 재현 가능 — 커밋에 포함)

FakeWS 로 SESSION_MESSAGE_DELTA 를 주입하는 훅 하니스 + 버블 본문 실행 카운터 하니스:

지표 before after
델타 1건당 참조 유지 item 0 / 21 20 / 21
무관한 리렌더 시 items 배열 전부 재생성 참조 그대로
반환 콜백 4개 렌더마다 새 함수 고정
동일 items 부모 리렌더 시 버블 재실행 20 / 20 0 / 20
델타로 item 1개 변경 시 전부 1 / 20

즉 델타 1토큰의 렌더 영향이 "스테이지 전체 + (드로어 열림 시) 버블 전원" 에서 변경된 질문 카드 하나로 줄어든다. 하니스는 회귀 가드로 커밋했다 (memo 나 참조 안정성이 깨지면 빨간불).

검증

  • npm run test 143/143, npm run build 성공(메인 청크 +0.47kB — memo 래퍼), npm run lint 에러·경고 0 (exhaustive-deps 포함).
  • memo 로 인한 갱신 누락 여부는 콜 사이트 단위로 점검 — 버블의 북마크 상태·StageQuestion 의 speaking 등은 모두 props/원시값으로 흐르고, wasSegmented 는 ref 를 호출 시점에 읽어 stale 없음.

- useLiveInterview 가 매 렌더 정렬·병합·items 를 재계산하고 반환 콜백도
  렌더마다 새로 만들어, 델타 1토큰마다 스테이지 전체가 재계산·리렌더됐다
- 정렬(serverMessages)·pending·items 를 useMemo 로, submitVoice·endSession·
  interruptSession·refetchSession 을 useCallback 으로 안정화
- baseItems(델타 무관)/items(델타 오버레이) 2단 분리 — 델타 1건당 스트리밍
  중인 메시지 1개만 새 객체 (참조 유지 0/21 → 20/21)
- FakeWS 델타 주입 계측 테스트 3케이스 (참조 안정성 회귀 가드)
- 델타 1토큰마다 InterviewStage 서브트리 전체(웹캠·컴포저·아바타)와
  드로어의 버블 전원이 리렌더되던 것을 변경분만 렌더하도록 축소
- QuestionBubble·AnswerBubble·ConversationThread·StageQuestion·
  WebcamSelfView·AnswerComposer·InterviewerAvatar memo 래핑
  (props 참조 안정화는 선행 커밋의 useLiveInterview 메모화가 전제)
- 훅 카운터 계측 테스트 2케이스 — 동일 참조 리렌더 시 버블 재실행 0/20,
  델타 1건 시 1/20 만 재실행
- FeedbackReport 가 매 렌더 새 highlightTerms 배열을 만들어 HighlightedText
  8곳의 useMemo([terms])가 항상 미스 — Set 생성·sort·RegExp 재컴파일 반복
- InterviewTranscript 의 메시지 정렬을 useMemo 로 호이스트해 memo 버블이
  참조 유지로 리렌더를 건너뛸 수 있게 함
@Jaeho-Site
Jaeho-Site merged commit 062a1a8 into dev Aug 22, 2026
5 checks passed
@Jaeho-Site
Jaeho-Site deleted the perf/live-interview-render branch August 22, 2026 11:58
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