vignette/docs/DESIGN_CONCEPT.md

71 KiB
Raw Permalink Blame History

date type project tags status
2026-06-25 design-concept 한신대학교 AI 심리상담 시뮬레이션 훈련 플랫폼
디자인컨셉
디자인시스템
UX
아바타
한신대
통합본 v1

한신대 AI 심리상담 시뮬레이션 플랫폼 — 통합 디자인 컨셉 문서

이 문서 하나로 사이트를 만들 수 있다. 디자인 철학 → 디자인 시스템 토큰(실측값) → 가상 내담자 아바타(상세) → 상담 세션 화면 → 3역할 대시보드 → 컴포넌트·모션 → React 구현 노트 → 안티패턴 체크리스트까지, 추상적 형용사 없이 실제 hex·px·컴포넌트·인터랙션으로 적었다.

5개 영역 설계([design-language] / [design-system] / [avatar] / [session-ux] / [role-dashboards])를 단일 기준 문서로 종합한 것이다. 토큰 충돌 지점은 본 문서가 **단일 진실원본(SSOT)**으로 일원화했다.

재사용 자산 연계: 윤찬 기존 디자인 시스템(Resources/50_Tech_Dev/디자인/slide-base.css)과 동일한 토큰 철학(무채 골격 + accent 교체). slide-base 표의 "한신대/의료" 빈 행을 본 문서의 --accent로 채운다.

2026-06-27 구현 메모: 운영 기본은 dark 화면이다. docs/design-concepts/generated/*.png의 7개 주요 화면 컨셉을 기준으로 docs/design-verification/full-pages/에 PC/태블릿/모바일 21장 캡처를 남겼고, 자동 검사 기준은 가로 overflow 0 + 큰 흰 CSS 배경면 0이다. P1 세션 아바타는 사용자 제공 PSD 라투디 여캐_ver2.psd에서 추출한 seoyeon-live2d-psd-v2를 기본값으로 쓴다. 이 세트는 Live2D식 래스터 파츠 분리 자산이며, sad 표정에서 PSD의 울상 눈썹·우는 입·눈물 레이어를 사용한다. 컨셉 보드 크롭 p1-concept는 P1 기본값으로 쓰지 않는다.


0. 한 문장 컨셉과 SSOT 결정

0.1 컨셉

"불안한 사람을 다루는 사람을 위한, 차분한 임상 도구."

상담 수련생(학습자)이 가상 내담자 AI와 음성으로 대면하고, 뒤에서 평가 AI가 조용히 관찰한다. 이 화면은 두 종류의 신뢰를 동시에 줘야 한다.

  1. 임상적 신뢰감 — 학습자가 "이건 진지한 임상 훈련 장비다"라고 느낀다.
  2. 교육적 따뜻함 — 연습 중 실수해도 안전하다고 느낀다.

자극적·게임적이면 안 되고, 차갑고 행정적이어도 안 된다. 정답은 그 사이의 "조용한 따뜻함(quiet warmth)" — 스펙트럼 위 65% 임상 : 35% 따뜻함 지점이다.

화면은 "상담실"이지 "대시보드"가 아니다. 평가 정보는 상담실 벽에 걸린 은은한 시계처럼 곁에 있되, 내담자의 얼굴에서 시선을 빼앗지 않는다.

0.2 토큰 SSOT 결정 (5개 설계 영역의 색 통일)

5개 영역이 각각 미세하게 다른 그린(#5B7A6B / #3E7A6E / #4F6B5D / #0E7C7B / #0F766E)을 제안했다. 본 문서는 아래로 확정 일원화한다.

용도 확정값 근거
메인 accent (전역 기본) --accent: #3E7A6E (세이지-틸) 저채도·차분, 흰 배경 대비 약 5.0:1 (WCAG AA 통과). 흔한 메디컬 블루/형광 틸 회피. slide-base의 #0F766E보다 한 톤 더 낮춤.
역할별 보조 accent 학습자 #3E7A6E / 교수자 #3A5BA0 / 관리자 #5B5F6B 같은 골격, accent 한 토큰만 교체. 모두 저채도.
보조 온기 accent --clay: #B0735C (테라코타) 양산형 메디컬 블루를 깨는 "사람이 만든 교육 도구" 온기. 저채도로만, 화면당 1곳.

이유: 세이지-틸은 임상적 차분함(자연·회복·안정)과 따뜻함(흙·식물)을 동시에 품으면서, 한국 상담/심리 분야에서 과용되지 않아 차별화된다. 의료 블루는 흔하고 차갑다.

0.3 구현 소유권 계약

이 문서는 디자인 결정의 원본이고, 구현 권위는 아래 순서로만 내려간다. 같은 결정을 페이지마다 다시 정의하지 않는다.

계층 단일 소유자 허용 범위 금지
전역 토큰·테마 apps/web/src/styles/tokens.css 중성 팔레트, 의미색, 타이포, 간격, radius, light/dark 페이지 CSS의 전역 토큰 재정의
UI 프리미티브 apps/web/src/components/ui/ Button, Surface, Badge, Field, EmptyState 같은 의미 단위 페이지 안에 같은 프리미티브 재구현
앱 크롬·레이아웃 apps/web/src/components/shell/ topbar, sidebar, main 폭, safe area 페이지 CSS가 .vg-topbar/.vg-nav/.vg-main/.vg-shell 재정의
페이지·기능 apps/web/src/pages/ 해당 업무 흐름의 배치와 상태 표현 공통 셸·전역 테마 소유권 침범
집중 화면 예외 pages/session/session.css, 인증·아바타 전용 CSS 세션의 몰입형 dark stage, 실제 아트 합성에 필요한 국소 색 예외 토큰을 다른 페이지로 전파

현재 제품은 기존 브랜드와 IA를 보존하는 신뢰 우선 제품 UI다. 디자인 다이얼은 DESIGN_VARIANCE 4 / MOTION_INTENSITY 3 / VISUAL_DENSITY 6으로 고정한다. 모션은 상태 전환과 조작 피드백에만 쓰고, 데이터 밀도는 카드 중첩보다 여백·그룹·얇은 구분선으로 제어한다.

새 시각 규칙은 다음 순서로 결정한다.

  1. 이 문서에 이미 있는 원칙인지 확인한다.
  2. 전역 결정이면 tokens.css, 공통 의미 단위면 components/ui, 앱 크롬이면 components/shell에 둔다.
  3. 페이지 전용 결정만 페이지 CSS에 둔다. 새 raw color가 필요하면 기존 의미 토큰으로 표현할 수 없는 이유를 주석으로 남긴다.
  4. 라우트 화면은 React.lazy로 분리하고 Suspense 로딩·오류 경계를 유지한다. 초기 진입 번들에 모든 역할 화면을 다시 합치지 않는다.
  5. npm run check:design-ssot, 타입체크, 프로덕션 빌드와 해당 시각 E2E를 통과해야 완료다.

1. 핵심 디자인 원칙 (신성불가침 5개)

원칙 1 — One Screen, One Intent (한 화면 한 의도)

상담 시뮬레이션은 본질적으로 집중을 요구한다. 학습자가 가상 내담자의 말에 귀 기울이는 순간 화면에 버튼 12개·카드 9개가 깔려 있으면 안 된다. 모든 화면은 그 순간의 단 하나의 주된 행동(말하기 / 듣기 / 피드백 읽기 / 세션 시작)을 중심으로 설계한다. 부차 정보는 위계 아래로.

  • 적용: 세션 진행 화면 = 중앙에 내담자 발화 + 음성 비주얼 하나. 평가 피드백은 화면 가장자리 차분한 사이드 패널로, 절대 모달로 튀지 않는다.

원칙 2 — 위계는 색 블록이 아니라 타이포 weight + 여백으로

Stripe·Linear의 공통점: 테두리·색 박스로 구역을 나누지 않고 여백과 글자 굵기로 나눈다. 강조는 ①font-weight(400→600) ②accent 텍스트/언더라인 ③상단 kicker(소제목) ④accent dot 으로만. border-left 강조선·좌측 사이드바 강조줄·색 박스 카드 격자 절대 금지.

  • 적용: 평가 피드백 "공감 반영: 우수"를 초록 배지로 칠하지 않는다. kicker("공감 반영") + 본문 한 줄 + 미세한 accent dot 한 점으로 위계를 만든다.

원칙 3 — 임상적 차분함 = 채도를 죽인 중성 베이스 + 절제된 단일 악센트

Calm/Headspace에서 배울 건 파스텔 그라데이션이 아니라 고채도·고대비를 의도적으로 피하는 절제다. 베이스는 따뜻한 회백(off-white)·차분한 슬레이트. 악센트는 세이지-틸 단 하나를 화면당 1군데만 배급(Linear의 "accent rationing"). 빨강·주황 경고색은 진짜 오류/위험에만.

  • 근거: 불안한 내담자를 다루는 훈련 도구이므로 자극적 색은 학습자 정서·임상 톤 양쪽에 해롭다. 녹색은 우울·불안·스트레스 점수를 가장 많이 낮춘 색이며 "go/긍정" 신호로도 조용히 작동한다.

원칙 4 — 따뜻함은 "둥근 카드"가 아니라 "휴머니스트 타이포 + 따뜻한 중성톤 + 넉넉한 여백"

따뜻함을 둥근 모서리·말랑한 일러스트로 내면 임상 신뢰가 깨진다(애들 앱처럼 보임). 대신 헤드라인에 휴머니스트 세리프 한 톤 옵션(therapy 웹의 정설: serif=신뢰·인간미), 본문은 깔끔한 산세리프. 순백(#FFF) 대신 따뜻한 종이색, 순흑 대신 잉크 네이비-그린. 이 미세한 온기가 "행정 시스템"과 "사람을 위한 도구"를 가른다.

  • 주의: 한글 본문은 Pretendard 단일 패밀리를 기본으로 한다(국문 상담 도메인 가독·중립). 세리프 헤드라인은 랜딩·표지 같은 희소 지점에서만 선택 적용(본명조). UI 전반은 산세리프 weight 위계로 통일.

원칙 5 — 평가 AI는 판사가 아니라 조용한 멘토 (Non-judgmental surfacing)

실시간 피드백이 빨간 X·점수 폭격·"틀렸습니다"로 뜨면 학습자는 위축된다. 피드백은 관찰("이 지점에서 내담자가 방어적으로 반응했어요") → 제안("열린 질문으로 바꿔볼까요?") 순서의 서술형·저채도·비모달로. 점수는 세션이 끝난 뒤 회고 화면에서만, 절대값이 아니라 성장 추세로.


2. 무드 좌표 (임상 ↔ 따뜻함 균형)

양 극단(차가운 EHR / 말랑한 명상앱) 사이, 65% 임상 : 35% 따뜻함.

임상 신뢰(차가움) ← → 우리 좌표 ← → 따뜻함(부드러움)
베이스색 순백·차가운 그레이 따뜻한 off-white #FBFAF8 + 차분한 슬레이트 크림·파스텔
악센트 임상 블루 세이지-틸 #3E7A6E 코랄·더스티 로즈
헤드라인 기하 산세리프 산세리프 weight 위계 (희소 지점만 본명조 옵션) 손글씨·라운드
모서리 직각 6~8px (거의 직각, 미세 라운드) 16px+ 둥근
그림자 없음(헤어라인) 1px 헤어라인 + 아주 약한 그림자 부드러운 큰 blur
모션 즉각·없음 200~320ms ease-out, 절제 느린 호흡 애니메이션

단 하나의 예외 — 음성 듣기 중 마이크/오브의 느린 호흡 펄스. 이건 "지금 듣고 있다"는 정서적 안심 신호라 의도적으로 명상앱 호흡 모션을 차용한다.


3. 디자인 시스템 토큰 (그대로 :root에 붙여 쓰는 실측값)

CSS 변수는 primitive(원시값) → semantic(의미 별칭) 2계층. 컴포넌트는 semantic만 참조 → 다크모드 1곳에서 스왑.

3.1 중성 베이스 (Neutral) — 골격

순백/순흑 금지. 따뜻한 종이색 + 잉크 네이비-그린.

:root {
  /* ── Primitive: Neutral (따뜻한 종이 + 쿨 슬레이트) ── */
  --paper:       #FBFAF8;  /* 본문 배경: 따뜻한 종이색 (순백 아님) */
  --paper-2:     #F4F2EE;  /* 카드/패널 미세 단차 (테두리 대신 톤차) */
  --surface:     #FFFFFF;  /* 카드 표면 (캔버스가 종이색이라 분리됨) */
  --neutral-100: #ECEFF1;  /* 표면 hover / subtle fill */
  --neutral-150: #E5E1DA;  /* 카드 보더 baseline = hairline */
  --neutral-200: #D5DBDE;  /* divider 진함 */
  --neutral-400: #98A4A9;  /* placeholder / disabled */

  --ink:        #1C2A2A;  /* 본문 텍스트: 잉크 네이비-그린 (순흑 아님) */
  --ink-2:      #5A6663;  /* 보조 텍스트: 슬레이트 */
  --ink-3:      #93A09C;  /* 캡션/메타 */
  --hair:       #E5E1DA;  /* 1px 헤어라인 (구역 분리는 이걸로) */
}

