세션 로그 시스템 (stt_dedup·MFCC·캡션) — 코드레벨 동작 흐름 P1코드레벨

마지막 업데이트 2026-07-22

작성일: 2026-06-14 대상: 개발자 — 핑퐁이 세션 로그 저장/조회 파악 핵심 파일: types/db/session-log.types.ts, hooks/use-session-logs.ts, api/session-logs/

개요 · 범위

한 수업의 모든 상호작용(아동 발화·핑퐁이 응답·텍스트 입력·호스트 개입·STT 메타·녹음·오디오 분석·이슈)을 단일 SessionLog 레코드 스트림으로 DynamoDB에 저장하고, 로그 페이지(/main/log)에서 조회·재생한다.

한 테이블, role×type로 구분: 모든 로그가 같은 구조(SessionLogUpdate)를 공유하고 role+type 조합과 선택 필드로 의미가 갈린다. id는 OpenAI item_id 또는 STT request id 등 소스 식별자와 동일 → 전사-오디오 매칭(캡션)에 사용.

데이터 모델 session-log.types.ts

role · type

role대표 type의미
useraudio / text / auto / fallback / stt_dedup아동 발화·입력
assistantaudio / stt_verified핑퐁이 응답(+MFCC 검증)
operatorhost_text / host_mute / host_next_step / host_cancel_ai …호스트 개입
systemaudio(녹음) / audio_analysis녹음·분석 산출물
issue이슈 기록

type별 의미 (헷갈리는 것)

type의미
audio전사된 발화 턴(user/assistant)
auto자동 시작 멘트(AUTO_START_MESSAGE)
fallbackWeb Speech 폴백 전사(#18)
stt_dedupExternal STT dedup 발생 시 원본 텍스트 보존(#4/#9, was_deduped)
stt_verifiedMFCC 검증 통과 턴
audio_analysis오디오 분석 에이전트 결과(별도 문서)

선택 필드 (소스별)

  • 호스트 개입: hostId, interventionType, relatedToLogId(어떤 로그에 대한 개입인지).
  • STT 메타: sttLatencyMs, sttSessionId, sttRequestId, diarization(화자분리 정보).
  • MFCC: mfccRange(MfccRangeSummary: startMs/endMs/detectedEnglish/matchedPatternSequence…), mfccS3Key — assistant+audio 턴에서만.
  • 캡션: captionS3Key — 녹음 로그(role=system, type=audio)에서만(#3).
  • 오디오 분석: audioAnalysisS3Key — role=system, type=audio_analysis에서만.

저장·조회 use-session-logs.ts / api/session-logs/route.ts

  • createLog(logUpdate)POST /api/session-logssetSessionLog(DynamoDB). 세션 매니저(#1)의 데이터채널 이벤트 핸들러가 user/assistant 전사 시 호출.
  • fetchLogs(userId, lessonIndex, activityId, options)GET /api/session-logs?.... 옵션: sortOrder(asc/desc), filterRange(5days/all), includeIssues, issueTextOnly. activityId=null은 문자열 "null"로 전달.
  • updateLogWithIssueTextPOST /api/issue-texts(로그에 이슈 텍스트/카테고리 부착).
  • 녹음 로그: 서버(#3)가 saveRecordingLog로 role=system·type=audio·captionS3Key 레코드 생성. deleteRecordingLog로 S3 동반 삭제.
인증: withAuthMember(치료사 인증) 미들웨어. 조회는 userId+lessonIndex(+activityId) 키 기준.

MFCC 검증 데이터 api/session-logs/[id]/{mfcc,mfcc-upload-url,mfcc-download-url}

핑퐁이 턴의 MFCC(영어 발화 감지 등) 원시 데이터는 로그 본문이 아니라 S3에 저장한다. mfcc-upload-url(presigned 업로드) → mfccS3Key를 로그에 기록 → 조회 시 mfcc-download-url/mfcc로 가져온다. 요약(mfccRange)만 로그 본문에 인라인. MFCC 로직 자체는 MFCC 튜닝·기계음 영어 발화 감지.

로그 페이지 · 재생

  • /main/log(components/pages/session-log.tsx) — 로그 목록·필터·테이블. session-log-table, session-log-floating-player(오디오 재생).
  • 캡션 동기화: 녹음 mp3 재생 시 captionS3Key의 caption.json으로 전사를 위치에 매핑(logId = SessionLog.id 매칭, #3). 오디오↔전사 하이라이트.
  • 필터/개입 로직: entities/session-log/model/{use-session-log-filter,use-session-log-intervention}, 내보내기 features/session-log-export.

함정 · 주의

  • id는 소스 식별자: OpenAI item_id / STT request id 등을 그대로 쓴다(캡션·중복 방지). 임의 생성하면 매칭이 깨진다.
  • type별 선택 필드 제약: mfcc*는 assistant+audio, captionS3Key는 system+audio, audioAnalysisS3Key는 system+audio_analysis에서만. 잘못된 조합으로 저장하면 조회/재생 로직이 못 찾음.
  • stt_dedup는 원본 보존용: 정식 전사(text/audio)와 별도로 dedup 전 원본을 남긴다 → 카운트/표시 시 중복 집계 주의.
  • activityId=null 직렬화: 쿼리에서 문자열 "null"로 전달. 실제 null과 구분되는 약속.
  • 대용량은 S3: MFCC·캡션·분석 원시 데이터는 로그 본문이 아닌 S3. 로그엔 키만. S3 삭제와 로그 삭제 동기화(saveRecordingLog/deleteRecordingLog) 필요.

파일 · 라인 레퍼런스

파일역할
types/db/session-log.types.tsSessionLog/role/type/MfccRangeSummary 모델
hooks/use-session-logs.tscreateLog/fetchLogs/updateLogWithIssueText
api/session-logs/route.tsGET/POST(setSessionLog·saveRecordingLog)
api/session-logs/[id]/mfcc*MFCC S3 업·다운로드
components/pages/session-log.tsx로그 페이지·재생
entities/session-log/model/*, features/session-log-export/필터·개입·내보내기