Activity 시스템 (템플릿·step·jumpConfig·auto-finish) — 코드레벨 동작 흐름 P1코드레벨

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

작성일: 2026-06-14 대상: 개발자 — 아동 대화 활동 구성·전환 파악 핵심 파일: types/db/activity.types.ts, lib/{activity-utils,spare-content-utils,lesson-utils}.ts, hooks/use-session-auto-finish.ts

개요 · 범위

한 수업은 여러 Activity(활동)로 구성되고, 각 활동은 여러 Step(스텝)을 가진다. 활동/스텝은 priority로 순서가 정해지며, 활동 종료 시 jumpConfig로 다음 활동을 정한다(기본/조건부). 스텝의 autoFinish 설정으로 발화 종료/특정 문구 감지 시 자동 전환된다.

구성: 데이터 모델(activity.types) + 우선순위 유틸(activity-utils) + 활동 이동·예비 스킵(spare-content-utils) + 템플릿 복사(lesson-utils) + 자동 종료(use-session-auto-finish, 세션 매니저 #1과 연동).

데이터 모델 activity.types.ts

Activity

Step

필드의미
typeprompt | hybrid | resource
actionType (hybrid)talk | resource
resTypescreen-share | embedded (+ resName)
startMent스텝 시작 멘트(세션 매니저 startMent로 전달)
avatarInitialState아바타 초기 상태(talking/idle 등)
autoFinishEnabled / autoFinishType / autoFinishPhrases자동 종료 설정(아래)

우선순위 기반 시퀀싱 activity-utils.ts

활동 이동 (jumpConfig) spare-content-utils.ts: findNextActivityByJumpConfig L167

// default 모드: 고정 다음 활동
if (jumpMode === "default")  → defaultNextActivityIndex 반환(범위 검증)

// conditional 모드: 키워드 매칭으로 분기
if (jumpMode === "conditional" && matchedConditionKeywords)
  for cj of conditionalJumps:
    normalize 후 cj.keywords 전부가 입력에 포함되면(every)
      → cj.targetActivityIndex 반환

예비 콘텐츠(isSpare) 스킵 spare-content-utils.ts: findNextStepSkippingSpare

isSpare 활동은 일반 순차 진행에서 건너뛰는 예비물이다. findNextStepSkippingSpare가 다음 후보를 찾을 때 spare를 스킵하며, 후보 소진 시 null 반환. (jumpConfig로 명시적으로 지목되면 사용 가능)

회기 템플릿 → 활동 복사 lesson-utils.ts L52–73

활동은 회기 템플릿에서 복사 생성된다. 복사 시 템플릿의 jumpConfig를 활동 인덱스에 맞게 재매핑한다(default의 defaultNextActivityIndex, conditional의 각 targetActivityIndex). 잘못된 인덱스는 필터링.

자동 종료 (auto-finish) hooks/use-session-auto-finish.ts

스텝의 autoFinishPhrases로 종료 문구를 감지하면 자동으로 다음으로 넘어간다. 세션 매니저(#1)의 전사 이벤트가 이 훅을 구동한다. autoTransitionEnabled(enabled) + config.enabled 둘 다 켜져야 동작.

문구 매칭 checkPhrase L49

// 각 condition은 콤마 구분 단어들. normalize(따옴표/공백 제거) 후
matchedCount = words.filter(w => text.includes(w)).length
threshold = words.length >= 3 ? 2 : words.length   // 3단어↑면 2개만 맞아도 OK
matchedCount >= threshold  →  매칭

두 가지 타입

type동작
after-pingpong-speech핑퐁이 발화 전사에서 문구 매칭(handlePingpongSpeech) → autoFinishSilence=true(입력 차단) → 1초 후 onAutoFinish
after-child-speech핑퐁이가 문구 발화 후 아동 응답을 기다림. 아동 발화 종료(handleChildSpeechEnd) 시 즉시 종료, 무응답이면 5초 타임아웃 종료. 호스트 타이핑 중이면 타이머 보류(handleHostTypingStatusChange)

onAutoFinish(matchedCondition, triggerText)는 매칭된 조건/문구를 함께 넘겨 jumpConfig conditional 분기의 키워드로 쓰일 수 있다. (세션 매니저 #1의 handleAutoFinish가 after-child-speech 시 cancelResponse 후 콜백)

함정 · 주의

파일 · 라인 레퍼런스

파일/심볼역할
types/db/activity.types.tsActivity/Step/jumpConfig 모델
lib/activity-utils.ts우선순위·기본 스텝·검증
lib/spare-content-utils.ts (findNextActivityByJumpConfig L167)활동 이동·예비 스킵
lib/lesson-utils.ts (L52–73)템플릿→활동 jumpConfig 재매핑
hooks/use-session-auto-finish.ts자동 종료(문구 매칭·타이머)
hooks/use-activity-templates.ts템플릿 CRUD

관련 문서