와와 학원 · 내부 도구 · 디자인 시스템

설명 AI
를 진짜로 만들기 전에
합의해둘 시각 어휘.

이 문서는 mockups/ask-ai/ 의 HTML 목업을 React 컴포넌트로 구현할 때 필요한 토큰·아톰·몰리큘·패턴을 한 페이지에 모은 것이다. 기존 apps/student/src/styles/tokens.css 를 기반으로, AskAI 한정 추가분만 새로 정의한다.

4대상 화면
3신규 색 토큰
1신규 폰트 (손글씨)
~14컴포넌트
0신규 라이브러리 (KaTeX·function-plot 만)

Foundations · 01

컬러 팔레트

기존 wawa-learn 토큰 그대로. 단, AskAI 전용으로 종이톤 3색빨간펜 1색을 추가했다. 새 hue 도입 없이, 의미 채널만 늘림.

잉크 스케일 · 기존

--ink
rgba(17,20,26,.92)
본문 텍스트
--ink-72
opacity 72%
본문 보조
--ink-60
opacity 60%
메타 · 캡션
--ink-40
opacity 40%
placeholder
--ink-09
opacity 9%
hairline 보더
--ink-05
opacity 5%
hover bg

시멘틱 · 기존

--primary
#2d3a8c
앱 강조 · CTA
--success
#3FA129
통과 · 확인
--danger
#E62829
에러 · 경고
--warning
#FAC000
주의 · 보통

타입 컬러 (포켓몬 시스템) · 기존 — 단원/과목 시그니처

--type-grass
#3FA129
증명 · 논리
--type-water
#2980EF
단어 · 언어
--type-electric
#FAC000
수행평가
--type-psychic
#F584A8
문법 · 추상
--type-ground
#915121
시험지
--type-dragon
#5060E1
도전 · 최난

AskAI 신규 토큰 · 종이·노트·빨간펜

--bg-paper
#f7f5ee
학원 단원지 인용 카드
--bg-question
#f1f3f9
학생 질문 박스
--bg-photo
#efece4
노트 사진 종이톤
--pen-red
#d92e2e
AI 빨간펜 — 채도 살짝 죽임

Foundations · 02

타이포그래피

본문은 Pretendard Variable. UI 숫자 정렬은 tabular-nums 강제. AskAI 신규 — 학생 손글씨를 묘사할 때만 Gaegu (Google Fonts).

스케일

--fs-hero 완벽한 풀이 56 / 900 / -0.025em
--fs-title-1 표본평균의 분산 32 / 900 / -0.02em
--fs-title-2 정의 다시 적기 22 / 800 / -0.01em
--fs-body-l 한 줄씩 차근차근 가보자. 18 / 400
--fs-body 매번 표본을 뽑을 때마다 평균이 바뀌므로 표본평균은 확률변수다. 15 / 400
--fs-label 정의 · 성질 · 계산 13 / 600
--fs-caption 단원지 §2.3 p.14 11 / 700 / 0.6px / UC
--font-hand ① AB = AC 이다 (가정) Gaegu — only for handwriting mockup
--font-mono --bg-paper: #f7f5ee; JetBrains Mono · 토큰 코드

Foundations · 03

간격 · 라디우스

4의 배수 (sp-1=4 → sp-10=40). 라디우스는 5단계. AskAI에서 자주 쓰는 라디우스는 r-md (12)r-lg (16).

간격

--sp-1
4px · 인접 간격
--sp-2
8px · 한 글자급
--sp-3
12px · 카드 내부
--sp-4
16px · 기본
--sp-5
20px · 카드 padding
--sp-6
24px · 섹션 내부
--sp-8
32px · 단계 사이
--sp-10
40px · 큰 섹션

라디우스

--r-xs · 4
--r-sm · 8
--r-md · 12
--r-lg · 16
--r-xl · 24

Foundations · 04

섀도우 · 모션

섀도우는 팝오버·모달·사진 카드에만. 일반 카드는 hairline 보더로만. 모션 곡선은 ease-out-quart 단일.

none
기본 — hairline 보더만. 카드 90%는 이거.
--shadow-pop
팝오버·모달·강조 액션 카드.
--shadow-photo
AskAI 신규 — 학생 사진 카드. 종이가 떠 있는 느낌.

모션

--ease:  cubic-bezier(0.25, 1, 0.5, 1) /* 자연 감속 — 유일한 곡선 */
--dur-fast: 150ms /* hover, focus, active state */
--dur-base: 220ms /* enter/exit 기본 */
--dur-slow: 320ms /* 큰 페이지 전환 */

금지: bounce, elastic, easing 다양화. 모션은 transform/opacity 만.

Atoms · 01

Button

5종 변형. 한 화면에 primary 하나만. 학생 화면은 btn-ink가 발신, 강사 화면은 btn-success가 OK 처리.

