마지막 업데이트 2026-07-22
기획자(PO) 관점의 요구사항을 Claude Code로 코드레벨 반영한 커밋. 오디오 분석 에이전트가 아동 발화를 오인식(high)했다고 판단하면, 핑퐁이가 다음 발화에서 스스로 정정하도록 문구를 게스트 Realtime 세션에 자동 주입한다. 이 로직은 host.tsx · session-card.tsx · monitor-dashboard 3곳에 동일하게 복제되어 있다 — 리뷰 시 가장 먼저 볼 지점.
오디오 분석 에이전트(Gemini/OpenAI)는 매 턴마다 아동 발화를 분석해 오인식 가능성을
low / medium / high로 판단한 JSON을 반환한다. 결과가 high이고 설정이 켜져
있으면, "직전 인식을 이렇게 잘못 들었으니 다음 발화에서 정정하라"는 지시문을 게스트 세션에 시스템
메시지로 주입한다. 판단·표시 자체는 기존 오디오 분석 에이전트 파이프라인(host.tsx:578
onResult) 그대로이며, 이 커밋은 그 결과에 반응하는 새 부수효과 하나를 추가한 것이다.
정정 문구는 관리자가 설정 화면에서 자유롭게 편집하는 템플릿이며, {heardContent}처럼
{키} 형태로 쓰면 활성 에이전트가 실제로 출력하는 JSON 필드 값으로 치환된다 — 에이전트
출력 스키마가 바뀌어도 템플릿을 고치지 않아도 되도록 설계했다.
enabled: false — 기존 세션 동작에는 영향 없음설정 UI — 토글 · 문구 편집
components/sections/audio-analysis-agents-section.tsx
PUT — 저장
PUT /api/audio-analysis-agents/correction · withAuthAdmin
DynamoDB — 싱글톤 레코드
lib/db-queries.ts · AUDIO_ANALYSIS_CORRECTION_KEY
훅 — GET으로 로드해 상태 반영
use-audio-analysis-agents.ts · correctionInjection
아래 4단계를 components/pages/host.tsx, features/session/ui/session-card.tsx,
app/monitor-dashboard/[group]/[roomId]/page.tsx 세 곳이 각자 onResult
콜백 안에 독립적으로 구현한다.
오디오 분석 결과 도착
onResult(result) — 3개 진입점 동일
조건 확인
enabled && probability === "high" && !error
host.tsx만 여기에 sessionRelay.isActive가 추가로 붙는다 — 나머지 두 곳엔 대응 가드가 diff상 보이지 않음.
문구 치환
buildCorrectionText(template, result)
게스트 세션에 주입
sendMessage(text) → 게스트 Realtime 세션, 다음 발화에 반영
| 레이어 | 파일 | 핵심 변경 |
|---|---|---|
| 타입 | types/db/audio-analysis-agent.types.ts | AudioCorrectionInjection, 기본 템플릿, buildCorrectionText/extractJsonKeysFromPrompt |
| DB | lib/db-queries.ts | getAudioCorrectionInjection/setAudioCorrectionInjection (chatPreset 테이블 싱글톤 레코드) |
| API (신규) | app/api/audio-analysis-agents/correction/route.ts | GET(member)/PUT(admin), template 내용 검증 없음 |
| 훅 | use-audio-analysis-agents.ts | setCorrectionInjection — 낙관적 업데이트 + 실패 시 롤백 |
| 설정 UI | audio-analysis-agents-section.tsx | 토글/문구/{키} 미리보기/활성 에이전트 키 칩 안내 |
| 런타임 ×3 | host.tsx · session-card.tsx · monitor-dashboard/page.tsx | 동일 조건 + 주입 호출 복제 |
동일한 주입 조건 + 호출 로직이 3개 파일에 그대로 복제됨. 공용 훅(예: useCorrectionInjectionEffect(onResult))으로 추출할지 검토.
host.tsx의 조건에만 sessionRelay.isActive가 붙어 있음. monitorSession.sendMessage가 내부적으로 비활성 세션을 무시하는지 확인 필요 — 아니라면 세션카드/모니터 대시보드 경로에서 비활성 세션에도 메시지를 보낼 수 있음.
buildCorrectionText는 템플릿의 {"{키}"}가 활성 에이전트 출력에 없으면 빈 문자열로 조용히 치환한다. 설정 화면의 키 칩은 안내용일 뿐 저장 시점에 검증하지 않아, 오타난 키를 넣어도 저장은 성공하고 깨진 정정 문구가 주입될 수 있음.
enabled 기본값이 false라 기존 세션엔 즉시 영향 없음. 커밋 메시지대로 realtime·tts 두 모드가 같은 경로로 동작한다면, 두 모드에서 sendMessage 처리 방식이 실제로 동일한지 별도 확인 권장.
관련 문서: 오디오 분석 에이전트 — 통합 코드 레벨 문서 — 이 커밋이 손댄 onResult 진입점(스테이지 4)의 원본 파이프라인 문서. "V2엔 모달이 없다" 함정과 관련해, 이 커밋으로 V2(session-card·monitor-dashboard)의 onResult가 정정 주입 목적으로는 처음 연결됨.