3.2 악센트 — 1주 + 1보조 (저채도)

:root {
  /* ── Sage-Teal (주 악센트 = 상담/신뢰), 화면당 1곳 배급 ── */
  --accent:      #3E7A6E;  /* ★ 메인 악센트 (버튼/링크/포커스). 흰 배경 대비 5.0:1 AA */
  --accent-deep: #316257;  /* hover / 진한 강조 텍스트 */
  --accent-tint: #EEF4F2;  /* 악센트 배경 틴트 (콜아웃·선택·active) */
  --accent-bright:#5F968B; /* dot·진행바 fill (화면 전용) */

  /* ── Terracotta (보조 악센트 = 학습/온기), 저채도, 화면당 1곳 ── */
  --clay:      #B0735C;  /* ★ 보조 악센트 (학습자 온기 포인트, 내담자 측 신호) */
  --clay-deep: #94604C;
  --clay-tint: #F6F0EC;
}

--accent #3E7A6E는 흰 배경 명도대비 약 5.0:1 → 본문 링크/버튼 텍스트 WCAG AA 통과. 2색을 동시에 큰 면적으로 쓰지 않는다 — sage가 전역 기본, clay는 학습자 모드/온기 포인트에서만 점·언더라인·소형 fill로.

3.3 의미색 (Semantic feedback) — solid + tint 페어

각 의미색은 아이콘/텍스트용 solid + 배경용 tint. tint 위 text는 모두 AA(4.5:1↑).

:root {
  /* 긍정 = 녹색 (상담 진전·라포 형성·가드레일 통과·잘함) */
  --pos-text:  #2C6E49;   --pos-solid: #3B8C5E;   --pos-tint:  #E8F3EC;

  /* 주의 = 앰버 (라포 약화·과도한 침묵·페이싱) — 빨강 대신 머스터드 */
  --warn-text: #8A5A00;   --warn-solid:#C28A2C;   --warn-tint: #FAF1E0;

  /* 위험 = 적색 (가드레일 위반·세션 강제중단·임상적 위급) — 오직 진짜 위급만 */
  --crit-text: #A8352C;   --crit-solid:#C4453A;   --crit-tint: #FAEAE8;

  /* 정보 = 슬레이트블루 (평가 AI 피드백·시스템 안내, 중립) */
  --info-text: #2E5A7A;   --info-solid:#3C7299;   --info-tint: #EAF1F6;

  --neutral-sig:#8895A2;  /* 데이터 없음·미평가 */
}

핵심 원칙: 평가 AI의 실시간 피드백 기본 톤은 info(슬레이트블루) 또는 pos(녹색) 으로 — 학습자가 비난받는 느낌을 받지 않게. 빨강은 코칭 피드백에 절대 쓰지 않고, 가드레일/위급에만.

3.4 시맨틱 별칭 (라이트 모드)

컴포넌트는 primitive를 직접 부르지 않고 이 별칭만 참조.

:root {
  --bg-app:        var(--paper);        /* 앱 캔버스 */
  --bg-surface:    var(--surface);      /* 카드/패널 */
  --bg-surface-2:  var(--paper-2);      /* 중첩 표면/입력 */
  --bg-tint:       var(--accent-tint);  /* 선택·강조 배경 */
  --bg-stage:      #1E2724;             /* 내담자 아바타 영역 (깊은 차콜그린, 시선 집중) */

  --text-strong:   var(--ink);          /* 제목 */
  --text-body:     var(--ink-2);        /* 본문 보조 */
  --text-muted:    var(--ink-3);        /* 캡션 */
  --text-on-accent:#FBFAF8;             /* accent 버튼 위 텍스트 */

  --border-subtle: var(--neutral-150);
  --border-strong: var(--neutral-200);
  --border-focus:  var(--accent);
  --focus-ring:    color-mix(in srgb, var(--accent) 45%, transparent);
}

3.5 다크 모드 (gloom 회피 — 충분한 밝은 면 + 절제된 악센트)

배경은 한색 슬레이트(순흑 아님). 악센트는 명도를 올려 가독 확보. 운영 기본 표면은 dark이며, 저장 theme 값이 없거나 API preference가 system이면 light로 떨어지지 않고 앱 초기 dark 값을 따른다. dark 화면 안의 대형 카드/섹션은 순백·밝은 베이지 면을 쓰지 않는다.

[data-theme="dark"] {
  --bg-app:        #131A1E;   --bg-surface:    #1A2429;   --bg-surface-2:  #222E34;
  --bg-tint:       #1E2E2A;   --bg-stage:      #0E1614;
  --text-strong:   #EAF0F1;   --text-body:     #C4CFD3;   --text-muted:    #88969C;
  --text-on-accent:#0F1A17;
  --border-subtle: #2A363C;   --border-strong: #38454C;   --border-focus:  #6FB3A4;
  --accent:        #6FB3A4;   --accent-deep:   #84C2B4;   --accent-tint:   #1E2E2A;
  --clay:          #CC8F77;

  --pos-text:  #7FD0A0;  --pos-solid: #5FB682;  --pos-tint:  #16271D;
  --warn-text: #E2B566;  --warn-solid:#D4A24A;  --warn-tint: #2A2415;
  --crit-text: #E89086;  --crit-solid:#D86459;  --crit-tint: #2A1715;
  --info-text: #79B0D4;  --info-solid:#5C97BE;  --info-tint: #15222C;
}

3.6 타이포그래피

역할 폰트 이유
본문/UI 기본 Pretendard Variable 한글 UI 사실상 표준. 9 weight 가변, 숫자 정렬 우수. 임상 데이터·평가 점수 표기에 깔끔.
숫자·타임코드 Pretendard + tabular-nums 세션 타이머·점수는 정렬 필요 → font-variant-numeric: tabular-nums.
(옵션) 랜딩 헤드라인 Noto Serif KR (본명조) 신뢰·인간미. 희소 지점만(표지·히어로). UI 전반은 산세리프.
:root {
  --font-sans: "Pretendard Variable", Pretendard, -apple-system,
               "Apple SD Gothic Neo", "Noto Sans KR", system-ui, sans-serif;
  --font-serif:"Noto Serif KR", "Source Serif 4", serif;  /* 랜딩 헤드만 */
  --font-num:  "Pretendard Variable", "JetBrains Mono", ui-monospace, monospace;
}
body { font-family: var(--font-sans); -webkit-font-smoothing: antialiased;
       text-rendering: optimizeLegibility; }