<Button variant="primary"/>
CTA · 강사 발신.
components/askAI/Button.tsx
<Button variant="ink"/>
학생 발신 · 채팅 send.
<Button variant="ghost"/>
보조 액션 · 거절/되돌리기.
<Button variant="success"/>
강사 큐 — OK 분류.
<Button variant="dangerOutline"/>
파괴적 액션 — 학생에게 경고 트리거.

Atoms · 02

Chip · Tag · Badge

Chip은 필터, ContextChip은 단원, Tag는 학생 슬립 내 과목, Badge는 큐 상태.

<FilterChip/>
강사 큐 필터 — count 옵션.
<FilterChip active/>
활성 상태 — 잉크 채움.
확통 III-1 표본분포
<ContextChip type="grass"/>
단원/과목 컨텍스트 · type별 surface 컬러.
미코멘트 OK 처리됨 코멘트 1 AI 답 틀림
<StatusBadge state="needs|ok|commented|wrong"/>
강사 큐 슬립 · 한 슬립당 1개.

Atoms · 03

Input · Textarea

학생 composer textarea, 강사 코멘트 textarea. 둘 다 같은 바탕(canvas) → focus 시 카드(white)로 부상.

<Textarea/>
기본 — auto-grow 60px ~ 160px.
components/askAI/Textarea.tsx
<Textarea isFocused/>
focus — primary 보더 + 흰 바탕.

Atoms · 04

Avatar · StepNum

Avatar는 학생 이니셜 1자. StepNum은 풀이 워크북 번호 — primary 패턴 시그니처.

<Avatar name="이루다" type="grass"/>
한글 이니셜 1자 (마지막 글자) · type 컬러로 채움.
1
2
3
<StepNum n={1}/>
잉크 사각 + tabular-nums. AskAI 시그니처 모티프.

Atoms · 05

ConfidenceBar

강사 큐 · 슬립에서 AI 응답 확신도를 3-segment 막대로 표시. 색이 곧 등급 신호.

AI 확신도 높음
<Confidence level="high"/>
3/3 success — 학원 자료에서 정확한 인용 가능.
AI 확신도 보통
<Confidence level="medium"/>
2/3 warning — 검토 권장.
AI 확신도 낮음
<Confidence level="low"/>
1/3 danger — 자동으로 needs_teacher = true.

Atoms · 06

PhotoChip

composer dropzone 안의 64×64 썸네일. 우상단 X 제거 버튼 + 하단 파일명 그라데이션.

textbook.jpg
my-proof.jpg
<PhotoChip src="..." onRemove/>
composer dropzone 내부 — 5장 한도.

Molecules · 01

StepBlock

AskAI 대화의 시그니처 단위. 채팅 버블이 아니라 워크북 페이지 한 항목처럼 보이게. left 64px 들여쓰기 + 잉크 step 번호 + 점선 연결자.

1
정의 다시 적기

표본평균은 그냥 평균이 아니라 '확률변수'다

매번 표본을 뽑을 때마다 평균값이 바뀌니까, 표본평균 자체가 변수야: $\bar X = \frac{1}{n}(X_1 + \cdots + X_n)$

<StepBlock n={1} tag="정의" title="..." body={...}/>
슬롯: tag · title · body (텍스트 + KaTeX + InlineCite + Figure + AnnotatedPhoto 가능). 마지막에 CheckpointCard 붙임.
components/askAI/StepBlock.tsx

Molecules · 02

CheckpointCard

단계 끝에 강제 멈춤. 학생이 "응" 하기 전엔 다음 StepBlock이 잠겨있음. 시스템이 보장하는 한 줄씩 학습.

정의 OK?
<CheckpointCard question="..." onYes onNo/>
기본 상태 — 점선 보더 + primary tint.
✓ 정의 OK? 넘어감
<CheckpointCard isPassed/>
통과 후 상태 — 흐려지고 success 색으로.

Molecules · 03

OcrPasteCard

학생이 사진 보냈을 때 AI가 가장 먼저 띄우는 게이트 — "내가 이렇게 읽었어, 맞아?". 잘못된 인식이 풀이 망치는 것 방지.

증명1-4-textbook.jpg 에서 읽은 문제
주어진: $\triangle ABC$ 에서 $\overline{AB} = \overline{AC}$.
증명할 것: $\angle B = \angle C$.
<OcrPasteCard src="textbook" parsed={...} confidence/>
paper bg + 신뢰도 뱃지 + "응 맞아 / 직접 고칠래" 버튼.

Molecules · 04

InlineCite

본문 사이에 들어가는 학원 자료 인용. 종이톤 bg + grass 좌측 보더.

