WebRTC 다자 화상회의에서 참가자별 STT 작업을 방(room) 단위로 묶고, 전원이 끝나면 전체 대화를 LLM으로 통합 요약하는 기능.
• 병렬 전사 — 각 참가자는 독립 WebSocket·작업으로 전사
• 자동 트리거 — 마지막 참가자 종료를 감지해 Celery로 요약
• 1:1 겸용 — 방 정보가 없으면 같은 코드가 1:1 모드로 동작한다.
방–작업 1:N
4상태 판정
자동 트리거
Celery 재시도 5
1:1 겸용
참가자별 작업
준비됨·미준비·전원 실패·작업 없음 (+ 조회 오류)
전원 종료 감지
준비 안되면 재시도
방 정보 없음
왜 이 설계가 필요했는가 (Problem)
방 상태 머신
핵심 설계 결정
1. 방–참가자–작업 구조 + 중복 참가 차단
# 스트림 작업 생성 — 중복 참가 가드기존 = await 같은 방의 같은 참가자 작업 조회(방, 참가자)if 기존 and 기존 상태 in [대기, 처리 중]: raise 409 Conflict # 이미 이 방에 참가 중
2. 4상태 완료 판정
# 판정 후 트리거판정 = await 방 요약 준비 판정(방)if 판정 == 준비됨: await 방 상태 갱신(방, 요약 중) 요약 태스크.delay(방) # Celery 트리거elif 판정 == 전원 실패: await 방 상태 갱신(방, 실패)
3. Celery 재시도 + 진입 시 안전 재확인
# 방 요약 태스크 (최대 재시도 5)if 판정 != 준비됨: raise 재시도(f"방 미준비: {판정}") # 경쟁 조건 방어대화록들 = await 완료된 참가자 대화록 조회(방)결합본 = 참가자마다 "--- 참가자: {이름} ---" + 대화록 을 이어 붙임요약 = await LLM 요약(결합본)await 방 통합 요약 저장(방, 요약)
설계가 만든 결과 (Result)
검증 결과
요약 준비 판정 테스트 · 15/15 통과 (pytest + hypothesis)
구분
검증 내용
상태
4상태 전수 — 작업 없음 / 미준비(보류 3조합) / 전원 실패 / 준비됨(성공 3조합)
상태
일부 실패해도 성공이 있으면 준비됨 — 한 명 실패로 전체 요약을 포기하지 않는다
★ 불변식
진행 중인 작업이 있으면 어떤 조합에서도 준비됨이 아니다 (500 케이스)
★ 불변식
준비됨이면 반드시 성공한 작업이 존재한다 (500 케이스)
불변식
집계가 서로 모순된 값이어도 정의된 상태만 반환한다 (300 케이스)
방어
집계 키가 일부 누락돼도 판정이 깨지지 않는다 (없는 키는 0으로 본다)
격리
조회가 실패하면 ‘조회 오류’ 반환 — 예외를 밖으로 전파하지 않는다
호환
기존 준비 여부 함수는 준비됨일 때만 참
두 불변식이 각각 다른 사고를 막는다
조회 실패를 예외로 흘리지 않는 이유
이 검증이 말하지 않는 것
자동 요약 트리거 흐름
실시간 자막의 동시 발화자 한계 (2026-08-30 실측)
지표
1 세션
동시 4 세션
스트리밍 중 자막 수신
2건
🔴 0건
세션당 세그먼트
4개
2개 (VAD 분할이 바뀜)
자막 지연
5.1~6.0s
측정 불가 (스트림 중 미도착)
마지막 전사 기록
스트림 내
🔴 클라이언트 종료 후 17~20초
⚠️ 이 수치를 과장해서 읽지 말 것
원인 가설을 세우고 — 기각했다
남는 정확한 서술: 동시 4세션에서 실시간 자막이 죽는다. 스레드 경합은 원인이 아님이 확인됐고(6↔2 무차이), 지연을 구간별로 쪼갤 로그 마커가 없어 원인을 더 좁히지 못했다.