.tabular { font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }

CDN: https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/variable/pretendardvariable.min.css

타입 스케일 (기준 본문 16px / 1.6, 한글 자간 -0.01~-0.02em. 위계는 크기보다 weight로):

토큰 px / rem line-height weight letter-spacing 용도
--fs-display 40 / 2.5rem 1.2 700 -0.02em 표지·랜딩 대제목 (희소)
--fs-h1 30 / 1.875rem 1.3 700 -0.02em 페이지 제목
--fs-h2 24 / 1.5rem 1.35 600 -0.015em 섹션 제목
--fs-h3 20 / 1.25rem 1.4 600 -0.01em 카드/패널 제목
--fs-lead 18 / 1.125rem 1.6 400 -0.01em 리드 문장
--fs-body 16 / 1rem 1.6 400 -0.01em 본문 기본
--fs-sm 14 / 0.875rem 1.55 400 0 보조·폼 라벨
--fs-xs 13 / 0.8125rem 1.5 500 0.01em 캡션·메타·배지
--fs-kicker 12 / 0.75rem 1.4 600 0.08em 상단 kicker 소제목

강조 방식(철칙): 색 블록·border-left 금지. ① weight 400→600 ② accent 텍스트 컬러 ③ 은은한 --accent-tint 배경 틴트 ④ 상단 kicker(작은 도트 동반). kicker가 양산형 좌측바를 대체하는 위계 신호다.

3.7 스페이싱 (8pt 기반, 넉넉하게)

:root {
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 64px; --sp-9: 96px;
}

원칙: 컴포넌트 내부 패딩은 8의 배수, 섹션 간 간격은 48~96px 넉넉히. 불안 완화의 핵심은 여백. 카드 내부 패딩 기본 --sp-5(24px), 패널 --sp-6(32px), 읽기 영역 max-width 640~680px.

3.8 그리드·형태

:root {
  --maxw: 1200px;          /* 대시보드 콘텐츠 최대폭 */
  --maxw-read: 680px;      /* 읽기 영역 */
  --nav-w: 240px;          /* 좌측 네비 펼침 */
  --nav-w-collapsed: 72px; /* 좌측 네비 아이콘 only */
  --radius: 8px;           /* 카드/버튼/입력 (거의 직각) */
  --radius-sm: 6px;        /* 입력·칩 */
  --radius-lg: 12px;       /* 패널 */
  --gutter: 24px;
}
  • border-radius: 카드 8px, 버튼 8px, 입력 6px (거의 직각, 미세 라운드만). 원형은 음성 오브·아바타·dot만 예외.
  • 깊이는 1px 헤어라인(--hair) + 화면용 아주 약한 그림자. glow·gradient-text·큰 blur 금지.
:root {
  --shadow-sm: 0 1px 2px rgba(28,42,42,.05);
  --shadow-md: 0 4px 14px rgba(28,42,42,.07);   /* 모달·팝오버만 */
}

3.9 모션

:root {
  --ease-out: cubic-bezier(.22,.61,.36,1);
  --ease-in-out: cubic-bezier(.45,.05,.55,.95);
  --dur-fast: 120ms;     /* hover·포커스 */
  --dur-base: 200ms;     /* 버튼·토글·드롭다운 */
  --dur-slow: 320ms;     /* 패널 전환·모달 */
  --dur-breathe: 3200ms; /* 음성 호흡 펄스 */
}
@media (prefers-reduced-motion: reduce) {
  *,*::before,*::after { animation-duration:.01ms!important; transition-duration:.01ms!important; }
}

원칙: 차분·짧게·자연 이징. 불안 도구이므로 튀는 스프링/바운스 금지. 화면 전환은 페이드+미세 슬라이드(translateY 8px 이하). 실시간 피드백 칩은 자리 미리 확보 후 fade(밀어내기/점프 금지 — 레이아웃 시프트가 불안 유발). prefers-reduced-motion 필수 대응.


4. 가상 내담자 아바타 (이 플랫폼의 심장)

학습자의 시선이 30~50분간 머무는 단 하나의 오브젝트. 산만하면 라포 연습을 방해하고, 과하면 실제 환자로 오인되며, 빈약하면 몰입이 깨진다.

4.1 추천: "반(半)구상 페르소나 카드 (Semi-figurative Persona Card)"

사실적 얼굴도, 추상 오브도 아닌 그 사이. 사실성 35~45%의 양식화 반구상 흉상 + 호흡하는 광배(aura).

표현 방식 비교 (왜 이걸 골랐나)

방식 몰입 제작비용(20주) 윤리/오인 위험 불쾌한 골짜기 결론
A. 추상 오브 / 음성 비주얼라이저 낮음 매우 낮음(1주) 없음 없음 폴백으로만(미선택/로딩/에러)
B. 2D 양식화 일러스트(반구상) 높음 중간(3~6주) 낮음 회피 가능 ★ 1차 채택
C. 실사 / AI생성 얼굴 매우 높음 높음 높음 직격(최악) 탈락
D. Live2D / 3D 매우 높음 매우 높음(6~10주+) 중간 리깅 품질 의존 2차/장기 후보
  • B를 고른 이유: 사실성을 의도적으로 35~45%에 고정 → 불쾌한 골짜기 회피. 벡터라 페르소나별 파라미터(피부톤·헤어·눈 형태·연령감)를 데이터로 찍어내 시스템화 가능(페르소나 무한 확장). 눈·눈썹·입꼬리·어깨선 4채널만으로 저항/라포/정서를 은은히 표현. 윤찬 미니멀 톤과 정합.
  • C 탈락: 80% 사실성에서 미세 립싱크 오차가 더 크게 불쾌. 미성년·취약 내담자를 실사로 그리면 "이 아이 실존?" 윤리 문제 + 데이터 편향.
  • A를 폴백으로 흡수: ElevenLabs Orb 같은 성숙한 React 자산을 페르소나 미선택/로딩/에러 화면에 영구 잔존.

카드 구조

┌─────────────────────────────────────┐
│  [상단 kicker]  교육용 가상 내담자       │  ← 상시 라벨(오인 차단)
│                                       │
│         ╭───────────────╮             │
│        │   양식화 흉상      │            │  ← 어깨~머리, 평면 벡터
│        │   (얼굴 35% 사실)   │            │     배경에 호흡하는 광배
│         ╰───────────────╯             │
│                                       │
│   서연 · 17세 · 고2                     │  ← 페르소나 메타 1줄
│   ──────────                          │
│   지금: 머뭇거리며 듣는 중               │  ← 상태 텍스트 1줄
└─────────────────────────────────────┘

핵심: 얼굴은 양식화하되 "사람"으로 읽히고, 절대 "실존 인물"로는 안 읽히게. 코·주름·모공 없음. 눈·눈썹·입꼬리·어깨 각도가 정서를 나르는 4개 채널.

4.2 음성 발화 중 반응 — 상태 모델 (4-state)

음성 UI 표준 idle/listening/thinking/speaking을 내담자 맥락으로 재정의.

상태 트리거 눈/눈썹 광배(aura) 어깨 호흡
listening (학습자 발화 중) 마이크 입력 감지 닫힘, 미세 입꼬리 학습자 쪽 응시, 깜빡임 4~6s 차분 펄스 0.06 opacity, 5.5s 진폭 1.5px, 4s
thinking (응답 생성 대기) STT 종료~TTS 시작 살짝 다묾 시선 살짝 아래/옆, 깜빡임 느려짐 안쪽 수축, 채도 -8% 정지에 가깝게
speaking (내담자 발화) TTS 오디오 재생 립싱크 진폭 정면 복귀, 눈썹 정서 반영 발화 진폭에 약동기(0.04~0.12) 발화 리듬따라 미세
idle (시작 전/일시정지) 무입력 닫힘 천천히 깜빡, 가끔 시선 이동 최소 펄스 느린 호흡 3.5s

4.3 립싱크 — "정밀 음소 매칭 안 함"이 정답

35% 사실성 얼굴에 정밀 비짐(viseme) 매핑은 오히려 불쾌. 오디오 진폭(RMS) → 입 열림 높이 1채널 매핑.

// Web Audio AnalyserNode → 매 프레임 RMS → 입 SVG path 세로 스케일
const rms = getRMS(analyser);            // 0~1
const mouthOpen = smooth(rms, 0.18);     // 지수평활(튐 방지), τ≈180ms
// <path class="mouth" style={{ transform:`scaleY(${0.35 + mouthOpen*0.65})` }}/>
  • 입 모양: 닫힘=얇은 호, 열림=타원. scaleY만 변형. 이빨·혀 절대 안 그림.
  • 데드존: rms < 0.04는 닫힘 고정 → 무음 구간 입 떨림 제거.
  • 평활 필수: raw RMS 직결하면 입이 경련함. τ=150~200ms.

4.4 모션 진폭 가이드 (산만함 차단의 핵심)

모션 진폭 주기/속도 비고
어깨 호흡(idle) translateY 1.5~2.5px 3.5~5.5s ease-in-out 무한 "있는 줄 모르게"
깜빡임 scaleY 1→0.08→1 120ms, 간격 4~7s 랜덤 생체감의 80%가 여기서
광배 펄스 opacity ±0.04~0.08 5~6s speaking 때만 오디오 동기
시선 이동(saccade) ±3px 0.3s, 간격 6~10s thinking에서 빈도↑
립싱크 scaleY 0.35~1.0 오디오 실시간 데드존+평활

원칙: 동시에 움직이는 채널 ≤ 2개. speaking이면 입+광배만. listening이면 깜빡임+호흡만.