단원지 §2.1 · p.11 "확률변수가 모분포를 따르고 서로 독립일 때, 이를 크기 n인 확률표본이라 한다."
<InlineCite src="..." page={11}>...</InlineCite>
학원 단원지 정의 인용 시.
components/askAI/InlineCite.tsx
학생 메모 · 이루다 "근의 위치·경계값에서 그림 안 그리는 습관." — 이번 풀이에 그래프 보강 권장.
<InlineCite variant="student-meta">
학생 _meta.json 인용 시 — water 색.

Molecules · 05

AnnotatedPhoto

학생 손글씨/사진 위에 SVG 오버레이 (빨간 박스·빗금·주석). 토글 가능 + 범례. AskAI 킬러 모먼트 컴포넌트.

<AnnotatedPhoto src="..." annotations={[...]} />
SVG 오버레이 layer. annotations: [{type:'box'|'strike'|'check'|'note', x,y,w,h,text,color}]. 헤더에 토글 + 범례.
components/askAI/AnnotatedPhoto.tsx

Molecules · 06

DropzoneSlot

composer 사진 첨부 영역. 페이지 어디든 드래그하면 활성화. 첨부된 PhotoChip 들 + "+추가" 빈 칩.

첨부된 사진 · 2 / 5
<DropzoneSlot photos={...} max={5}/>
react-dropzone 기반. drag-over 상태에서 primary 보더 + tint.
components/askAI/DropzoneSlot.tsx

Molecules · 07

SourceButtonRow

사진 입력 4채널 — 파일·카메라·붙여넣기·내노트. 모두 동등한 비중으로.

<SourceButtonRow onPick={...}/>
학생이 어디서 사진을 가져올지 4채널 동시 노출. mobile에선 카메라가 primary.

Molecules · 08

ConversationSlip

강사 큐 좌측 리스트의 한 항목. 종이 슬립 비유 — 4px 타입 컬러 stripe + 학생/시간/과목/미리보기/confidence/badge.

이루다 14:02
증명 확통 III-1 · 표본분포

표본평균의 분산이 왜 σ²/n 인가요? 단원지에 그냥 그렇다고만…

미코멘트
<ConversationSlip data={...} selected onClick/>
type 컬러는 자동 (단원 → type 매핑 테이블). selected 시 우측 잉크 보더 표시.
components/askAI/ConversationSlip.tsx

Molecules · 09

TeacherActionRow

강사 큐 detail 하단의 3-액션 그리드. 키보드 단축키 표기 — 50건 처리 동선 핵심.

<TeacherActionRow onOK onComment onMarkWrong/>
단축키: k=OK · ⌘↵=코멘트 · x=AI틀림 · j=다음 슬립.
components/askAI/TeacherActionRow.tsx

Patterns · 01

대화 스레드 (학생)

3컬럼 grid: 56px sidebar | 1fr conversation | 320px rail. mobile에서 rail 숨김 + sidebar 숨김.

student-chat.html · <AskAIChatPage/>
컨테이너 grid + StepBlock 반복 + 우측 CitationCard 리스트.
apps/student/src/pages/AskAIPage.tsx

Patterns · 02

강사 큐

2컬럼 master-detail: 380px slip list | 1fr detail. 단축키 우선 동선.

teacher-queue.html · <AskAIQueuePage/>
ConversationSlip 리스트 + 우측 detail (질문 + AI 단계 요약 + 인용 + ActionRow).
apps/desktop/src/pages/AskAIQueuePage.tsx

Patterns · 03

사진 업로드 → AI 채점

학생이 사진 보내면 AI가 OCR 게이트(OcrPasteCard) → 진단(AnnotatedPhoto) → 정답 풀이(StepBlock + Figure) 순으로 응답. 채팅 thread는 기본 Pattern 1과 동일.

→ 사진 도착
사진 2장 + "어디가 틀렸는지 봐주세요"
→ Step 1: OCR 게이트
"사진에서 이렇게 읽었어, 맞아?" — 학생 확인 후 다음 단계.
→ Step 2: 빨간펜 채점
학생 손글씨 사진 위에 SVG 오버레이로 어디가 무너졌는지 표시.
→ Step 3: 정답 풀이
보조선/정의/SSS 등 — Figure 포함된 새 풀이 (StepBlock 동일).
student-photo.html · <AskAIPhotoFlow/>
flow는 orchestrator(Worker)가 결정 — 학생은 그냥 사진 보낼 뿐. UI는 도착하는 응답 단계 그대로 렌더.

Implementation · 01

신규 토큰 (CSS)

기존 apps/student/src/styles/tokens.css 끝에 추가. 다른 학생 앱 페이지에 영향 없음.

/* === AskAI 추가 토큰 === */


/* index.html <head> 에 추가 */
<link rel="stylesheet"
  href="https://fonts.googleapis.com/css2?family=Gaegu:wght@400;700&display=swap">

Implementation · 02

파일 매핑 (React)

