수업 로그 기술이슈 리포트 포맷 — before/after

마지막 업데이트 2026-08-25

대상일 2026-08-24작성 2026-08-25소스: S3 prod/lesson-logs/*/archives/lesson-log-20260824.jsonl.gz 233개

결론. 기존 포맷은 로그 레벨(error/치명)로 세션을 골랐고, 그래서 4건을 오탐하고 44건을 놓쳤다. 같은 233개 원본 로그를 영향 기반 판정 룰 21개로 다시 돌리면 차단 10 · 저하 67 · 관측만 74 · 무증상 82으로 갈린다. 가장 큰 차이는 기존 긴급 1·2·4·7위였던 자동전환 실패 4건이 전부 오탐이라는 것과, 20:14:49에 두 세션이 초 단위로 동시에 AI 시작 실패한 서버측 사건이 개별 카드로 흩어져 보이지 않았다는 것이다.

1. 무엇이 달라졌나

동일한 원본 로그, 동일한 제외 기준(테스트 계정·force kick). 판정 축만 바꿨다.

기존 포맷개선 포맷
선별 기준error/치명 로그가 있으면 후보사용자 영향이 정의된 룰이 임계를 넘으면 후보
심각도긴급 / 확인 (로그 레벨 개수)차단 / 저하 / 관측 (수업 진행에 미치는 영향)
카드 본문37건 중 26건이 error 레벨; error 레벨룰마다 영향 문장 1줄 고정
근거동시 발생 시그니처 상위 3개(무관한 것 포함)룰이 매칭한 로그만 시각과 함께
분류같은 시그니처가 세션마다 다른 그룹룰 ID가 곧 분류 (1:1)
노이즈임계 없음 (1회도 후보)기저 발생률 측정 후 관측으로 격리
미확정표기 없음룰 단위로 "미확정" 사유 명시
4오탐으로 탈락
44새로 포착
6확인 → 차단 승격
2긴급 → 저하 강등

2. 오탐 — 자동전환 실패 4건은 실패가 아니었다

기존 포맷의 긴급 1·2·4·7위. 근거는 "통보는 됐으나 goToNextStep이 호출되지 않았다".

당일 전체 로그에서 Video ended — transition snapshotgoToNextStep called를 (activityIndex, stepIndex)로 짝지으면 autoTransitionEnabled=true인 통보 1615건은 1615건 모두 60초 내에 goToNextStep이 뒤따랐다. 짝이 없는 통보는 5건뿐이고, 그 5건은 전부 autoTransitionEnabled=false — 진행자가 자동전환을 꺼둔 상태였다.

// 김재겸 4회기 — 기존 포맷이 "자동전환 실패 2건 (긴급)"으로 올린 세션
15:01:16  transition snapshot  act0/step0  autoTransitionEnabled=true
15:01:16  goToNextStep called  act0/step0                            ← 같은 초에 정상 전환
   ... (act0/1, act0/2, act1/0, act2/0, act3/0 모두 동일 패턴, 누락 0)
15:20:28  transition snapshot  act7/step0  autoTransitionEnabled=false  ← 자동전환 OFF
15:21:37  transition snapshot  act7/step1  autoTransitionEnabled=false  ← 자동전환 OFF
                                                                     → 이 2건을 "실패"로 집계
// 오탐이 만들어진 경로
autoTransitionEnabled 플래그 미검사
   → 진행자가 끈 전환까지 "통보 후 미호출"로 집계
   → 무관한 동시 발생 시그니처(RESOURCE_ERROR, MFCC 업로드 실패)를 근거로 첨부
   → error 로그 1건 동반 → 긴급 승격
   → 긴급 8건 중 4건(50%)이 오탐, 운영자 확인 시간 낭비

나머지 탈락 2건도 같은 계열이다. 김재겸 4회기(긴급), 정이안 13회기(확인), 차예준 8회기(긴급), 허윤서 39회기(확인) — 정이안은 캐시 실패였으나 원본은 정상 제공됐고, 허윤서는 Ack received for unexpected RPC request만으로 등재됐다. 이 RPC 경합 로그는 당일 11개 세션에서 나오며 증상과 연결된 근거가 없다.

강등 2건. 신리안 11회기, 이수원 7회기 — 자동전환 근거는 사라졌지만 다른 실제 저하 룰(출력 무음·리버퍼링)이 남아 후보에는 유지된다.

3. 놓친 것 — 시간축이 없어 서버 사건이 안 보였다

기존 포맷은 세션을 독립 카드로만 나열해, 여러 아동에게 동시에 일어난 사건을 개별 이슈로 흩뿌린다.

// AI 세션 시작 실패 + 에이전트 준비 타임아웃 — 발생 시각
17:51:59  김나은 46회기   Failed to start session        (UNAUTHORIZED 동반, 단독 사건)
20:14:49  김시은 45회기   Failed to start session + agent readiness wait failed
20:14:49  김민하 10회기   Failed to start session + agent readiness wait failed   ← 초 단위 동시
20:49:27  김리현 16회기   Failed to start session + agent readiness wait failed

20:14:49의 두 건은 서로 다른 아동·진행자·기기인데 같은 초에 같은 실패를 냈다. 개별 아동 문제가 아니라 LiveKit 에이전트 측 사건으로 봐야 하고, 확인 대상도 아동 세션이 아니라 그 시각의 agent 로그다. 기존 포맷에서는 3위·6위 카드로 떨어져 있어 이 관계가 드러나지 않았다.

새로 포착 44건. 대부분은 error가 아닌 warn으로만 남는 계열이다 — 영상 첫 재생 시 출력 무음(25), 로컬 트랙 muted/ended(22), 영상 리버퍼링 상위 5%(11), 업링크 정체(9). 기존 포맷은 error 레벨만 후보로 올려 이들을 구조적으로 제외했다.
승격 6건 (확인 → 차단). 김지호 15회기, 유인성 13회기, 이찬영 2회기, 임재균 3회기, 정유리 6회기, 최윤서 48회기 — 재입장 루프·입장 차단·마이크 권한 거부처럼 수업이 실제로 막힌 건들이 기존에는 "확인"이었다.

4. 노이즈를 임계로 걷어내기

1회 발생을 알림으로 올리기 전에 당일 전체 세션의 기저 발생률을 먼저 잰다.

시그니처발생 세션총 건수판정근거
MONITOR_CONSUMER|Consumer suspected silent111 / 233754관측754건 전부 trigger=consumer-created. 코드상 이 프로브는 consumer 생성 직후 2회 샘플링이 유일한 호출 지점이라, 아동이 마침 말하지 않으면 정상 세션에서도 뜬다. 지속 무음의 근거가 못 된다.
MEET_VIDEO|Unexpected pause detected121 / 2332649관측52% 기저 발생, 자동 복구 경로 포함
CONSOLE|Ack/Response for unexpected RPC11 / 233360관측error 레벨이지만 증상 연결 근거 없음
MEET_VIDEO|Video waiting [*]134 / 233저하(임계 12)p50=2, p90=10, p95=11 → 12회 이상만 알림(11세션)
기존 포맷의 문제는 반대 방향에서도 나타난다. 반세경 61회기는 Consumer suspected silent 23회로 "확인" 등재됐는데, 이는 23번의 무음 구간이 아니라 consumer가 23번 재생성된 것이다. 반대로 이 시그니처가 111개 세션에서 나온다는 사실은 카드 어디에도 없었다.

5. 판정 룰 카탈로그

룰 ID = 분류. 임계와 영향 문장을 룰에 붙여두면 카드 본문이 비지 않는다.

ID등급이름매칭 시그니처임계사용자 영향 / 비고세션
B1-AI-START차단AI 세션 시작 실패AI_SESSION|Failed to start session≥1회핑퐁이와 대화 자체가 시작되지 않는다4
B2-AGENT-READY차단LiveKit 에이전트 준비 타임아웃LiveKit agent readiness wait failed / LiveKitAgentReadinessTimeoutError≥1회에이전트가 방에 붙지 않아 AI 무응답3
B3-ENTRY차단수업 데이터 로드 실패로 입장 차단GUEST_PAGE_SESSION|Failed to load lesson data, blocking entry≥1회아동이 수업에 들어가지 못함1
B4-MIC차단마이크 권한 거부LOCAL_MEDIA_STREAM|getUserMedia failed (NotAllowedError)≥1회아동 음성이 캡처되지 않음2
B5-REENTRY차단재입장 루프GUEST_ENTRY|Re-entry loop detected≥1회아동 화면이 재입장에 갇힘3
B6-AUTOTRANS차단영상 종료 자동전환 끊김autoTransitionEnabled=true 스냅샷 후 60초 내 동일 (activity,step) goToNextStep 없음≥1회진행자 수동 전환 필요0
D1-INPUT-SYNC저하듣기 ON/OFF가 에이전트에 미반영Failed to update LiveKit runtime input enabled≥1회듣기를 켜도 AI가 아동 발화를 못 받는 구간 발생9
D2-NO-RESP저하OpenAI 응답 5초 초과AI_SESSION|No response from OpenAI within N seconds≥2회아동 발화 뒤 핑퐁이 침묵6
D3-INTERRUPT저하AI 발화 중단(끼어들기) 실패Failed to send LiveKit manual interrupt≥1회아동이 말해도 발화가 안 멈춤3
D4-UPLINK저하소켓 업링크 정체SOCKET_UPLINK|Uplink stall detected (ack timeout)≥1회아동 이벤트 서버 도달 지연9
D5-CONSUME저하미디어 consume/resume 실패Consume failed / Failed to resume consumer / set consumer layer≥1회모니터에 아동·AI 미디어가 안 붙음8
D6-TRANSPORT저하mediasoup 트랜스포트 실패Send transport failed / Mediasoup transport failed≥1회미디어 경로 단절·재연결3
D7-AI-AUDIO-STALL저하AI 오디오 producer 송신 정지MEDIASOUP_PRODUCER|Audio producer outbound stalled≥1회진행자 쪽 핑퐁이 소리 끊김4
D8-OUTPUT-SILENT저하영상 첫 재생 시 출력 무음AUDIO_PROBE|Audio output suspected silent (trigger≠warmup)≥1회아동 기기에서 소리 없이 수업 시작25
D9-VIDEO-REBUF저하영상 리버퍼링·디코드 과부하MEET_VIDEO|Video waiting [*]≥12회 (당일 p95=11)영상 끊김·멈춤11
D10-TRACK-LOST저하로컬 미디어 트랙 muted/endedLOCAL_MEDIA_STREAM|Local media track muted/ended≥1회 (당일 p95=1)아동 카메라·마이크 트랙 중도 소실22
D11-MIC-RACE저하·미확정활동 전환 중 mic producer 초기화 경합MEDIASOUP_PRODUCER|Failed to produce mic audio (queue stopped)≥1회모니터 relay 마이크 미연결 가능. 후속 성공 로그 없어 미확정12
O1-SILENT-PROBE관측생성 직후 consumer 무음 프로브MONITOR_CONSUMER|Consumer suspected silent알림 제외754건 전부 trigger=consumer-created. 111/233 세션(48%) 기저 발생111
O2-RPC관측LiveKit RPC ack/response 경합Ack/Response received for unexpected RPC request알림 제외증상과 연결된 근거 없음11
O3-RESCACHE관측리소스 캐시 실패(원본 제공됨)RESOURCE_CACHE|... but resource is available알림 제외캐시만 실패, 재생은 정상1
O4-PAUSE-RECOVER관측영상 일시정지 자동복구MEET_VIDEO|Unexpected pause detected, attempting recovery알림 제외121/233 세션(52%) 기저 발생, 자동 복구됨121
B6-AUTOTRANS는 당일 0건이다. 룰이 없어서가 아니라, 룰을 제대로 세우면 0건이라서 0건이다. 기존 포맷의 4건은 이 룰의 autoTransitionEnabled 조건이 빠진 형태였다.

6. 개선 포맷 결과 — 차단 10건

카드마다: 영향 문장 · 룰 ID와 임계 · 매칭 로그 시각 · roomId. 기존 포맷에서 어떻게 분류됐는지도 함께 표기했다.

김지호15회기16:28~16:56LogRocket
042cb2d1-4f46-44f1-95a2-e0fb73002888_15
차단B5-REENTRY재입장 루프1회 / 임계 1

아동 화면이 반복 재입장에 갇힌다.

16:38:48 GUEST_ENTRY|Re-entry loop detected
저하D4-UPLINK소켓 업링크 정체(ack timeout)1회 / 임계 1

아동 이벤트가 서버에 늦게 도달해 반응이 밀린다.

16:35:11 SOCKET_UPLINK|Uplink stall detected (ack timeout)
이찬영2회기17:00~17:22LogRocket
963a5f2c-94d8-48b1-a22b-d3ee4abd8854_2
차단B4-MIC마이크 권한 거부(getUserMedia NotAllowedError)1회 / 임계 1

아동 음성이 아예 캡처되지 않아 AI·진행자 모두 못 듣는다.

17:00:31 LOCAL_MEDIA_STREAM|getUserMedia failed
김나은46회기17:30~17:53LogRocket
b9faeb69-7c01-4c8b-ae84-464a6ea65e66_46
차단B1-AI-STARTAI 세션 시작 실패2회 / 임계 1

핑퐁이와 대화를 시작하지 못해 수업 진행 자체가 막힌다.

17:51:59 AI_SESSION|Failed to start session
17:51:59 AI_SESSION|Failed to start session (handler)
최윤서48회기19:59~20:24LogRocket
59b42ded-c7bf-45ec-9978-c46260865518_48
차단B4-MIC마이크 권한 거부(getUserMedia NotAllowedError)1회 / 임계 1

아동 음성이 아예 캡처되지 않아 AI·진행자 모두 못 듣는다.

20:00:41 LOCAL_MEDIA_STREAM|getUserMedia failed
저하D1-INPUT-SYNC듣기 ON/OFF 상태가 에이전트에 반영 실패2회 / 임계 1

진행자가 듣기를 켜도 AI가 아동 발화를 받지 못하는 구간이 생긴다.

20:02:56 LIVEKIT_CLIENT_SESSION|Failed to update LiveKit runtime input enabled
20:05:24 LIVEKIT_CLIENT_SESSION|Failed to update LiveKit runtime input enabled
유인성13회기20:00~20:21LogRocket
420ecf3d-0605-4e0b-9c51-f82c8a7a93a1_13
차단B3-ENTRY수업 데이터 로드 실패로 입장 차단1회 / 임계 1

아동이 수업에 들어가지 못한다.

20:00:05 GUEST_PAGE_SESSION|Failed to load lesson data, blocking entry
김시은45회기20:00~20:21LogRocket
160c31ba-1cbc-4c71-950a-e809c99aa86c_45
차단B1-AI-STARTAI 세션 시작 실패2회 / 임계 1

핑퐁이와 대화를 시작하지 못해 수업 진행 자체가 막힌다.

20:14:49 AI_SESSION|Failed to start session
20:14:50 AI_SESSION|Failed to start session (handler)
차단B2-AGENT-READYLiveKit 에이전트 준비 타임아웃2회 / 임계 1

에이전트가 방에 붙지 않아 AI가 응답할 수 없다.

20:14:49 LIVEKIT_CLIENT_SESSION|LiveKit agent readiness wait failed
20:14:56 UNHANDLED_REJECTION|LiveKitAgentReadinessTimeoutError: LiveKit agent readiness timed out
저하D1-INPUT-SYNC듣기 ON/OFF 상태가 에이전트에 반영 실패1회 / 임계 1

진행자가 듣기를 켜도 AI가 아동 발화를 받지 못하는 구간이 생긴다.

20:16:38 LIVEKIT_CLIENT_SESSION|Failed to update LiveKit runtime input enabled
저하D8-OUTPUT-SILENT영상 첫 재생 시 출력 무음 감지1회 / 임계 1

아동 기기에서 소리가 안 나는 상태로 수업이 시작된다.

20:00:44 AUDIO_PROBE|Audio output suspected silent
김민하10회기20:00~20:28LogRocket
e22f550e-0658-4c72-ad8f-acd962f13ca8_10
차단B1-AI-STARTAI 세션 시작 실패2회 / 임계 1

핑퐁이와 대화를 시작하지 못해 수업 진행 자체가 막힌다.

20:14:49 AI_SESSION|Failed to start session
20:14:49 AI_SESSION|Failed to start session (handler)
차단B2-AGENT-READYLiveKit 에이전트 준비 타임아웃2회 / 임계 1

에이전트가 방에 붙지 않아 AI가 응답할 수 없다.

20:14:49 LIVEKIT_CLIENT_SESSION|LiveKit agent readiness wait failed
20:14:51 UNHANDLED_REJECTION|LiveKitAgentReadinessTimeoutError: LiveKit agent readiness timed out
저하D5-CONSUME미디어 consume/resume 실패3회 / 임계 1

진행자 화면에서 아동 또는 AI 오디오/영상이 붙지 않는다.

20:19:36 CONSOLE|Failed to consume existing producers:
20:21:18 CONSOLE|Failed to consume existing producers:
20:25:14 CONSOLE|Failed to consume existing producers:
김리현16회기20:26~20:50LogRocket
749697d8-f51f-4b96-bbfd-116b3553bf9f_16
차단B1-AI-STARTAI 세션 시작 실패2회 / 임계 1

핑퐁이와 대화를 시작하지 못해 수업 진행 자체가 막힌다.

20:49:27 AI_SESSION|Failed to start session
20:49:27 AI_SESSION|Failed to start session (handler)
차단B2-AGENT-READYLiveKit 에이전트 준비 타임아웃2회 / 임계 1

에이전트가 방에 붙지 않아 AI가 응답할 수 없다.

20:49:27 LIVEKIT_CLIENT_SESSION|LiveKit agent readiness wait failed
20:49:32 UNHANDLED_REJECTION|LiveKitAgentReadinessTimeoutError: LiveKit agent readiness timed out
저하D9-VIDEO-REBUF영상 리버퍼링/디코드 과부하12회 / 임계 12

영상이 끊기거나 멈춘다.

20:30:33 MEET_VIDEO|Video waiting [SEEK_REBUFFER]
20:32:14 MEET_VIDEO|Video waiting [SEEK_REBUFFER]
20:37:20 MEET_VIDEO|Video waiting [SEEK_REBUFFER]
외 9건
임재균3회기20:30~20:56LogRocket
8cda93a3-482e-48c3-8a81-b098d1051ac6_3
차단B5-REENTRY재입장 루프9회 / 임계 1

아동 화면이 반복 재입장에 갇힌다.

20:30:32 GUEST_ENTRY|Re-entry loop detected
20:30:45 GUEST_ENTRY|Re-entry loop detected
20:30:57 GUEST_ENTRY|Re-entry loop detected
외 6건
정유리6회기20:31~20:58LogRocket
7b4b524c-aa93-42b8-af8d-d91e742ed0af_6
차단B5-REENTRY재입장 루프1회 / 임계 1

아동 화면이 반복 재입장에 갇힌다.

20:35:01 GUEST_ENTRY|Re-entry loop detected

7. 저하 67건

진행은 됐으나 체감 품질이 손상된 세션. 룰 ID로 필터해 같은 계열끼리 묶어 본다.

아동회기시작기존 포맷
박서현4008:53D8-OUTPUT-SILENT D9-VIDEO-REBUF신규
이도윤108:57D5-CONSUME D8-OUTPUT-SILENT D10-TRACK-LOST기존 확인
김강민209:55D8-OUTPUT-SILENT신규
김지안1711:28D9-VIDEO-REBUF신규
한유안113:54D10-TRACK-LOST기존 확인
김이솔114:00D7-AI-AUDIO-STALL신규
박건우1314:00D11-MIC-RACE신규
고지효214:25D9-VIDEO-REBUF신규
권나연514:53D3-INTERRUPT D11-MIC-RACE D10-TRACK-LOST기존 확인
김예준215:28D10-TRACK-LOST신규
유인지215:30D10-TRACK-LOST신규
나현우6016:00D4-UPLINK D11-MIC-RACE신규
신리안1116:51D8-OUTPUT-SILENT기존 긴급
박소연916:57D4-UPLINK D5-CONSUME D11-MIC-RACE기존 확인
이다은216:59D2-NO-RESP신규
김하승3717:00D11-MIC-RACE D10-TRACK-LOST기존 확인
김주원217:23D10-TRACK-LOST신규
김리아117:27D4-UPLINK D6-TRANSPORT D8-OUTPUT-SILENT기존 확인
이다인317:30D1-INPUT-SYNC D8-OUTPUT-SILENT기존 확인
고가빈517:47D5-CONSUME D8-OUTPUT-SILENT기존 확인
이수원717:55D8-OUTPUT-SILENT D9-VIDEO-REBUF기존 긴급
김시원6118:24D1-INPUT-SYNC D2-NO-RESP D3-INTERRUPT D4-UPLINK D6-TRANSPORT D7-AI-AUDIO-STALL D11-MIC-RACE기존 확인
최윤호3618:27D8-OUTPUT-SILENT D10-TRACK-LOST신규
반세경6118:29D2-NO-RESP D4-UPLINK D5-CONSUME D9-VIDEO-REBUF기존 확인
황도경118:45D8-OUTPUT-SILENT신규
지윤우918:52D8-OUTPUT-SILENT신규
정현준1018:53D5-CONSUME D8-OUTPUT-SILENT기존 확인
이여준3118:57D10-TRACK-LOST신규
이도훈618:57D10-TRACK-LOST신규
박서준2519:00D10-TRACK-LOST신규
길주한3219:23D8-OUTPUT-SILENT D9-VIDEO-REBUF신규
김승준1019:24D9-VIDEO-REBUF신규
백지훈1519:24D5-CONSUME D8-OUTPUT-SILENT D11-MIC-RACE D10-TRACK-LOST기존 확인
손예승119:26D8-OUTPUT-SILENT기존 확인
송준우119:26D2-NO-RESP D5-CONSUME기존 확인
김이안219:27D9-VIDEO-REBUF신규
김시율119:27D8-OUTPUT-SILENT신규
조유진2219:30D1-INPUT-SYNC D2-NO-RESP D3-INTERRUPT D4-UPLINK D10-TRACK-LOST기존 확인
배예찬2719:32D10-TRACK-LOST신규
정아인1519:40D10-TRACK-LOST신규
신지호3719:51D9-VIDEO-REBUF신규
이시율219:59D7-AI-AUDIO-STALL신규
김동겸4119:59D11-MIC-RACE신규
안시하619:59D9-VIDEO-REBUF신규
김지웅820:00D10-TRACK-LOST신규
김규린3120:00D11-MIC-RACE신규
이하온120:00D10-TRACK-LOST신규
안준우4820:00D11-MIC-RACE D10-TRACK-LOST신규
현다빈920:00D7-AI-AUDIO-STALL신규
김성운3520:00D8-OUTPUT-SILENT신규
김유담1720:02D4-UPLINK신규
나한결220:22D1-INPUT-SYNC기존 확인
강수현120:25D8-OUTPUT-SILENT신규
신가윤4420:27D2-NO-RESP신규
김설민1920:30D8-OUTPUT-SILENT신규
서승연120:30D8-OUTPUT-SILENT신규
정윤구3620:30D11-MIC-RACE D10-TRACK-LOST신규
황정빈1420:30D8-OUTPUT-SILENT신규
안태빈3920:30D8-OUTPUT-SILENT신규
이주원1120:30D1-INPUT-SYNC기존 확인
정리베920:31D10-TRACK-LOST신규
이예림220:53D8-OUTPUT-SILENT신규
곽태규120:56D6-TRANSPORT기존 확인
김서윤721:00D1-INPUT-SYNC D4-UPLINK기존 확인
김현서1921:00D10-TRACK-LOST신규
백지호1221:00D1-INPUT-SYNC D11-MIC-RACE D10-TRACK-LOST기존 확인
김영준3521:04D8-OUTPUT-SILENT기존 확인

8. 이 포맷이 아직 못 하는 것

재현. S3 prod/lesson-logs/에서 archives/lesson-log-20260824.jsonl.gz 233개를 받아 룰을 적용했다. 아동명은 ppi-user-prodid → name으로 붙였다.