4.5 정서 시각화 — 6파라미터 상태머신

valence/arousal 축을 아바타 파라미터로 인코딩. 과장 절대 금지(만화적 눈물·홍조·땀방울 전부 금지). 상담 도구의 정서는 "감지되되 단언되지 않는" 수준.

내담자 정서 눈/눈썹 입꼬리 자세(어깨선) 광배 색조 호흡
중립/라포 눈썹 수평, 눈맞춤 미세 상향 정면, 약간 열림 세이지 #3E7A6E 4% 안정 4s
우울(저각성·부정) 눈꺼풀 1~2px 하강, 시선 아래 수평~미세 하향 어깨 안으로·아래로 청회색 #5B6B73 5% 느리고 얕게 5.5s
불안(고각성·부정) 깜빡임↑(2~4s), saccade↑ 다묾, 긴장 약간 들썩 차가운 청 #3B6E8F 5%, 빠른 펄스 빠르고 얕게 3s
저항/방어 시선 회피(옆/아래 고정) 굳게 닫힘 반쯤 돌아선 각도(turn 8°) 중립 회색, 무펄스 정지에 가깝게

상태머신이 (eyelidDrop, gazeAvert, shoulderTurn, breathRate, auraHue, blinkInterval) 6개 숫자만 바꾸면 정서 전환. 라포가 쌓이면(세션 진행) 저항 페르소나가 shoulderTurn 8°→0°, gazeAvert→눈맞춤으로 서서히 완화 → 학습자가 "내가 라포를 만들었다"를 시각적으로 체감. 이게 이 도구의 교육적 핵심. 정서 전환은 0.8~1.2s ease로 천천히, 동시 변하는 파라미터 ≤3개.

4.6 페르소나 파라미터 시스템 (새 페르소나 = 새 숫자 묶음)

// persona/seoyeon.json — 청소년 페르소나 예시
{
  "id": "seoyeon",
  "label": "서연 · 17세 · 고2",
  "appearance": {
    "ageBand": "teen",              // teen | youngAdult | adult | senior
    "skinTone": "#E8C9A8",
    "hair": { "style": "long-straight", "color": "#2B2723" },
    "faceRatio": { "eyeSize": 1.15, "jawWidth": 0.92 },  // teen=큰 눈·좁은 턱
    "outfit": "hoodie",             // 실루엣만, 디테일 X
    "realism": 0.40                 // 0.35~0.45 고정(불쾌한 골짜기 회피)
  },
  "voice": { "provider": "openai", "preset": "soft-young-fem", "rate": 0.96 },
  "baseAffect": "anxious",          // 시작 정서
  "resistance": 0.6,                // 0~1, 라포로 감소
  "auraHueShift": -6
}

연령대 외형 규칙

ageBand 눈 크기 턱/얼굴 실루엣 광배 채도 음성 톤
teen 1.1~1.2× 좁은 턱·둥근 후디·체크 약간 높음(생기) 부드럽고 높은
youngAdult 1.0× 표준 캐주얼 중간 표준
adult 0.95× 각진 턱 셔츠·니트 낮음(차분) 낮고 안정
senior 0.92× 부드러운 윤곽 단정 낮고 따뜻 느린
  • 미성년 페르소나는 realism을 0.35로 더 낮추고 교육용 가상 내담자(미성년 시뮬레이션) 라벨 강화 → 실존 미성년 오인 원천 차단.
  • 외형은 인종·특정 외모 stereotype 회피를 위해 중립 톤 팔레트 3~4종만 제공(편향 최소화).

4.7 아바타 구현 기술 — SVG 1차, Rive 2차

기술 적합 근거
SVG + CSS/Web Animations + Web Audio ★ 1차 페르소나=벡터 파라미터, 립싱크=RMS 1채널, 의존성 0, React 친화, 미니멀 정합
Rive (상태머신) ★ 2차 고도화 상태머신이 .riv에 내장, React는 input만 wiring. Lottie 대비 파일 10~15× 작음
Lottie 보조 정형 애니(로딩·전환)엔 OK, 실시간 오디오 반응엔 부적합
Live2D/3D 장기 표현력 최고지만 20주·시스템화 불리

1차안 컴포넌트 구조 (SVG)

<ClientAvatar persona state affect analyser/>
 ├─ <AuraLayer hue affect state/>     // 배경 광배: radial-gradient, opacity 펄스
 ├─ <BodySilhouette persona/>         // 어깨선, shoulderTurn 각도
 ├─ <FaceGroup persona affect>
 │    ├─ <Eyes blink gaze eyelidDrop/>
 │    ├─ <Brows affect/>              // 정서별 각도 2~3px
 │    └─ <Mouth analyser state/>      // RMS→scaleY 립싱크
 └─ <PersonaLabel/>                    // "교육용 가상 내담자" 상시
