cuDNN 부재 환경에서 ctranslate2 는 Python 예외가 아니라 네이티브 크래시로 죽어 프로세스가 통째로 사라진다. 같은 프로세스의 try/except 로는 절대 잡을 수 없어 디바이스 확인을 버릴 수 있는 자식 프로세스(--self-check)로 분리했다. auto 는 CUDA 프로브 실패 시 CPU(int8)로 폴백하고, 명시적 --device cuda 는 조용히 강등하지 않는다. 함께 고친 것: - warmup PCM 생성의 연산자 우선순위 버그(b"\x00\x00" * N // 2 가 바이트열 정수 나눗셈이 되어 TypeError). warmup_pcm() 으로 분리하고 테스트로 고정했다. - audioop 은 Python 3.13 에서 제거되므로 array + 정수 연산으로 RMS 를 직접 구한다. 실측(저장소 무참조 synthetic seed 8.72초, CPU int8 small): interim 9 · final 5 · word timestamp 12개 present, 전사는 원문과 한 글자 차이. 사이드카 회귀 37/37.
29 KiB
한신대학교 SW중심대학 산학협력 — 생성형 AI 심리상담 시뮬레이션 플랫폼 마스터플랜
통합 기준 문서 (SoT, Single Source of Truth) · 작성 2026-06-25 · 트웬티온스 산학협력 제약: 20주 / 매칭금 500만 / 기존 풀스택팀
🔄 2026-06-25 업데이트 (윤찬 확인): IRB 정식 심의 불필요. 수련생 대상 교육 활용이라 인간 대상 임상시험이 아니므로 IRB 면제. → 아래 "IRB 승인"이 걸려있던 의존성/리드타임은 모두 해소(Phase 3 게이트 제거, 즉시 착수 가능). 단 미성년 원본 사례데이터(0615 등) 활용동의 + 개인정보 처리방침은 별도로 한신대 공문 확인 유지(IRB와 무관한 데이터 거버넌스 사안). 본 문서는 9개 도메인 전문 설계서를 단일 마스터플랜으로 종합한다. 각 도메인 상세는 §부록 A의 설계서 원본 참조.
상담 수련생 훈련용 — 가상내담자 시뮬레이션 + AI 실시간 피드백 + 안전 가드레일. 이 플랫폼은 진단·치료가 아니라 수련생 연습용(FDA General Wellness / 식약처 비의료기기 포지셔닝)이라는 점을 전 계층에서 고정한다.
0. 한 페이지 요약 (의사결정 고정값)
| 영역 | 확정 결정 | 핵심 근거 |
|---|---|---|
| AI 엔진 | 기본=Anthropic Messages API(Opus 4.8/Sonnet 4.6) 엔진 어댑터 뒤에 배치. claude -p(Max OAuth)는 옵션 플래그·개발 시연용 |
claude -p+OAuth 과금 누수(이틀 $1,800 사례)·동시성 1프로세스 한계·rate limit 마비 리스크. 어댑터 한 줄로 전환 가능하게 흡수 |
| 3-AI 구조 | 상담사 AI(선택) / 내담자 AI / 백그라운드 평가 AI. 정보 비대칭을 DB visible_to[] 컬럼이 강제(프롬프트 신뢰 X) |
상담사AI가 내담자 CCD를 보면 시뮬레이션 가치 0 |
| 상태머신 | 라포→탐색→개입→정리 전이는 FastAPI 백엔드가 결정론적으로 소유(LLM 아님) | 단계 흐릿하면 수련생 채점 신뢰도 붕괴 |
| 저항 엔진 | 내담자 저항을 프롬프트 형용사 아닌 상태머신 수치로 단계 주입 (핵심 차별기술) | CARE-Bench가 LLM positivity bias(과순응) 정량 확인 |
| 피드백 | 피드백 패널 = 1급 시민. 자유연습(피드백 OFF) 기본 차단 | Stanford CARE RCT: 연습만 d=-0.52 하락, 연습+피드백 집단격차 d=0.72 |
| 프론트 | React 19 + SSE, pnpm/Turborepo 모노레포(packages/core 100% 공유, 추후 RN) |
웹→네이티브 전환을 구조로 증명, 20주 과대약속 회피 |
| 백엔드 | FastAPI + SSE 스트리밍, 상태머신·가드레일·엔진 어댑터 | |
| DB | NAS PostgreSQL 16(+pgvector) 단일 SoR. Timescale은 확장 시 hypertable만 선택 | 20명 규모에 Timescale 과잉 |
| 배포 | Docker Compose 단일 호스트 모놀리식(5~6 컨테이너), Caddy 리버스프록시. K8s 금지 | 20주·인력 제약에 모놀리식이 최적 |
| 외부노출 | chanpaca.net = Cloudflare named tunnel(일반) + SSE 경로는 버퍼링 우회 분리(Tailscale Funnel) | Cloudflare가 SSE를 ~100KB 버퍼링 + 100초 timeout → 50분 상담 스트림 충돌 |
| 음성 | 1차 캐스케이드(Deepgram STT → 로컬 엔진 → OpenAI gpt-4o-mini-tts). s2s 1차 탈락 | transcript가 평가·로깅·재귀학습·가드레일의 1급 자산. s2s는 transcript 손실 |
| 인증 | BFF + OAuth 2.1 Auth Code + PKCE(S256). 토큰은 서버(Redis)에만, 브라우저엔 HttpOnly 쿠키 | 미성년 사례데이터+상담 민감정보 → XSS 토큰탈취 원천 차단 |
| 안전 | MIND-SAFE식 다층 분리 + 한국어 자살콘텐츠 분류(Llama Guard 한국어 미지원 공백 보강) | 재현율=법적 책임 최우선 |
1. 시스템 아키텍처 개요
1.1 물리 토폴로지 (인바운드 포트 0)
[교수님 브라우저] https://chanpaca.net
│
┌─────────┴──────────┐
│ Cloudflare Edge │ ← named tunnel(영구 URL, TLS/DDoS)
│ (정적·일반 API) │ ⚠ SSE는 버퍼링 → 분리 경로
└─────────┬──────────┘
│ (outbound-only, 개방포트 0)
┌───────────────────────────┼────────────────────────────────────────┐
│ 로컬 PC / NAS (한국 내 · 데이터 주권) Docker Compose: counsel-net │
│ ┌────────────┐ │
│ │ cloudflared│──┐ ┌──────────┐ ┌──────────────────────────┐ │
│ │(named tun.)│ │ │ frontend │ │ backend (FastAPI) │ │
│ └────────────┘ │ │ React19 │ │ ┌────────────────────┐ │ │
│ ┌────────────┐ ├──►│ 정적빌드 │◄──►│ │ 상태머신(결정론) │ │ │
│ │ Caddy │◄─┘ └──────────┘ │ │ 가드레일/안전레일 │ │ │
│ │ SSE flush-1 │◄──── [SSE 직결경로] │ │ SSE 스트리머 │ │ │
│ └─────┬──────┘ (Tailscale Funnel) │ │ 엔진 어댑터(라우터)│ │ │
│ │ │ └────────┬───────────┘ │ │
│ ▼ └──────┬────┼──────────────┘ │
│ stream.chanpaca.net (SSE 전용) │ │ │
│ ┌─────▼─┐ ┌▼─────────┐ │
│ ┌────────────────┐ ┌──────────────┐ │engine │ │ voice-gw │ │
│ │ Postgres 16 │ │ pgvector(RAG)│ │adapter│ │ OpenAI │ │
│ │ (NAS 영구볼륨) │ │ 임베딩 1024d │ │ ①claude_api(기본) │ │
│ │ 학습로그·관계형 │ └──────────────┘ │ ②claude_cli(옵션) │ │
│ │ RLS 이중강제 │ │ ③openai/solar │ │
│ └────────────────┘ [Presidio PII 마스킹] ──► 외부 LLM(마스킹 후만) │
└──────────────────────────────────────────────────────────────────────┘
원칙: ① 인바운드 포트 0 (cloudflared outbound 터널) ② 데이터는 로컬(NAS)을 떠나지 않음, PII 마스킹 후에만 외부 LLM 호출 ③ 전송 계층 추상화(VITE_SSE_BASE_URL)로 SSE 경로 무중단 전환.
1.2 논리 레이어 (프롬프트 캐싱 친화)
[L0 역할+안전가드레일+도식노출금지] ┐
[L1 페르소나 카드(정적)] ├─ cache_control (입력비 90%↓, 실측 59~70% 절감)
[L2 RAG 임상청크] ┘
[L3 상태머신 주입(stage, openness)]
[L4 메모리 버퍼(사실 hard-pin)]
[L5 수련생 발화]
2. AI 3종 상호작용 모델
2.1 정보 비대칭 (DB가 강제)
| AI | system 프롬프트 | 볼 수 있는 것 | 절대 못 보는 것 |
|---|---|---|---|
| ① 상담사 AI (선택/보조) | 마이크로스킬 시연용 | 대화 표면 | 내담자 CCD·DSM 차원·평가결과 |
| ② 가상내담자 AI | 페르소나 카드+CCD+저항 | 자기 페르소나·대화 | 평가 점수·정답 라벨 |
| ③ 백그라운드 평가 AI | 루브릭+골든 taxonomy | 전체 회기·CCD·정답 | (전부 봄, 학습자에 노출 X) |
3-AI는 서로 다른 system 프롬프트의 독립 claude -p/API 호출. "누가 무엇을 보는가"는 DB visible_to[] 컬럼이 강제하며 프롬프트를 신뢰하지 않는다.
2.2 턴 사이클 (결정론 상태머신 중심)
수련생 발화 U_t
→ [입력 가드레일] PII 마스킹 + 위기 분류(수련생 실제위기 vs 페르소나 연기 구분)
→ [상태머신] stage·effective_openness(t) 계산
effective_openness = clamp(stage.openness
+ rapport_credit(t)*unlock_rate
- resistance*decay(t), 0, 1)
→ [내담자 AI] 페르소나 응답 생성 (Structured Outputs, CCD 직접노출 금지)
→ [출력 가드레일] 자살수단 정보 차단, ideation_stage ≤ 3 상한
→ [평가 AI 2-tier]
· fast-loop(경량): U_t만 보고 4차원 태깅 (실시간 신호)
· deep-loop(Opus): 단계 전환·회기말, 0-5 채점 + 대안발화 (대시보드)
→ [로깅] TurnLog → Postgres (= 재귀학습 JSONL 원천)
rapport_credit: 수련생이 공감·반영·타당화·홀딩을 쓰면 +, 조언점프·평가적언어·유도질문이면 0/−. → 좋은 상담을 하면 내담자가 열리고, 나쁜 상담을 하면 닫힌다. 0615 실데이터의 "방어가 서서히 풀어지고 있음" 궤적 재현.
2.3 평가 AI 2-tier 루프 (핵심 레버)
- fast-loop: Haiku/Solar 경량, 발화별 4차원(공감·개방질문·검증·이론부합) 태깅 → 콜드스타트 지연·비용 통제
- deep-loop: Opus 4.8, 전체 회기 + 골든라벨 RAG로 0-5 채점(CTRS는 0-6 분리) + 대안발화 제시. 실시간 팝업보다 종료 후 대시보드가 SUS↑·인지부하↓
- LLM-judge 보정: raw 직접사용 금지, 길이정규화, 이중코딩 vs LLM weighted-κ≥0.6 / ICC≥0.75 게이트 통과분만 골든셋 승격
2.4 가상내담자 페르소나 (DSM-5 = 내부 파라미터, 비노출)
- 차원적 프로파일(RDoC 정신): negative_affect·hopelessness·suicide_risk{ideation_stage 1
5}·sleep_disturbance를 01 연속값 (단일 DSM 라벨 X) - CCD 8요소(Patient-Ψ): core_belief(worthless 등)·automatic_thought·coping_strategy — 직접 발화 금지, 행동으로만 드러내 상담자가 추론하게
- 시드 페르소나 3종(교수 검수 필수 게이트): P1=0615 청소년 우울·자퇴·자살사고(hard) / P2=성인 범불안·신체화(moderate, 자살0) / P3=인간중심 미혼모(PCT 훈련). 2차 백로그: ADHD품행·경계선특질·적응장애·위기4~5단계 전용
3. 데이터 모델 + Postgres 스키마 요약
3.1 원천 — 0615 파란색 라벨의 3종 혼재 (실측 확인)
축어록_파란색라벨_0615.hwpx를 직접 파싱(파랑 #3057B9, 라벨 89개·77종) → 한 셀에 3종이 혼재함을 확인. 학습 신호 오염 방지를 위해 3개 분리 필드로 격상이 스키마 설계의 출발점:
- (A) 기법 태그(복수): 공감/반영/탐색/홀딩/타당화/직면/해석/자기개방/안정화/희망고취/위험사정…
- (B) 내담자 상태 태그(복수): 비자발/방어/자살사고인정/부정적자기인식/갈등상태…
- (C) 슈퍼바이저 논평 2종:
rationale(근거설명) vscritique(과도한 자기개방·비언어반영 부족 등)
3.2 스키마 요약 (PostgreSQL 16, 3 스키마: app / audit / ds)
-- ── app: 운영 ──────────────────────────────────────────────
sessions(id, learner_id, persona_id, theory_mode, started_at, ended_at, stage_path JSONB)
turns/utterances( -- 발화 = 최소 원자단위, 모든 라벨/평가/PII가 FK로 매달림
id, session_id FK, seq, speaker('counselor'|'client'),
stage('라포'|'탐색'|'개입'|'정리'),
text, -- 저장 전 Presidio PII 마스킹
text_masked, -- 외부 LLM 전송용
actor_kind, -- 3 AI + 인간(수련생/슈퍼바이저) 통합 출처
llm_provider, model, tokens_in, tokens_out, cost_usd, visible_to TEXT[])
-- 라벨은 버전드 코드테이블 + 다대다(복수 라벨)
technique_label_def / client_state_def / stage_def / scale_def(0-5, CTRS 0-6)
turn_technique(turn_id, label_id) / turn_client_state(turn_id, label_id)
feedback_scores(turn_id, dimension, score, rationale) -- 0-5, D3
supervisor_comment(turn_id, kind('rationale'|'critique'),
text, intent_deviation JSONB{expected, actual, severity, dimension}) -- 윤찬 "의도와 다른 부분" 1급 시민
safety_events(session_id, trigger_type, ko_risk_level, escalated, latency_ms, created_at)
rag_chunks(id, source, embedding vector(1024), text)
-- ── audit: append-only 법적 증거 ──────────────────────────
event_log / llm_call_log(cost·드리프트·inference_geo) / audit_log(열람추적)
-- ── ds: 재귀 학습 파이프라인 ──────────────────────────────
dataset / dataset_item / annotation_round / annotation / export_manifest
-- AI자동(1R) → 인간검수(2R) → IAA 게이트(κ≥0.6, ICC≥0.75) → 골든셋 → JSONL
3.3 거버넌스 (인프라 직결)
- 저장 전 PII 마스킹 하드 게이트: backend→외부 LLM 경로에 Presidio(MedicalNERRecognizer). 마스킹 후 텍스트만 적재·전송
- RBAC + Postgres RLS 이중강제: 학습자=본인 / 교수자=담당 코호트 / 관리자=전부+교수활동(열람을 audit_log에 기록)
- 데이터 국내처리: DB=NAS(국내), 민감구간은 국내 모델(Solar/HyperCLOVA) 라우팅 또는
inference_geo:us명시 - 미성년 원본 4단계 격리: 원본 축어록은 플랫폼 DB 절대 미적재, 사람이 가명처리·전문가 검수한 CCD 스펙만 진입 (Character.AI 판례 대응)
3.6 RAG 아키텍처 (2026-06 최신 기준 · 윤찬 요청 보강)
RAG는 부가기능이 아니라 본 시스템 3개 축(페르소나 일관성 / 피드백 근거 / 지식)을 떠받치는 핵심. 2026.6 production RAG 합의 = failure mode 기준으로 사다리 최소한만 오른다(GraphRAG·Agentic 풀스택 처음부터 X).
용도별 매핑 (서로 다른 RAG)
- 페르소나 메모리 (내담자 일관성) — 순수 RAG 아님 → 하이브리드 메모리: 구조화 상태(상태머신 수치) + rolling summary + episodic 벡터 recall. 임상 비네트는 소규모 고정셋이라 검색난도 낮음.
- 피드백 근거 (0615 발화-라벨 정답셋 + 슈퍼바이저 논평) — 오답비용 큼 → 하이브리드 + 리랭킹 (+확장 시 CRAG 그레이딩).
- 지식 (DSM-5 진단기준 · 상담이론 인간중심/CBT) — 정적 KB → 하이브리드 + Contextual Retrieval.
확정 스택 (MVP = Phase 1)
- 임베딩 = BGE-M3: 다국어(한국어 강함) + dense·sparse·ColBERT 멀티벡터를 단일 모델로 제공 → 하이브리드와 late-interaction을 한 모델로 흡수. 우리 rag-memory가 이미 BGE-M3 사용 중 → 재활용.
- 저장/검색 = pgvector(HNSW): 기존 NAS Postgres에 인프라 추가 0, 수백만 벡터 sub-100ms.
- 하이브리드 검색: dense(pgvector) + sparse BM25(PG full-text 또는 BGE-M3 sparse), top-50 회수.
- Contextual Retrieval(Anthropic): 청크 임베딩 전 1문장 맥락 주입 → 검색실패 49%↓(+리랭킹 시 67%↓).
- 리랭커 = cross-encoder(BGE-reranker-v2-m3, 한국어): top-50 → top-5. 답변품질 15~30%↑.
확장 (Phase 2+)
- Adaptive RAG 라우터(2026 SOTA): 질의 복잡도 분류 → 단순=하이브리드 / 복잡=다단계 라우팅.
- CRAG(Corrective RAG): 피드백 근거처럼 오답비용 큰 경로에 관련성 그레이딩 + 재질의.
- (선택) GraphRAG: 상담이론 교차개념(인간중심↔CBT 연결) 맵이 커질 때만 2차 — 단순 lookup엔 과잉이라 1차 제외.
- (선택) ColBERT 독립 late-interaction: BGE-M3 멀티벡터로 충분, 품질 부족 시에만.
근거 출처: Anthropic Contextual Retrieval, RAG Production Patterns 2026, Jina ColBERT v2 다국어. Agentic+KG 환각 62%↓(2026.5 MLOps 벤치).
4. Phase별 구현 로드맵 (단일 로드맵, 산발 task 금지)
각 Phase에 우선순위·의존성·완료기준(DoD) 명시. Phase는 순차, 내부 트랙은 병렬(소유 파일 분리).
Phase 0 — 기반 정렬 (1~2주차) · 우선순위 P0
- 목표: 인프라 스캐폴드 + taxonomy 확정 + IRB 착수
- 작업:
- docker-compose 6서비스 스캐폴드 +
secrets/git-ignore + Caddyfile(flush_interval -1) - Postgres 스키마 §3.2 적용 + RLS 정책 + pgvector
- 라벨 taxonomy v1.0 확정(3축 분리) → 0615 축어록 골든셋 라벨링 1차
- IRB 프로토콜 초안(Stanford CARE 차용: minimal risk·자살시나리오 1차 제외·전문가 검증 내담자)
- 엔진 어댑터 인터페이스 정의(provider 플래그: claude_api/claude_cli/openai/solar)
- docker-compose 6서비스 스캐폴드 +
- 의존성: 없음 (시작점). taxonomy ↔ DB 코드테이블 동기화 필요
- 완료기준:
docker compose up으로 6서비스 기동 + Postgres 스키마 마이그레이션 통과 + 골든셋 50발화 라벨링 + IRB 신청서 제출
Phase 1 — MVP 코어 루프 (3~8주차) · 우선순위 P0
- 목표: 텍스트 기반 1-페르소나 상담→피드백 1회 완주 (chanpaca.net 시연 가능)
- 트랙 A (백엔드/AI): 엔진 어댑터 Messages API 직결 + 캐싱 레이어 + 상태머신(라포→탐색→개입→정리) + 내담자 AI(P1 페르소나) + 평가 AI deep-loop + 입출력 가드레일
- 트랙 B (프론트):
/learn셸 + 상담 시뮬레이션 UI 3존(대화60%·피드백패널40%·숨김안전배너) + SSE 스트리밍(React19useActionState/use) + 단계바 - 트랙 C (인프라): Cloudflare named tunnel → chanpaca.net + SSE 실측(50분 세션 끊김 테스트) → 끊기면 stream.chanpaca.net Funnel 분리
- 의존성: Phase 0 전부. 트랙 A·B는 SSE 스키마·점수 Structured Output 스키마 합의 후 병렬
- 완료기준: 교수님이 chanpaca.net에서 P1 내담자와 텍스트 상담 → 회기말 0-5 4차원 피드백+대안발화 수신 → 전 turn이 Postgres에 cost 텔레메트리 포함 적재. 저항 엔진 작동 검증(공감 시 개방도↑, 조언점프 시↓)
Phase 2 — 음성 + 3역할 + 페르소나 확장 (9~15주차) · 우선순위 P1
- 목표: 멀티모달 + 3역할 페이지 + 페르소나 3종 + 안전 가드레일 완성
- 트랙 A (음성): 캐스케이드(Deepgram STT → 엔진 → OpenAI TTS), persona→voice 매핑 테이블, 턴테이킹(semantic EOT·침묵 임계 1.2~2.0s), barge-in 로깅
- 트랙 B (3역할):
/teach(담당 학습자 전체 열람+검수 오버라이드)/admin(전부+교수활동 감사) + BFF OAuth 2.1 + RBAC×소유권 이중게이트 - 트랙 C (AI): 페르소나 P2·P3 추가(교수 검수), fast-loop 실시간 태깅, 한국어 자살콘텐츠 분류기(few-shot 5단계)
- 트랙 D (데이터): 재귀 학습 파이프라인(annotation_round + IAA 게이트), 교수자 검수 루프(AI vs 교수자 weighted-κ 누적)
- 의존성: Phase 1 코어 루프. 음성은 transcript 입력레일 위기분류와 결합 필수
- 완료기준: 음성 왕복 상담 round-trip
1.12.0s + 3역할 권한 격리 실동작 검증(학습자가 타인 기록 접근 차단) + safety_events 트리거→교수자 자동알림 + 교수 검수 데이터 누적
Phase 3 — IRB 파일럿 + 효과성 검증 (16~20주차) · 우선순위 P1
- 목표: 수련생 20명 IRB 파일럿 + 사전사후 효과 측정 + 데이터셋 골든화
- 작업: IRB 승인 하 20명 pre-post(자기효능감, 자살/자해 시나리오 1차 제외) + SUS·KPI 측정 + 골든셋 export_manifest → JSONL + 결과 리포트
- 의존성: Phase 2 전부 + IRB 승인(Phase 0 신청)
- 완료기준: 20명 세션 완주 + KPI 충족(임베딩 일관성≥0.79, 환각률≤5%, SUS≥80, κ≥0.6/ICC≥0.75) + 자기효능감 사전사후 유의 + 재귀학습 데이터셋 1차 산출
1차 명시 제외(2차 백로그)
6-에이전트 풀시스템 · 임상KG 자체구축 · 멀티벤더 A/B · 위기 4~5단계 자유시뮬 · RN 네이티브 앱(1차는 apps/mobile 스캐폴드+core import 검증만) · OpenAI Realtime s2s · K8s · Timescale 전면 도입 · 한신대 학내 SSO(1차 Google OIDC 단독)
5. 기술스택 확정
| 계층 | 확정 | 비고 |
|---|---|---|
| 프론트 | React 19 + Vite 정적빌드, SSE(useActionState/useOptimistic/use), pnpm+Turborepo 모노레포 |
packages/core 로직/타입/스키마 100% 공유, 추후 RN/Expo |
| 백엔드 | FastAPI + uvicorn(--workers, SSE 롱리브드 연결 산정) |
상태머신·가드레일·엔진 어댑터·SSE 스트리머 소유 |
| DB | PostgreSQL 16 + pgvector(RAG 통합), NAS 영구볼륨, RLS | Timescale은 hypertable 선택 확장 |
| 컨테이너 | Docker Compose 단일 호스트 모놀리식(6 컨테이너), Caddy 리버스프록시(flush_interval -1) |
이식=compose+secrets, 클라우드 VM(국내 리전) docker compose up |
| AI 엔진 | 엔진 어댑터 → 기본 Anthropic Messages API(Opus 4.8/Sonnet 4.6), claude -p(Max OAuth)는 옵션 플래그 |
과금 누수·동시성·rate limit 흡수. tier: client=Sonnet/Solar, feedback=Opus, cheap=Haiku |
| 음성 | local_whisper), TTS는 노트북 Higgs Audio v3. 근거·제약은 decisions/local-voice-stack.md |
s2s 1차 탈락(transcript 보존). Higgs 운영 사용은 라이선스 확인 전까지 dev 전용이라 운영 TTS는 OpenAI 유지 |
| 인증 | OAuth 2.1 Auth Code + PKCE(S256) BFF, Google OIDC 1차, Authlib | 토큰 Redis만, HttpOnly __Host- 쿠키, stateful 세션(IRB 철회 즉시 무효화) |
| 외부노출 | Cloudflare named tunnel + SSE는 Tailscale Funnel 분리 | 인바운드 포트 0 |
| 안전 | Presidio PII 마스킹 + NeMo rail + 한국어 자살분류 + 결정론 게이트 | Llama Guard 한국어 미지원 보강 |
6. 핵심 리스크 + 완화책
| # | 리스크 | 영향 | 완화책 |
|---|---|---|---|
| R1 | claude -p OAuth 과금 누수 (이틀 $1,800 사례) |
매칭금 증발 | 기본=Messages API 직결, claude_cli는 옵션 플래그+비용캡 모니터. 어댑터로 무중단 전환 |
| R2 | Cloudflare SSE 버퍼링·100초 timeout | 시연 중 스트림 끊김 | named tunnel(일반)+Tailscale Funnel(SSE) 분리, 30초 heartbeat, 전송계층 추상화 |
| R3 | positivity bias(저항 내담자 재현 실패) | 시뮬레이션 가치 저하 | 저항을 백엔드 결정론 수치로, Big5 저항 파라미터, CARE-Bench 회귀 테스트 |
| R4 | CCD 메타노출("제 핵심신념은…") | 추론 훈련 무력화 | 직접노출 금지 + QA 체크리스트 + Structured Outputs |
| R5 | 자살수단 정보 누출 | 법적 책임·안전 | ideation_stage ≤ 3 상한, 출력 가드레일, 4~5단계는 안전종료 시나리오만 |
| R6 | LLM-judge 편향(길이·성별) | 채점 타당도 | raw 직접사용 금지, 길이정규화, 이중코딩 κ≥0.6/ICC≥0.75, 성별 균형 |
| R7 | PII 외부 LLM 유출 | IRB·법적 책임 | Presidio 마스킹 미들웨어 강제, 마스킹 후만 적재·전송, safety_events 로깅 |
| R8 | 한국어 위기 분류 공백(Llama Guard 미지원) | 위기 미탐지 | JMIR 2026 한국어 자살콘텐츠 벤치(few-shot 5단계), 재현율 우선 |
| R9 | 한국어 토큰 팽창(최대 35%) | 비용 과소추정 | 실샘플 token counting, cost_usd 실측 적재 후 재추산, 캐싱 |
| R10 | NAS 단일 호스트 SPOF | 시연 중 다운 | 스냅샷 백업, pgdata 정기 덤프, 클라우드 VM 페일오버 리허설 |
| R11 | 한신대 SSO 미확인 | 2단계 일정 불확실 | 1차 Google OIDC 단독, SSO는 Authlib provider 추상화 뒤 2차, 공문 질의 |
| R12 | 20주 일정 압박 | 과대약속 실패 | 1차 범위 통제(2차 백로그 명시), MVP 코어 루프 우선, RN은 스캐폴드만 |
7. 학술 / IRB 체크리스트
학술 엄밀성
- DSM-5 차원 프로파일(RDoC) 반영, 진단명 외부 비노출 가드레일
- 가상내담자 충실도: Patient-Ψ(CCD 8요소) + Client101(비네트+메모리)
- 피드백 타당도: 검증 척도 이식(0-5, CTRS 0-6 분리), 4차원 채점, Structured Outputs
- 효과성 인과: Stanford CARE RCT(연습+피드백 d=0.72)로 피드백 필수성 입증 → 자유연습 비활성화
- LLM-judge 보정 프로토콜(이중코딩 vs LLM κ≥0.6/ICC≥0.75)
- 인용 논문 마스터 목록: PSI-Bench, PsychEval, TherapyGym/THERAPYJUDGE, Roleplay-doh, CARE-Bench, MIND-SAFE
IRB / 윤리
- "교육용·비치료용" intended use 고정(FDA General Wellness / 식약처 비의료기기)
- minimal risk 프로토콜, 자살 시나리오 1차 제외, 전문가 검증 내담자
- 수련생 20명 사전 동의(로그인 직후 하드 게이트, 미동의=시뮬레이션 라우트 서버 차단)
- 미성년 원본 데이터 4단계 격리, 법정대리인 활용동의 범위 확인
- PIPC(2024.12) + 생명윤리법 + 가명처리, 데이터 국내처리/해외전송 명시
- D6 컴플라이언스 매트릭스(APA/PIPC/WHO/Character.AI 판례/FDA)
- 한신대 공문 질의 필요: SSO 프로토콜/클레임, IRB 주관, 미성년 원본 활용동의, NAS 국내처리 보장
KPI(M5 수용기준): 임베딩 일관성≥0.79 · 환각률≤5%(목표≤1%) · Top-1≥0.80 · SUS≥80 · κ≥0.6/ICC≥0.75 · 저항 재현 · 자기효능감 사전사후
8. 즉시 착수할 다음 액션 Top 5
- 한신대 공문 질의서 발송 — SSO 프로토콜/클레임, IRB 주관 기관, 미성년 원본 사례데이터 법정대리인 활용동의 범위, NAS Postgres 국내처리 보장. (트웬티온스→한신대, 가장 긴 리드타임·블로킹 의존성)
- IRB 프로토콜 초안 작성·제출 — Stanford CARE 차용(minimal risk, 자살시나리오 1차 제외, 전문가 검증 내담자, 수련생 20명 사전동의). 승인 리드타임이 Phase 3 게이트.
- docker-compose 6서비스 스캐폴드 + Postgres 스키마 §3.2 + Caddyfile(
flush_interval -1) — 기존 풀스택팀에 인프라 베이스 인계. 이후 트랙 병렬화의 기반. - 0615 축어록 라벨 taxonomy v1.0 확정 + 골든셋 1차 라벨링 — 3축 분리(기법/내담자상태/슈퍼바이저논평) 코드테이블화. 평가 AI 정답셋 + 페르소나 상태전이 정답으로 이중 활용.
- 엔진 어댑터 PoC(Messages API 기본 + 캐싱 레이어 + Presidio 마스킹 선행) —
claude -p과금 누수 회피 검증 + P1 페르소나 1턴 응답 + 비용 텔레메트리 실측. claude_cli는 옵션 플래그로 병존.
부록 A. 도메인 설계서 원본 (절대경로)
- 학술근거·평가:
Projects/영업/2026/한신대학교 산학협력 프로젝트/설계서/01_학술근거_평가프레임워크_설계서.md - DSM-5 페르소나(M1):
…/scratchpad/M1_persona_engine_design.md - taxonomy·annotation:
…/_analysis/상담기법-슈퍼비전-taxonomy-annotation-스키마-설계서.md - 3-AI 오케스트레이션:
…/설계/3AI_오케스트레이션_아키텍처_설계서.md - 데이터모델·NAS Postgres:
Projects/수업/2026/한신대 SW중심대학 산학협력 2026/설계/데이터모델_NAS_Postgres_스키마_설계서.md - 인증·RBAC·IRB:
…/설계/auth-rbac-설계서.md - 실시간 음성 채팅:
…/설계/[설계서] 실시간 음성 채팅 아키텍처.md - 프론트엔드·UX:
…/설계/프론트엔드-UX-설계서.md - 배포·인프라: 본 마스터플랜 §1·§4·§5에 통합 (별도 파일 미생성)
부록 B. 디자인 철칙 (윤찬, 전 화면 강제)
border-left 강조선 · 이모지(SVG 내부 포함) · AI 양산형 카드덤프 · 무지개 점수색 전부 금지. 에디토리얼 미니멀, 한 페이지 한 메시지, 강조는 weight/배경틴트/상단 kicker. 채도 낮은 그린-그레이 신뢰 톤. (린트 강제 권장)