신규 컴포넌트는 모두 apps/{student|desktop}/src/components/askAI/ 아래. 페이지는 pages/AskAI*.

컴포넌트파일 경로비고
학생 앱 (apps/student)
AskAIPagepages/AskAIPage.tsx/ask 라우트. 채팅 + photo 모두 통합. URL ?session=... 로 기존 대화 복원.
AskAIHistoryPagepages/AskAIHistoryPage.tsx내 질문 목록. ConversationSlip 재활용 (학생 버전 — 강사 액션 없이).
StepBlockcomponents/askAI/StepBlock.tsx단일 단계 + 자식 슬롯 (KaTeX/InlineCite/Figure/AnnotatedPhoto/Checkpoint).
CheckpointCardcomponents/askAI/CheckpointCard.tsx단계 잠금 — onYes로 다음 step state.unlocked = true.
OcrPasteCardcomponents/askAI/OcrPasteCard.tsxOCR 인식 결과 확인 게이트.
AnnotatedPhotocomponents/askAI/AnnotatedPhoto.tsx사진 위 SVG 오버레이. annotations[] prop.
InlineCitecomponents/askAI/InlineCite.tsx학원 자료 인용. variant=unit|student-meta.
Figurecomponents/askAI/Figure.tsxfunction-plot/JSXGraph 라우터. spec.type 분기.
DropzoneSlotcomponents/askAI/DropzoneSlot.tsxreact-dropzone 래퍼.
PhotoChipcomponents/askAI/PhotoChip.tsxDropzoneSlot 자식 — 64×64 thumb + remove.
SourceButtonRowcomponents/askAI/SourceButtonRow.tsx파일·카메라·붙여넣기·노트 4채널.
CitationCardcomponents/askAI/CitationCard.tsx우측 rail 단원지 카드.
KaTeXcomponents/KaTeX.tsx 기존이미 존재. 재사용.
강사 앱 (apps/desktop)
AskAIQueuePagepages/AskAIQueuePage.tsx큐 master-detail. 단축키 j/k/x/⌘↵.
ConversationSlipcomponents/askAI/ConversationSlip.tsx큐 리스트 한 항목.
TeacherActionRowcomponents/askAI/TeacherActionRow.tsx3-액션 그리드 + 단축키.
QuickCommentRowcomponents/askAI/QuickCommentRow.tsx코멘트 템플릿 +버튼들.
백엔드 (workers)
ask-ai/index.tsworkers/ask-ai/index.ts라우터 — POST /ask, GET /history, GET /queue, POST /comment, POST /flag.
orchestrator.tsworkers/ask-ai/orchestrator.tsClaude API 호출 + tool_use 루프 + JSON 스키마 강제.
tools/searchUnit.tsworkers/ask-ai/tools/searchUnit.tsdata/by-curriculum/ 검색 — 단원지 RAG.
tools/studentCtx.tsworkers/ask-ai/tools/studentCtx.tsdata/students/{name}/_meta.json 로드.
tools/verifyAnswer.tsworkers/ask-ai/tools/verifyAnswer.tsSymPy worker 호출 — 기존 /math-verify 재활용.
d1/schema.sqlworkers/ask-ai/d1/schema.sqlquestions / answers / steps / comments / flags 테이블.

Implementation · 03

열린 질문 — 구현 전 결정 필요

목업으로 시각 어휘는 잡혔지만, 실제 구현 들어가기 전에 답이 필요한 것들.

스택

Cloudflare Workers vs Next.js API

workers/ 이미 존재 — Worker 가는 게 자연스러움. 다만 KaTeX 서버사이드는 Workers 메모리 빠듯할 수 있음.

데이터

D1 vs KV 선택

대화 thread = D1 (관계형, 강사 큐 쿼리). 임시 OCR 캐시·rate limit = KV.

LLM

Claude Sonnet 4.6 vs Haiku 4.5

한글 수학 설명 품질이 핵심 → Sonnet. 비용 비싸지면 OCR 게이트만 Haiku로 분기.

스키마

응답 JSON 스키마 확정

steps[]·confidence·needs_teacher·references[] — Claude tool_use 강제. 누락 처리 어떻게.

권한

학생 화이트리스트

현재 ERP의 학생 인증 그대로 사용 가능? 일일 30 한도 어디서 강제 (Worker vs DB)?

사진

이미지 저장 + 자동삭제

R2 업로드 → 7일 후 자동삭제 cron. 강사 큐에서 봐야 하니 강사 코멘트까지 보존 옵션.

검수

코멘트 알림 채널

강사 코멘트 → 학생에게 어떻게? 푸시 X, 다음 로그인 시 in-app 토스트 정도.

AI 그림

function-plot vs JSXGraph 분기 정확화

Claude가 Figure spec 만들 때 어느 라이브러리 쓸지 결정 — system prompt에서 명시할 룰셋 필요.