// 단일 rAF 루프, 의존성 0
function useAvatarMotion(state, affect, analyser) {
  const [frame, setFrame] = useState(initFrame(affect));
  useEffect(() => {
    let raf, t0 = performance.now();
    const loop = (t) => {
      const dt = (t - t0) / 1000;
      const breath = Math.sin(dt * (2*Math.PI/affect.breathPeriod)) * affect.breathAmp;
      const mouth  = state==='speaking' ? smoothRMS(analyser) : 0;
      const blink  = blinkSchedule(t, affect.blinkInterval);
      setFrame({ breath, mouth, blink, gaze: gazeFor(state) });
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, [state, affect, analyser]);
  return frame;
}
  • 퍼포먼스: SVG 변형은 transform(GPU 합성)만, layout 트리거 속성(width/top) 금지. 단일 rAF, 60fps 여유.
  • RN 이전 대비: SVG는 react-native-svg, Web Audio는 react-native-audio-api로 대체 → 로직 재사용. Rive도 RN 런타임 있음.
  • 접근성: prefers-reduced-motion 켜지면 호흡·광배 정지, 상태는 텍스트로만.

5. 상담 세션 화면 (메인 화면)

핵심 긴장: 몰입 vs 평가 가시성. 실시간 피드백이 라포 형성을 방해하면 안 되고, 평가가 사후로만 묶이면 학습 효과가 떨어진다. 해법 = 2단(two-tier) 피드백 모델 — 실시간은 "신호(signal)" 수준, 정밀 평가는 "회기말 리뷰"로.

5.0 회기 시작 전 준비 화면

  • 헤더와 준비 본문은 같은 가용 폭을 사용한다. 별도의 고정 카드 폭으로 페이지 축을 끊지 않는다.
  • 데스크톱은 내담자 요약·회기 설정·진행 초점의 3열이되, 열은 고정 px가 아니라 가용 폭에 비례해 확장한다.
  • 진행 초점은 장식용 문구가 아니라 현재 단계, 선택 이론의 대화 기준, 이번 목표, 시간·안전 운영 기준을 즉시 확인하는 동적 브리핑이다.
  • 좁은 화면에서는 회기 시작이라는 단일 의도를 지키기 위해 진행 초점을 숨기고 핵심 설정과 시작 버튼을 우선한다.

5.1 3-column 골격 (데스크탑 ≥1280px)

┌──────────────────────────────────────────────────────────────────────────┐
│  상단 바 (80px)  좌:기록  중앙:회기 상태·단계·시간  우:학습 홈              │
├──────────────────┬──────────────────────────────────┬──────────────────────┤
│  LEFT (326px)    │       CENTER (flexible)          │   RIGHT (357px)      │
│  ─────────────   │       ─────────────────          │   ─────────────      │
│  내담자 컨텍스트   │     [ 아바타 + 이름·사례 요약 ]      │   AI 코치·코칭 기회     │
│  회기 단계 트랙커  │     [ 현재 표정·발화 상태 ]         │   코칭 포인트          │
│  (라포→탐색→       │                                  │   음성·AI 응답 상태     │
│   개입→정리)      │     실시간 자막 (아래→위 흐름)      │   ── 관찰 신호 ──      │
│  세션 진행        │                                  │   방어·개방·라포 게이지 │
│  시간·남은시간·턴  │                                  │   ── 안전 점검 ──      │
├──────────────────┴──────────────────────────────────┴──────────────────────┤
│  하단 컨트롤 바 (116px) 마이크 · [몰입│상태 신호│코칭] · 일시정지 · 회기 종료   │
└──────────────────────────────────────────────────────────────────────────┘

비율 의도: 시각적 무게 = 주의 배분. 내담자 stage 60%, 평가 패널 15%(평시 대부분 접힘). 화면은 대시보드가 아니라 상담실이다.

활성 세션도 전역 data-themetokens.css 의미 토큰을 그대로 따른다. 세션 전용 로컬 팔레트로 --bg-surface·--text-*·--accent를 다시 정의하지 않으며, 패널과 AI 코치 인셋은 공통 Surface가 소유한다. 라이트에서는 종이·글래스 무대, 다크에서는 차콜·세이지 무대로 함께 전환한다.

라이트 데스크톱의 시각 기준은 1536×1024 보태니컬 워크스페이스다. 좌·우 레일은 작은 카드를 쌓지 않고 각각 하나의 연속 표면으로 보이며, 중앙만 인물 무대와 자막으로 분리한다. 장식은 apps/web/public/session-botanical/leaf-1.webp~leaf-5.webp의 투명 수채화 자산을 좌우 캔버스와 아바타 뒤에 배치한다. 자산은 상호작용과 정보보다 뒤에 놓고 pointer-events:none을 유지하며, 다크 테마에서는 밝기·채도를 낮춘다.

반응형:

  • 중간 폭(881~1180px): 단계·현재 신호는 상단 회기 요약으로 압축한다. 평시 RIGHT 진단 레일은 숨기되 코칭 모드에서는 AI 코치 카드만 하단 전폭으로 보존한다.
  • 모바일(≤880px): 단일 컬럼. stage·자막을 우선하고 단계·상태는 상단 요약으로 압축한다. 코칭 모드에서는 진단·장식을 제외한 AI 코치 카드만 본문 아래에 유지한다.
  • 넓지만 짧은 화면(≥1280px, 높이 ≤820px): 스테이지를 약 182px까지 압축해 자막을 주 작업영역으로 보존하고, 발화 예시·보조 흐름 설명을 먼저 접는다.
  • 그 외 짧은 높이(≤700px): AI 코치의 판단·본문·근거/이력 액션을 먼저 보존하고 발화 예시와 보조 흐름 설명을 접는다.

5.2 중앙 STAGE — 음성 오브 (Voice Orb, 4상태)

자극적 막대 파형 대신 차분한 호흡(breathing) 애니메이션. 아바타(원형 220px) 둘레 오브 링.

상태 시각 모션
내담자 말하는 중 따뜻한 링, 음량 따라 미세 진동 --clay glow, 두께 4px 음량 연동 amplitude(0.5~3px), 0% 형광
학습자 말하는 중 세이지 링, 호흡 펄스 --accent glow 1.4s ease breathing scale 1.0→1.04
대기/침묵(thinking) 가는 점선 매우 느리게 회전 --ink-3 8s/회전, 거의 안 보일 정도
일시정지 반투명 오버레이 + "일시정지" --bg-stage 60% 정지
.orb {
  position: absolute; inset: -14px; border-radius: 50%;
  box-shadow: 0 0 0 3px var(--ring-color),
              0 0 28px 4px color-mix(in srgb, var(--ring-color) 35%, transparent);
  transition: box-shadow 320ms ease;
}
.orb[data-state="learner"] { --ring-color: var(--accent); animation: breathe 1.4s ease-in-out infinite; }
.orb[data-state="client"]  { --ring-color: var(--clay); /* JS가 RMS 음량을 --amp로 주입 */ }
@keyframes breathe { 0%,100%{ transform: scale(1) } 50%{ transform: scale(1.035) } }

음량 연동은 JS onVolumeChange/RMS → CSS 변수 --amp로 box-shadow blur 미세 모듈레이션. 막대 파형(equalizer) 금지 — 너무 "녹음 앱"스럽고 자극적. 호흡하는 빛이 임상적이다.

5.3 실시간 자막 (Transcript) — 대본 스타일

음성이 주, 자막은 보조. stage 하단, 아래→위 흐름. 채팅 버블 양산형 회피, 대본(script) 스타일:

─────────────────────────────────────
  내담자                        14:32
  요즘은 그냥… 아침에 일어나는 게
  제일 힘들어요.
  나(학습자)                    14:33
  아침에 일어나는 것조차 버겁게
  느껴지시는군요. 그 마음을 조금
  더 들려주실 수 있을까요?
─────────────────────────────────────
  • 화자 라벨 12px 600 메타톤. 내담자 발화는 --clay-tint 옅은 배경 틴트 블록, 학습자 발화는 --accent-tint 틴트. 버블 외곽선·꼬리·border-left 없음. 틴트 블록만으로 화자 구분.
  • 진행 중 발화(partial)는 --ink-3 흐릿하게 타이핑되다 확정되면 --ink 또렷하게.
  • 자동 스크롤, 위로 스크롤하면 자동스크롤 해제 + "최신으로" 작은 칩.

5.4 회기 단계 표시 (라포 → 탐색 → 개입 → 정리)

LEFT 패널 세로 트랙커 + 상단 바 가로 미니. 현재 단계만 또렷, 나머지는 은은히 (단계 압박 방지).

회기 진행                      ← kicker
  ●  라포 형성          09:12   ← 완료: 채워진 sage 도트 + 소요시간
  │
  ◉  탐색               진행중   ← 현재: 링+채움, accent, 굵게
  │
  ○  개입                       ← 예정: 빈 도트, ink-3
  │
  ○  정리
  • 연결선 1px --hair, 완료 구간만 --accent-bright.
  • 자동 추적 기본, 수동 보정 가능. 백그라운드 평가 AI가 대화로 현재 단계 추정해 이동. 학습자가 직접 "다음 단계로" 가능(자각 촉진). 추정과 인식 어긋나면 회기말 리뷰에서 짚음.
  • 자극 배제: 단계 전환 시 화면 전환·효과음·축하 애니 없음. 도트가 조용히 채워질 뿐(400ms ease).

5.5 실시간 피드백 — "거슬리지 않게" (이 설계의 심장)

3단계 강도 모델을 학습자가 토글로 고른다 (하단 컨트롤 바 segmented control, 기본=은은한 신호):

모드 실시간 표시 대상
몰입(Immersive) 라이브 신호 전혀 없음. 백그라운드 기록만. 모든 피드백 회기말. 숙련·실전 압박 연습
은은한 신호(Ambient) ★기본 우측 패널에 앰비언트 도트 1개만, 색으로 톤만. 텍스트 없음(호버 시) 일반 연습
코칭(Coached) 발화 직후 짧은 텍스트 힌트 페이드인 초보·특정 기법 집중

앰비언트 신호 (기본 모드 핵심)

우측 패널에 단 하나의 부드러운 도트가 직전 발화 평가 톤만 색으로 전한다. 점수·숫자·순위 없음.

라이브 신호               ← kicker
    ●  공감적 반영          ← pos 도트 + 한 단어. 6초 후 페이드.
  최근 흐름  · · ● · ◦ · ●   ← 최근 6개 발화 톤 미니 시퀀스(클릭 가능)
  • 도트 색: --pos-solid(잘함) / --warn-solid(살펴볼 점) / --ink-3(중립). 빨강·점수 없음.
  • 등장: 발화 종료+평가 완료 시 opacity 0→1, 350ms. 6초 후 자동 페이드 — 누적되면 대시보드가 됨.
  • 거슬림 최소화 3원칙: ①한 번에 1개 ②텍스트 기본 숨김(색만) ③시간 제한 페이드. 진동/소리/번쩍임 전무. 주변시로 "느낄" 수준.

코칭 모드 텍스트 힌트

코칭 힌트                 ← kicker
  방금 질문은 '예/아니오'로 닫혀 있었어요.
  내담자가 더 말하도록 열어보면 어떨까요?
  예: "그때 어떤 마음이 드셨는지 들려주세요."
       [ 알겠어요 ]  ← 가볍게 dismiss
  • --accent-tint 배경 틴트 블록(border 없음), 13~14px. 예시 문장 --ink-2 이탤릭. 한 번에 1개, 새 힌트 오면 이전 것 교체(stack 안 함).
  • 우측 레일의 순서는 AI 코치 → 현재 신호 → 연결 상태다. 코치가 장식성 신호나 운영 상태 아래로 밀려 뷰포트 밖에서 잘리면 안 된다.
  • 연결 상태는 음성·AI 응답 두 값만 짧게 표시한다. 화면 모드는 하단 토글이 이미 소유하므로 우측에서 중복하지 않는다.
  • 라이브 신호 영역에는 의미 없는 equalizer/막대 파형을 두지 않는다. 최근 흐름 도트는 보조 정보이며 코치 가시성을 침범하면 먼저 접는다.
  • 위험 신호만 예외적 즉시 표시(모드 무관): 자해·위기 언급을 학습자가 놓치면 모드 무관하게 우측에 차분한(빨강 아닌 --warn-solid) 알림 — "안전 점검: 방금 위기 신호가 있었어요." 교육적으로 놓치면 안 되는 지점이라 항상 노출.

내담자 상태 미터 (우측 상단) — "반응 읽기 연습"의 거울

내담자 상태
감정 톤      불안 ▓▓▓▓░░   ← 가로 게이지, clay 계열, 라벨 텍스트
마음 열림    ▓▓░░░░        ← 라포 진척 대리지표

게이지는 매우 천천히(2s ease) — 실시간 흔들림이 산만하지 않게. 막대 라운드 없는 사각, 4px 높이.

5.6 하단 컨트롤 바

  • 마이크 버튼(주 컨트롤): 56px 원형. 학습자 말하는 중 = --accent 채움 + 호흡. 음소거 = 아웃라인. push-to-talk 또는 토글. 상태 텍스트 한 줄("듣고 있어요" / "마이크 꺼짐").
  • 일시정지: 타이머·평가·녹음 모두 정지. 정지 중 stage 차분한 오버레이.
  • 종료: 오발동 방지 — 숨은 제스처가 아니라 명시적 회기 종료 버튼 + 확인 다이얼로그. 종료가 유일하게 진한 경고색(--crit-solid) 허용 영역.
  • 접근성: 키보드(Space=마이크, P=일시정지), --focus-ring 2px. 음성 상태는 색만이 아니라 텍스트 병기(색각 이상 대응).

5.7 회기 종료 후 리뷰 화면 (진짜 학습이 일어나는 곳)

실시간에선 일부러 참았던 정밀 평가를 여기서 푼다. 구조: 타임라인 + 기법 라벨 + 슈퍼바이저 코멘트 + 개선점. 리뷰도 라이브 세션과 같은 dark 작업면을 유지한다. 저장된 발화가 없는 빈 상태에서도 흰 카드로 빠지지 않고, 근거 대기/평가 대기/워크시트 대기를 어두운 패널로 보여준다.

┌──────────────────────────────────────────────────────────────────────────┐
│  리뷰 · 시나리오:우울 호소 20대/회기1   오디오 다시듣기▷  PDF 내보내기        │
├──────────────────────────────────────────────────────────────────────────┤
│  한 줄 요약 (큰 문장 하나, 24px/600 — 에디토리얼 미니멀의 핵심)              │
│  "라포는 안정적으로 형성됐지만, 탐색 단계에서 닫힌 질문이 반복돼              │
│   내담자의 자기개방이 일찍 멈췄습니다."                                      │
├───────────────────────────────────────┬──────────────────────────────────┤
│  LEFT (62%) 타임라인 + 자막             │  RIGHT (38%) 분석 사이드            │
│  회기 타임라인(가로 막대)               │  ── 기법 사용 분포 ──              │
│  라포▏▏탐색▏▏▏▏▏개입▏▏정리▏            │  반영적 경청 ▓▓▓▓▓▓               │
│  ▲ 마커(코멘트·기법·하이라이트)          │  개방형 질문 ▓▓                    │
│  ─── 스크롤 자막(마커 연동) ───          │  닫힌 질문 ⚠ ▓▓▓▓▓ (살펴볼 점)     │
│  나 14:33 ◆[감정 반영] …                │  ── 잘한 순간 ──                   │
│         └ 슈퍼바이저: "좋은 반영…"       │  ── 다음 회기 개선점(최대 3개) ──   │
└───────────────────────────────────────┴──────────────────────────────────┘
  • 타임라인(가로): 4단계 너비 비례 구간으로 색 농담 구분. 마커 = 기법 라벨·살펴볼 순간·잘한 순간·슈퍼바이저 코멘트(이모지 아님, SVG 글리프/도트). 클릭하면 좌측 자막 점프 + 오디오 그 시점으로.
  • 자막 + 인라인 분석: 학습자 발화마다 기법 라벨 칩([반영적 경청] [개방형 질문] [닫힌 질문]), --accent-tint/--warn-tint 배경, border 없음 11px. 라벨 아래 들여쓰기로 슈퍼바이저 코멘트(AI 자동 + 교수자 직접). AI코멘트 --ink-2, 사람 코멘트 --accent + "교수자" 태그.
  • 분석 사이드: 기법 사용 분포(가로 게이지, 점수 아님 빈도+적절성, 과다·과소만 --warn 라벨). 잘한 것 먼저, 개선점 최대 3개(실행 가능 구체적, 각 항목 타임라인 마커 연결). 다음 회기 개선점은 "다음에 시도할 한 문장" 형태.
  • 톤: 점수·등급·합불 없음. 상담 역량은 성장 곡선이지 시험이 아니다. 추세는 별도 "학습자 성장" 화면에서만, 단일 리뷰엔 절대점수 안 보임. PDF 내보내기(슈퍼바이저 제출), 오디오 다시듣기, 클립 공유.

6. 3역할 대시보드 (학습자 / 교수자 / 관리자)

6.1 4가지 설계 결정 (근거)

결정 근거
레이더차트 금지, small-multiples 라인 채택 레이더는 항목 순서로 모양 왜곡 + 범주선 "증가/감소" 착시. Tufte small-multiples + 공통 축이 정확. 윤찬 "카드덤프 금지"와도 정합.
신뢰·차분 = 단일 accent + 넉넉한 여백 + 위계 의료 UI: blue=신뢰, green=정상범위, red는 진짜 임상 긴급에만 예약. whitespace·typography로 불안 완화.
교수자 화면은 "인지"가 아니라 "개입"까지 교사용 LA 대시보드 대부분이 awareness만 주고 actionable intervention이 없다는 비판 → 첫 화면을 "개입 필요 학생" 액션 큐로.
역할 전환 = 컨텍스트 라벨 + accent 토큰 과한 색·뱃지 남용은 양산형. 좌상단 역할 라벨 + accent 한 토큰 교체로 "지금 누구의 화면인지"만 조용히.

6.2 역할별 accent 오버라이드

body[data-role="learner"]    { --accent:#3E7A6E; --accent-bright:#5F968B; --accent-tint:#EEF4F2; } /* 세이지-틸: 성장 */
body[data-role="instructor"] { --accent:#3A5BA0; --accent-bright:#5478C4; --accent-tint:#EAEFF7; } /* 인디고-블루: 감독 */
body[data-role="admin"]      { --accent:#5B5F6B; --accent-bright:#7D818E; --accent-tint:#EEEFF1; } /* 슬레이트: 운영 */

세 역할 모두 채도를 낮춰 자극 없게. red(--crit-solid)는 어느 역할에서도 장식으로 안 쓴다 — 오직 "지금 개입해야 하는 학생/세션" 단 한 곳.

6.3 공통 앱 셸 (Shell)

같은 골격 공유, 좌측 네비 항목 + 좌상단 컨텍스트 라벨만 차이. 역할 전환 시 화면 리셋이 아니라 메뉴·accent만 바뀜.

  • 톱바 56px background:var(--surface); border-bottom:1px solid var(--hair); (그림자 없음).
  • 좌측 네비는 넓은 화면에서 항목 텍스트를 항상 함께 보이고, 7211024px에서는 168px 레일로 줄여도 라벨을 숨기지 않는다. 모바일에는 역할별 주요 3개 목적지와 전체 메뉴를 고정해 현재 위치와 추가 경로를 모두 찾을 수 있게 한다. 전체 메뉴는 불투명 표면의 native dialog로 열고 Escape·Tab·호출자 포커스 복원을 보장한다. 활성 = 아이콘 color:var(--accent) + 3px 강조바 금지 → 아이콘 배경 var(--accent-tint) border-radius:8px 알약형(네비 알약만 8px 관용).
  • 앱 셸은 뷰포트 높이의 고정 프레임이다. 톱바와 GNB는 화면에 남고, 라우트 콘텐츠를 담는 메인 영역만 독립적으로 세로 스크롤한다. GNB 장식은 네비 자체의 background 레이어로만 합성하며 문서 위에 절대 위치 의사요소로 띄우지 않는다.
  • 역할 컨텍스트 라벨: 톱바 좌측, font-family:var(--font-num); font-size:13px; letter-spacing:0.04em; color:var(--accent); — "학습 대시보드"/"교수 콘솔"/"운영 콘솔". "지금 누구로 보고 있나"의 유일하고 조용한 신호.
  • 모바일 역할 전환은 현재 역할명이 보이는 native select(접근성 이름: 공간 선택)로 제공하며, 조작면과 인접 아이콘 버튼은 각각 최소 44×44px을 유지한다. Ctrl+W·Ctrl+N·Ctrl+T의 브라우저 예약 단축키는 가로채지 않고, 기존 Alt 단축키를 보존하며 Alt+H는 역할 홈으로 이동한다.
  • 권한 표현 원칙: 권한 없으면 DOM에서 제거. disabled 회색처리도 안 함 — 존재를 숨김. 화면이 깨끗해지고 "내가 못 하는 것" 노이즈 제거. 임상 데이터 프라이버시(관리자는 학생 개별 성장곡선·transcript 기본 접근 불가, 메뉴 자체 렌더 안 함).

6.4 학습자 대시보드 (홈 = "당신은 나아지고 있다")

COUNSELING PRACTICE · 4주차                                      ← kicker
수련생님, 지금까지 12회 연습했어요.                              ← h1 28px/700
최근 라포 형성이 눈에 띄게 안정됐습니다.            ← lead, accent .em

┌─────────────────────────────┐  ┌───────────────────────────┐  ← cols 7:5 비대칭
│ 종합 상담 역량               │  │ 다음 연습                  │
│    ╭───────╮                │  │ ▸ 불안 호소 내담자·중급    │
│   │  72   │ +6 ▲           │  │   이전 약점: 침묵 다루기   │
│    ╰───────╯  지난주 대비   │  │   [ 연습 시작 → ]          │
│  (단일 게이지, 둘레 progress)│  │ 추천 이유: 라포는 올랐지만 │
└─────────────────────────────┘  │ 위기개입 정확도 정체       │
                                  └───────────────────────────┘
역량별 추이 (최근 8회)                                          ← kicker
┌────────┐┌────────┐┌────────┐┌────────┐  ← small multiples 4열, 공통 y축 0-100
│라포형성 ││기법사용 ││개입정확도││공감반영 │
│ ╲__  ││ __  ││ ╲__╲  ││  __  │
│ 82 ▲   ││ 68 →   ││ 61 ▼   ││ 75 ▲   │
└────────┘└────────┘└────────┘└────────┘
최근 피드백 모아보기 (테이블, 카드 아님)                          ← kicker
6/24 불안 내담자 │ "침묵 견디지 못하고 성급히 해결책 제시…" — 개입 ▸
6/22 분노 내담자 │ "반영 정확. 다만 감정 명명이 늦음."     — 공감 ▸
  • 종합 게이지(radar 대체): 단일 원형. SVG <circle> 트랙 stroke:var(--neutral-150), fill arc stroke:var(--accent); stroke-linecap:round. 중앙 숫자 48px/700. 변화량 +6 ▲ = --pos-solid, 하락이면 --warn-solid(앰버, 빨강 아님). 아래 한 문장 자연어 요약.
  • 역량별 추이 = small multiples: 4개 동일 크기 미니 라인. 공통 y축 0-100(첫 카드만 0/50/100 옅게 표기). 라인 stroke:var(--ink-2); stroke-width:1.5. 마지막 점만 r:3; fill:var(--accent). 카드 background:var(--surface); border:1px solid var(--hair); border-radius:8px; padding:16px. 상단 강조선·좌측바 금지. 우하단 최신값+추세 화살표(▲--pos, →--ink-3, ▼--warn). 호버 툴팁, 클릭 시 세션 상세.
  • 피드백 모아보기 = 테이블, 카드 아님: 날짜/내담자유형/인용 코멘트/태그/. zebra 없이 행 border-bottom:1px solid --paper-2. 행 hover background:var(--accent-tint). 카드 격자로 흩뿌리지 않고 시간순 한 컬럼 위계.

6.5 교수자 콘솔 (홈 = "누구를 먼저 도와야 하는가")

핵심: awareness가 아니라 triage. 첫 화면 최상단이 "개입 필요 학생" 액션 큐.

상담실습 II · 28명 담당                                         ← kicker
이번 주, 3명에게 개입이 필요합니다.                        ← h1, accent .em

┌──────────────────────────────────────────────────────────────┐  ← 개입 큐(최우선, 풀폭)
│ ● 박서연  개입정확도 3주 연속 하락(61→52→44)  미연습 5일  ▸    │     좌측 dot = --crit-solid
│ ● 이도현  위기상담 시뮬 중도이탈 2회        마지막 6/20  ▸    │
│ ● 최민준  라포 점수 급락, 피드백 미열람 7건             ▸    │
└──────────────────────────────────────────────────────────────┘

학생별 현황               [정렬: 위험도▾] [영역: 전체▾]
학생     세션 라포 기법 개입 공감  추세      마지막  상태
김수련    12  82↗ 68→ 61↘ 75↗  ▁▃▅▆▇   6/24   양호
박서연     8  55↘ 49↘ 44↘ 58↘  ▇▅▃▂▁   6/19   ● 개입
이도현    14  88↗ 79↗ 71→ 84↗  ▅▆▆▇▇   6/23   양호
  • 개입 큐(triage): 풀폭 패널. 각 행 좌측 dot 8px; background:var(--crit-solid)(red의 유일한 정당한 사용처). 사유 = 수치 변화 + 행동 신호(미연습일·미열람·중도이탈)를 자연어로. 알고리즘이 뽑되 교수가 최종 판단하도록 "왜"를 노출.
  • 반 평균 역량 분포 = 가로 막대(레이더 아님): fill var(--accent), 트랙 var(--paper-2). 최저 항목만 우측 ← 취약 color:var(--warn-solid). 나머지 차분한 무채.
  • 학생별 테이블: sparkline(▁▃▅▆▇, 셀 안 7px SVG, 최근 8회 종합점수). 역량 셀 82↗(화살표 색만 시맨틱). 정렬 기본 위험도 순. 상태 "양호"는 --ink-3 무채, "● 개입"만 --crit-solid dot. red를 한 곳에 집중. 행 클릭 → 학생 드릴다운(학습자 화면 + 세션별 utterance-level 평가 타임라인).

6.6 관리자 콘솔 (홈 = "시스템이 건강한가 · 누가 무엇을 했는가")

핵심: 운영 신뢰성 + 감사. 학습 내용엔 개입 안 하고 시스템·사용·교수활동 감사에 집중. 무채 슬레이트로 가장 차분.

  • 정보구조: /admin은 운영 홈으로 고정한다. 사용자 CRUD는 /admin/users, 역할·그룹·권한 정책은 /admin/access, 사용자 문제·불만·장애 접수는 /admin/tickets로 분리한다. 설정은 계속 /settings다.
  • 증거 원칙: 운영 티켓은 app.support_ticket, 헬스 샘플 이력은 raw app.admin_health_event와 daily app.admin_health_daily_rollup에 저장된 실제 행만 표시한다. 티켓 중복 표시는 저장된 fingerprint/parent_ticket_id 기반 힌트와 관리자 수동 연결만 보여주며, 자동 병합이나 자동 수정처럼 보이게 만들지 않는다. 관리자 화면 조회와 synthetic sampler가 샘플을 적재할 수 있지만, "SLA 업타임"처럼 표현하지 않고 "최근 헬스 샘플 정상률/중단 기록"으로 표시한다. 세분 그룹 CRUD처럼 저장소/API가 없는 항목은 빈 상태 또는 정책 초안으로 남기며, 운영 수치처럼 보이는 목업 숫자는 금지한다.
  • 운영 KPI 5: 사용자/강좌/세션주/가동%/API오류. mono 32px. 오류 0 초과 시 해당 KPI만 --warn-solid, 임계 초과 --crit-solid. 정상 땐 전부 무채 — "조용한 게 정상".
  • 세션 추이 = 단일 라인차트(막대 아님). 피크 1점만 라벨.
  • 음성·AI 사용 + 비용: OpenAI 음성 분/평가 토큰/추정 비용/예산 대비 게이지(80% 넘으면 --warn-solid). 운영비 가시화(윤찬 graphify 비용 통제 문화).
  • 교수 활동 감사 테이블: 교수별 피드백 열람률(품질 신호)·시나리오 발행·마지막 활동. 저조 지표만 ← 저조 --warn. "⚠ 점검" = 관리자 리마인드 대상.
  • Audit log: 시간순 한 컬럼. 행위자·행위·대상. 색 없음(감사는 중립). 클릭 시 상세.

6.7 데이터 시각화 하드룰 (전 역할 공통)

상황 채택 금지
한 사람 여러 역량 추이 small multiples 라인(공통 y축) 레이더/스파이더
여러 역량 현재값 비교 가로 막대(공통 0-100), 최저값만 강조 레이더, 전항목 색칠
한 지표 시간 추이 단일 라인(피크/최신 1점만 라벨) 3D·면적 그라데이션
테이블 안 추세 압축 sparkline(7px) + 화살표 셀마다 미니 도넛
종합 한 숫자 단일 원형 게이지 + 변화량 여러 도넛 격자

차트 공통 스타일: 격자선 최소(y축 0/50/100 옅은 점선만, 세로 격자 없음). 라인 stroke-width:1.5, 점은 최신/이상치만. 색은 데이터 의미에만(추세 ↗--pos/↘--warn/→무채, 평상시 라인 --ink-2 무채 → 색 인플레이션 방지). 진입 라인 draw 280ms, 게이지 arc 400ms ease-out 1회만. 깜빡임·펄스·glow 없음. 모든 수치 tabular-nums.


7. 컴포넌트 원칙 (요약 카탈로그)

공통: border-radius 절제(6~12px, 알약 금지), 그림자 절제(헤어라인 우선), border는 --hair. 카드는 쓰되 균등 4-4-4 격자 남용 금지 → 비대칭·표·도식.

7.1 버튼 (위계 3단, 알약형 금지 radius 8px)

종류 배경 텍스트 보더 용도
Primary --accent --text-on-accent none 세션 시작·저장 (화면당 1~2개)
Secondary --bg-surface --accent 1px --accent 보조 액션
Ghost transparent --text-body none 취소·텍스트 액션
Danger --crit-solid #fff none 세션 강제 종료 등 위급만
.btn { font: 600 var(--fs-sm)/1 var(--font-sans); padding: 10px 18px;
  border-radius: var(--radius); border:1px solid transparent;
  transition: background .16s ease, transform .12s ease; cursor:pointer; }
.btn-primary { background: var(--accent); color: var(--text-on-accent); }
.btn-primary:hover { background: var(--accent-deep); }
.btn:active { transform: translateY(.5px); }   /* 미세 누름, 과한 모션 X */
.btn:focus-visible { outline:none; box-shadow: 0 0 0 3px var(--focus-ring); }

7.2 입력 (radius 6px, 포커스 시 보더색 + 얇은 ring, 좌측바 X)

.input { width:100%; background: var(--bg-surface-2); color: var(--text-body);
  border:1px solid var(--border-strong); border-radius: var(--radius-sm);
  padding:10px 12px; font:var(--fs-body)/1.5 var(--font-sans);
  transition:border-color .15s, box-shadow .15s; }
.input:focus { border-color: var(--border-focus); outline:none; box-shadow: 0 0 0 3px var(--focus-ring); }
.input[aria-invalid="true"] { border-color: var(--crit-solid); }

7.3 카드 / 패널 (헤어라인 + 미세 그림자, 상단 강조선 금지)

.card { background: var(--bg-surface); border:1px solid var(--border-subtle);
  border-radius: var(--radius); padding: var(--sp-5); box-shadow: var(--shadow-sm); }
.panel { background: var(--bg-surface); border:1px solid var(--border-subtle);
  border-radius: var(--radius-lg); padding: var(--sp-6); }
.panel-tint { background: var(--bg-tint); border-color: transparent; }  /* 강조 패널: 틴트 배경 */

7.4 평가 피드백 콜아웃 (이 플랫폼 핵심, 좌측 컬러바 금지 → 배경 틴트 + 도트 + kicker)

.callout { border-radius: var(--radius); padding: var(--sp-4) var(--sp-5);
  font-size: var(--fs-sm); line-height:1.6; }
.callout .clh { font: 600 var(--fs-xs)/1.4; letter-spacing:.04em;
  display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.callout .clh::before { content:""; width:7px; height:7px; border-radius:50%; } /* dot, 바 아님 */
.callout.pos  { background:var(--pos-tint);  color:var(--pos-text); }
.callout.pos  .clh::before { background:var(--pos-solid); }
.callout.info { background:var(--info-tint); color:var(--info-text); }
.callout.info .clh::before { background:var(--info-solid); }
.callout.warn { background:var(--warn-tint); color:var(--warn-text); }
.callout.warn .clh::before { background:var(--warn-solid); }
.callout.crit { background:var(--crit-tint); color:var(--crit-text); }  /* 가드레일 위반만 */
.callout.crit .clh::before { background:var(--crit-solid); }

피드백 강도 매핑: 잘함→pos(녹색), 일반 코칭/관찰→info(슬레이트), 페이싱·라포 주의→warn(앰버), 가드레일/위급→crit(적색). 학습자 화면 기본 피드백은 info/pos가 다수가 되도록.

7.5 라이브 음성 오브 (§5.2 참조)

내담자 발화=sage, 학습자 발화=clay로 화자 구분(채도 낮게). 깜빡이는 빨강 금지 → 호흡 펄스.


8. React 구현 노트

8.1 컴포넌트 트리

<AppShell role={role}>              // body[data-role] 설정, 네비·톱바
  <RoleNav items={navByRole}/>      // 권한 없는 항목 필터링 후 렌더(DOM 제거)
  <ContextLabel/>                   // mono accent 라벨
  <Outlet/>
    ├ <LearnerHome>   Hero1줄 + cols(Gauge, NextPractice) + MiniMultiples×4 + FeedbackTable
    ├ <InstructorHome> InterventionQueue + KPIs + ClassDistribution + StudentTable(sparkline)
    ├ <AdminHome>     OpsKPIs + OnlineUsers + ResourceHealth + UsageCost + IntegrationEmptyStates
    ├ <AdminUsers>    UserList + RegisterTab + ActivityTab
    ├ <AdminAccess>   RolePolicy + GroupPolicy + PermissionMatrix
    └ <AdminTickets>  TicketQueueEmpty + CategoryPolicy + ResponseRules

<SessionScreen>
 ├ <SessionTopBar scenario stage elapsed onEnd/>
 ├ <SessionLayout>                  // CSS grid 320/1fr/300, RN은 Flex
 │  ├ <StagePanel> <StageTracker/> <ClientContextCard/>          // LEFT
 │  ├ <ClientStage>                                              // CENTER
 │  │   ├ <ClientAvatar persona state affect analyser/>          // §4 아바타
 │  │   ├ <VoiceOrb state amplitude/>
 │  │   └ <LiveTranscript turns partial/>
 │  └ <FeedbackRail mode>                                        // RIGHT
 │      ├ <ClientStateMeter tone openness/>
 │      ├ <AmbientSignal latest recentSequence/>                 // 은은한 신호
 │      ├ <CoachHint hint onDismiss/>                            // 코칭 모드만
 │      └ <SelfNote/>
 └ <ControlBar mic paused mode onMic onPause onModeChange onEnd/>

<ReviewScreen>
 ├ <ReviewHeader scenario onExportPdf onReplay/>
 ├ <ReviewHeadline summary/>        // 큰 한 문장
 ├ <SessionTimeline phases markers onSeek/>
 ├ <AnnotatedTranscript turns techniqueLabels supervisorComments audioSync/>
 └ <AnalysisSide techniqueDistribution highlights improvements/>

8.2 상태 관리

  • 음성 이벤트(onModeChange/onVolumeChange/partial transcript)는 OpenAI Realtime 스트림 → 단일 SessionStore(Zustand 권장)로 모아 VoiceOrb·LiveTranscript·FeedbackRail·ClientAvatar 구독.
  • 평가 AI는 **별도 채널(백그라운드)**로 발화 단위 신호를 throttle해서 push. FeedbackRail이 6초 페이드 큐로 소비. 평가와 음성 상태 표시는 분리(평가가 음성 UX를 막지 않게).
  • 차트 프리미티브 4종 먼저 구축: <Gauge> <SparkLine> <MiniMultiple> <HBar> (§6.7 룰 내장, props=data+role토큰). 학습자 컴포넌트가 교수 드릴다운에서 재사용됨.

8.3 구현 순서

  1. tokens.css(§3) + 앱 셸(§6.3) — 셸은 3역할 공통이므로 1회만.
  2. 차트 프리미티브 4종.
  3. 학습자 홈 → 교수 홈 → 관리자 홈 순(재사용 극대화).
  4. 세션 화면: 폴백 추상 오브 먼저(음성 파이프라인·4-state 배선 검증) → 반구상 SVG 아바타 → 정서 6파라미터 → 페르소나 JSON.
  5. 리뷰 화면 + utterance-level 평가 타임라인.
  6. 역할 가드: 라우터에서 role 기반 메뉴·라우트 렌더 제외(disable 아님).
  7. (여유) Rive 아바타 고도화. 안 되면 SVG 1차안으로 출시(폴백 안전).

8.4 RN 전환 대비

레이아웃 토큰은 절대 px 의존 최소화(rem·flex 우선). SVG→react-native-svg, Web Audio→react-native-audio-api, Rive→RN 런타임. 브레이크포인트 sm:640/md:768/lg:1024/xl:1280.


9. 안티패턴 체크리스트 (HARD NO — 출시 전 자가검증)

  1. border-left 강조선 / 좌측 사이드바 형태 강조줄 — 피드백·콜아웃·카드·활성표시에 색 막대 금지. 위계는 kicker+weight+여백+dot+배경틴트.
  2. 이모지 — UI·일러스트·SVG 내부 장식까지 전부 금지. 아이콘은 Lucide(stroke 2, 직각). 평가 결과에 체크/엑스 이모지 금지. 추세는 ▲▼→ 기하 화살표.
  3. 카드 덤프 / 균등 그리드 무한반복(4-4-4) — 비대칭(7:5) 레이아웃·데이터 테이블·도식으로. 학습자 홈은 게이지+small-multiples+테이블, 교수 홈은 triage 큐+KPI+테이블.
  4. 양산형 SaaS 랜딩 — "그라데이션 히어로 + 떠다니는 mockup + 3컬럼 feature 카드 + 보라 그라데이션 CTA" 공식 금지.
  5. 과한 그라데이션·glow·gradient-text·큰 blur — 깊이는 1px 헤어라인.
  6. 둥근 모서리 과다(16px+)·말랑 일러스트 — 거의 직각(6~12px). 원형은 오브·아바타·dot만.
  7. 게임화 폭격 — 점수 팡파레, 빨간 X, 레벨업 배지, 별점 5개 즉시. 평가는 서술형·비모달·회고 시점.
  8. 순흑(#000)·순백(#FFF)--ink:#1C2A2A / --paper:#FBFAF8.
  9. 고채도 메디컬 블루 단독 의존 — 세이지-틸로 차별화 + 온기.
  10. 실시간 피드백 모달 — 상담 흐름 중 팝업 금지. 차분한 사이드 패널로.
  11. 레이더/스파이더 차트 — small-multiples 라인 + 단일 게이지로.
  12. 권한 없는 메뉴 disabled 회색 나열 — DOM에서 제거.
  13. 빨강 장식 사용--crit-solid는 (교수)개입 큐·"개입" 상태·(관리자)임계 오류에만.
  14. One screen, one message 위반 — 각 화면 최상단 h1이 그 화면 단일 메시지("나아지고 있다"/"3명 개입 필요"/"정상 운영"/"듣고 있어요").

10. 핵심 의사결정 5줄 (윤찬이 기억할 것)

  1. 컬러: 세이지-틸 #3E7A6E 단일 accent + 테라코타 #B0735C 온기 보조. 의료 블루 회피, 저채도로 임상+따뜻함 동시. 역할별 accent 한 토큰만 교체.
  2. 아바타: 사실적 얼굴(오인·불쾌한 골짜기·편향)도 추상 오브(비언어 연습 불가)도 답 아님 → 사실성 35~45% 양식화 반구상 흉상 + 호흡 광배. 눈·눈썹·입·어깨 4채널 × 정서 6파라미터. SVG 1차 → Rive 2차. 미성년은 realism 더 낮추고 교육용 가상 내담자 라벨 상시.
  3. 세션 화면: 실시간 피드백은 "신호(색 도트, 6초 페이드, 1개)"까지만, 정밀 평가는 회기말 리뷰로. 학습자가 모드(몰입/은은/코칭)를 고른다. 음성 상태는 막대 파형이 아니라 빛의 호흡(sage=학습자, clay=내담자).
  4. 시각적 무게 = 주의 배분. 내담자 stage 60%, 평가 패널 15%·평시 접힘. 화면은 대시보드가 아니라 상담실.
  5. 대시보드: 레이더 금지 → small-multiples 라인 + 단일 게이지. 점수·합불 없음(성장 추세만). 교수자 첫 화면은 triage 큐. 권한 없으면 DOM 제거.

참고 (실조사 출처)

디자인 언어·시스템

  • Linear Brand Guidelines / Stripe Design / Calm·Headspace 색 (accent rationing, 저채도, 호흡 모션)
  • Fuzzy Math — Color Palettes of Mental Healthcare UI / Villa Healing Center — Calming Colors
  • Halo Lab — Digital Healthcare UX Trends 2026 / Progress — Color Psychology in Healthcare
  • Pretendard (orioncactus/pretendard) / az-loc — Best Fonts for CJK Websites 2026
  • Aufait UX — Accessible Color Tokens / WCAG Contrast Guide 2026

아바타

  • Behavioral Sciences 2026 — Human-like/Animal-like/Object-like LLM Virtual Doctor Avatar
  • arXiv 2506.11890 — Graduated Realism (AI Avatars in VR Teacher Training)
  • PMC12692777 — AI Physician Avatars (윤리·편향·오인 위험)
  • NYU Steinhardt — AI Avatar for Social Work Counseling Practice
  • ElevenLabs UI Orb / orb-ui (4-state) / Rive vs Lottie 2026 / arXiv 2502.16038 (Valence-Arousal-Dominance)

세션·대시보드

  • arXiv 2502.18673 — Scaffolding Empathy (utterance-level 피드백 학습효과 vs 인지부하) ← 2단 피드백 모델 근거
  • arXiv 2505.02428 — LLM-Simulated Practice/Feedback for Counselors
  • assistant-ui / Vocalis / Agora (음성 상태 시각화)
  • Scott Logic·Observable — Radar Charts 비판 (small-multiples 대체 근거)
  • GoReact — Counseling Skills Rubric / Springer Open — LA Dashboard actionable intervention 비판
  • Eleken·Fuselab — Healthcare UI/UX 2026

vault 연계 자산

  • Resources/50_Tech_Dev/디자인/slide-base.css (무채 골격·강조 위계 계승)
  • Resources/50_Tech_Dev/디자인/[디자인 시스템] HTML 슬라이드·보고서 베이스 (2026-06).md (한신대/의료 행에 --accent:#3E7A6E 채움)