14 KiB
14 KiB
레슨 콘텐츠 타입별 UX 정의
이 문서는 레슨(Lesson) 시스템의 4가지 콘텐츠 타입이 어떻게 보이고 어떻게 동작해야 하는지 명확하게 정의합니다.
1. Theory (이론 설명)
목적
개념이나 지식을 가르치는 읽기 전용 콘텐츠
데이터 구조
interface TheoryBlock {
markdown: string;
imageUrl?: string;
}
렌더링 방법
컴포넌트: TheoryRenderer.tsx
UI 구성:
- 마크다운을 HTML로 렌더링 (제목, 굵은 글씨, 목록 등 지원)
- 이미지가 있으면 하단에 표시
- 읽기 전용 (사용자 입력 없음)
사용자 액션:
- 읽기만 함
- 스크롤 가능
- 액션 없음 → 자동으로 "완료" 처리
예시:
## 의성어란?
소리를 흉내 낸 말이에요.
**예시:**
- 강아지: 멍멍, 왈왈
- 비: 주룩주룩, 후두둑
의성어를 사용하면 글을 읽는 사람이 소리를 상상할 수 있어요!
렌더링 결과:
┌─────────────────────────────────┐
│ 의성어란? │
│ │
│ 소리를 흉내 낸 말이에요. │
│ │
│ 예시: │
│ • 강아지: 멍멍, 왈왈 │
│ • 비: 주룩주룩, 후두둑 │
│ │
│ 의성어를 사용하면... │
│ │
│ [이미지가 있으면 여기에 표시] │
└─────────────────────────────────┘
2. Quiz (퀴즈)
목적
이해도를 확인하는 문제 (객관식 또는 주관식)
데이터 구조
interface QuizBlock {
question: string;
type: 'multiple_choice' | 'short_answer';
options?: string[]; // 객관식인 경우
answer: string | number; // 주관식: string, 객관식: 선택지 인덱스 (0부터)
explanation: string;
}
렌더링 방법
컴포넌트: QuizRenderer.tsx
UI 구성:
- 문제 표시
- 답변 입력 영역 (타입에 따라)
- 객관식: 라디오 버튼
- 주관식: 텍스트 입력
- 제출 버튼
- 결과 표시 (제출 후)
- 정답/오답 표시
- 해설 표시
사용자 액션
객관식 플로우:
- 문제 읽기
- 선택지 중 하나 선택 (Radio button)
- "정답 확인" 버튼 클릭
- 결과 표시:
- ✅ 정답: "정답입니다!" + 해설
- ❌ 오답: "아쉬워요! 정답은 X번입니다" + 해설
- 다음으로 진행 가능
주관식 플로우:
- 문제 읽기
- 텍스트 입력
- "정답 확인" 버튼 클릭
- 정답과 비교 (대소문자 무시, 공백 제거 후 비교)
- 결과 표시
- 다음으로 진행 가능
UI 예시
객관식 (제출 전):
┌─────────────────────────────────┐
│ 📝 퀴즈 │
│ │
│ 다음 중 의성어가 아닌 것은? │
│ │
│ ○ 졸졸 │
│ ○ 빨갛다 │
│ ○ 윙윙 │
│ ○ 톡톡 │
│ │
│ [정답 확인] │
└─────────────────────────────────┘
객관식 (정답 제출 후):
┌─────────────────────────────────┐
│ 📝 퀴즈 │
│ │
│ 다음 중 의성어가 아닌 것은? │
│ │
│ ○ 졸졸 │
│ ● 빨갛다 ❌ (선택) │
│ ○ 윙윙 │
│ ○ 톡톡 │
│ │
│ ❌ 아쉬워요! │
│ 정답은 2번 "빨갛다" 입니다. │
│ │
│ 💡 '빨갛다'는 색깔을 나타내는 │
│ 말이에요. │
└─────────────────────────────────┘
주관식:
┌─────────────────────────────────┐
│ 📝 퀴즈 │
│ │
│ 비유란 무엇일까요? │
│ │
│ ┌─────────────────────────────┐ │
│ │ │ │
│ └─────────────────────────────┘ │
│ │
│ [정답 확인] │
└─────────────────────────────────┘
3. Mission (미션)
목적
학생이 직접 찾거나 수행해야 할 체크리스트
데이터 구조
interface MissionBlock {
description: string;
items: string[]; // 체크할 항목들
}
렌더링 방법
컴포넌트: MissionRenderer.tsx
UI 구성:
- 미션 설명
- 체크박스 리스트
- 완료 상태 표시
사용자 액션
- 미션 설명 읽기
- 각 항목 수행 후 체크
- 모든 항목 체크 시 자동 완료
중요: 실제로 "수행했는지"는 검증 불가능 → 신뢰 기반 체크
UI 예시
초기 상태:
┌─────────────────────────────────┐
│ 🎯 미션 │
│ │
│ 소리 탐정이 되어보자! │
│ │
│ ☐ 지금 주변에서 들리는 │
│ 소리 3가지 찾기 │
│ │
│ ☐ 각 소리를 의성어로 │
│ 표현해보기 │
│ │
│ 진행률: 0 / 2 │
└─────────────────────────────────┘
일부 완료:
┌─────────────────────────────────┐
│ 🎯 미션 │
│ │
│ 소리 탐정이 되어보자! │
│ │
│ ☑ 지금 주변에서 들리는 │
│ 소리 3가지 찾기 │
│ │
│ ☐ 각 소리를 의성어로 │
│ 표현해보기 │
│ │
│ 진행률: 1 / 2 │
└─────────────────────────────────┘
전체 완료:
┌─────────────────────────────────┐
│ 🎯 미션 │
│ │
│ 소리 탐정이 되어보자! │
│ │
│ ☑ 지금 주변에서 들리는 │
│ 소리 3가지 찾기 │
│ │
│ ☑ 각 소리를 의성어로 │
│ 표현해보기 │
│ │
│ ✅ 완료했어요! │
└─────────────────────────────────┘
4. WritingPrompt (글쓰기 프롬프트)
목적
레슨 안에서 간단하게 글을 써보는 연습
주의: 본격적인 글쓰기는 /write 페이지의 Topic 사용. WritingPrompt는 배운 내용을 바로 적용해보는 짧은 연습용.
데이터 구조
interface WritingPromptBlock {
prompt: string;
guideLines: string[];
minLength?: number; // 최소 글자 수
}
렌더링 방법
컴포넌트: WritingPromptRenderer.tsx
UI 구성:
- 글쓰기 주제
- 가이드라인 목록
- 텍스트 에디터 (간단한 Textarea)
- 글자 수 카운터
- 제출 버튼
사용자 액션
- 주제와 가이드라인 읽기
- 텍스트 에디터에 글 작성
- 최소 글자 수 도달 확인
- "제출" 버튼 클릭
- 완료 처리
저장 위치:
- LocalStorage 또는 Realtime DB에 임시 저장
- 나중에
/write페이지에서 이어 쓸 수 있도록 연동 가능 (선택)
UI 예시
초기 상태:
┌─────────────────────────────────┐
│ ✍️ 글쓰기 │
│ │
│ 소리가 가득한 아침 │
│ │
│ 가이드라인: │
│ • 오늘 아침에 들은 소리들을 │
│ 떠올려보세요 │
│ • 의성어를 3개 이상 사용해보세요 │
│ │
│ ┌─────────────────────────────┐ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ └─────────────────────────────┘ │
│ │
│ 0 / 100자 (최소 100자) │
│ │
│ [제출] (비활성화) │
└─────────────────────────────────┘
작성 중:
┌─────────────────────────────────┐
│ ✍️ 글쓰기 │
│ │
│ 소리가 가득한 아침 │
│ │
│ 가이드라인: │
│ • 오늘 아침에 들은 소리들을... │
│ • 의성어를 3개 이상... │
│ │
│ ┌─────────────────────────────┐ │
│ │ 아침에 일어나니 새들이 │ │
│ │ 짹짹거리는 소리가 들렸다. │ │
│ │ 부엌에서는 엄마가 후라이팬에 │ │
│ │ 계란을 지글지글 굽고 계셨다. │ │
│ │ │ │
│ └─────────────────────────────┘ │
│ │
│ 78 / 100자 (거의 다 왔어요!) │
│ │
│ [제출] (비활성화) │
└─────────────────────────────────┘
제출 가능:
┌─────────────────────────────────┐
│ ✍️ 글쓰기 │
│ │
│ 소리가 가득한 아침 │
│ │
│ ┌─────────────────────────────┐ │
│ │ 아침에 일어나니 새들이 │ │
│ │ 짹짹거리는 소리가 들렸다... │ │
│ │ (글 내용 계속) │ │
│ └─────────────────────────────┘ │
│ │
│ 125 / 100자 ✅ │
│ │
│ [제출] │
└─────────────────────────────────┘
레슨 전체 플로우
LessonViewer 컴포넌트 구조
<LessonViewer lessonId={lessonId}>
{/* 헤더 */}
<LessonHeader
title="1강. 소리를 글로 표현하기"
progress={currentIndex / totalContents}
/>
{/* 현재 콘텐츠 블록 */}
<ContentRenderer
content={lesson.contents[currentIndex]}
onComplete={() => handleComplete()}
/>
{/* 네비게이션 */}
<LessonNavigation
onNext={() => nextContent()}
onPrevious={() => previousContent()}
canNext={currentContentCompleted}
isLastContent={currentIndex === totalContents - 1}
/>
</LessonViewer>
진행 상태 관리
로컬 상태:
currentIndex: 현재 보고 있는 콘텐츠 인덱스completedBlocks: 완료한 블록들의 Set
서버 저장 (나중에 구현):
- UserLessonProgress 모델
- 레슨 완료 시 경험치 및 스티커 보상
완료 조건
| 타입 | 완료 조건 |
|---|---|
| Theory | 자동 완료 (읽기만) |
| Quiz | 정답 확인 후 |
| Mission | 모든 항목 체크 |
| WritingPrompt | 최소 글자 수 이상 + 제출 |
구현 우선순위
Phase 1: 기본 렌더러
- TheoryRenderer (가장 간단)
- MissionRenderer
- QuizRenderer (주관식만)
- WritingPromptRenderer
Phase 2: 고급 기능
- QuizRenderer 객관식 지원
- 마크다운 렌더링 (react-markdown)
- 진행 상태 저장
Phase 3: UX 개선
- 애니메이션 (콘텐츠 전환)
- 로딩 상태
- 에러 처리
디자인 토큰
색상:
- Theory:
blue(파란색) - Quiz:
purple(보라색) - Mission:
orange(주황색) - WritingPrompt:
green(초록색)
아이콘:
- Theory:
HiOutlineDocumentText - Quiz:
HiOutlineQuestionMarkCircle - Mission:
HiOutlineFlag - WritingPrompt:
HiOutlinePencilAlt
참고 사항
접근성
- 모든 인터랙티브 요소에 키보드 접근 가능
- 스크린 리더 지원 (aria-label)
- 명확한 포커스 표시
반응형
- 모바일 우선 디자인
- 터치 친화적 버튼 크기 (최소 44x44px)
성능
- 마크다운 렌더링은 메모이제이션
- 긴 콘텐츠는 가상화 고려
© 2024 BlueNovaLab. All rights reserved.