2025-12-23 07:55:23 +00:00

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 구성:

  1. 문제 표시
  2. 답변 입력 영역 (타입에 따라)
    • 객관식: 라디오 버튼
    • 주관식: 텍스트 입력
  3. 제출 버튼
  4. 결과 표시 (제출 후)
    • 정답/오답 표시
    • 해설 표시

사용자 액션

객관식 플로우:

  1. 문제 읽기
  2. 선택지 중 하나 선택 (Radio button)
  3. "정답 확인" 버튼 클릭
  4. 결과 표시:
    • 정답: "정답입니다!" + 해설
    • 오답: "아쉬워요! 정답은 X번입니다" + 해설
  5. 다음으로 진행 가능

주관식 플로우:

  1. 문제 읽기
  2. 텍스트 입력
  3. "정답 확인" 버튼 클릭
  4. 정답과 비교 (대소문자 무시, 공백 제거 후 비교)
  5. 결과 표시
  6. 다음으로 진행 가능

UI 예시

객관식 (제출 전):

┌─────────────────────────────────┐
│ 📝 퀴즈                          │
│                                 │
│ 다음 중 의성어가 아닌 것은?      │
│                                 │
│ ○ 졸졸                          │
│ ○ 빨갛다                        │
│ ○ 윙윙                          │
│ ○ 톡톡                          │
│                                 │
│        [정답 확인]               │
└─────────────────────────────────┘

객관식 (정답 제출 후):

┌─────────────────────────────────┐
│ 📝 퀴즈                          │
│                                 │
│ 다음 중 의성어가 아닌 것은?      │
│                                 │
│ ○ 졸졸                          │
│ ● 빨갛다 ❌ (선택)               │
│ ○ 윙윙                          │
│ ○ 톡톡                          │
│                                 │
│ ❌ 아쉬워요!                     │
│ 정답은 2번 "빨갛다" 입니다.      │
│                                 │
│ 💡 '빨갛다'는 색깔을 나타내는    │
│    말이에요.                    │
└─────────────────────────────────┘

주관식:

┌─────────────────────────────────┐
│ 📝 퀴즈                          │
│                                 │
│ 비유란 무엇일까요?               │
│                                 │
│ ┌─────────────────────────────┐ │
│ │                             │ │
│ └─────────────────────────────┘ │
│                                 │
│        [정답 확인]               │
└─────────────────────────────────┘

3. Mission (미션)

목적

학생이 직접 찾거나 수행해야 할 체크리스트

데이터 구조

interface MissionBlock {
    description: string;
    items: string[];  // 체크할 항목들
}

렌더링 방법

컴포넌트: MissionRenderer.tsx

UI 구성:

  1. 미션 설명
  2. 체크박스 리스트
  3. 완료 상태 표시

사용자 액션

  1. 미션 설명 읽기
  2. 각 항목 수행 후 체크
  3. 모든 항목 체크 시 자동 완료

중요: 실제로 "수행했는지"는 검증 불가능 → 신뢰 기반 체크

UI 예시

초기 상태:

┌─────────────────────────────────┐
│ 🎯 미션                          │
│                                 │
│ 소리 탐정이 되어보자!            │
│                                 │
│ ☐ 지금 주변에서 들리는           │
│   소리 3가지 찾기                │
│                                 │
│ ☐ 각 소리를 의성어로             │
│   표현해보기                     │
│                                 │
│ 진행률: 0 / 2                    │
└─────────────────────────────────┘

일부 완료:

┌─────────────────────────────────┐
│ 🎯 미션                          │
│                                 │
│ 소리 탐정이 되어보자!            │
│                                 │
│ ☑ 지금 주변에서 들리는           │
│   소리 3가지 찾기                │
│                                 │
│ ☐ 각 소리를 의성어로             │
│   표현해보기                     │
│                                 │
│ 진행률: 1 / 2                    │
└─────────────────────────────────┘

전체 완료:

┌─────────────────────────────────┐
│ 🎯 미션                          │
│                                 │
│ 소리 탐정이 되어보자!            │
│                                 │
│ ☑ 지금 주변에서 들리는           │
│   소리 3가지 찾기                │
│                                 │
│ ☑ 각 소리를 의성어로             │
│   표현해보기                     │
│                                 │
│ ✅ 완료했어요!                   │
└─────────────────────────────────┘

4. WritingPrompt (글쓰기 프롬프트)

목적

레슨 안에서 간단하게 글을 써보는 연습

주의: 본격적인 글쓰기는 /write 페이지의 Topic 사용. WritingPrompt는 배운 내용을 바로 적용해보는 짧은 연습용.

데이터 구조

interface WritingPromptBlock {
    prompt: string;
    guideLines: string[];
    minLength?: number;  // 최소 글자 수
}

렌더링 방법

컴포넌트: WritingPromptRenderer.tsx

UI 구성:

  1. 글쓰기 주제
  2. 가이드라인 목록
  3. 텍스트 에디터 (간단한 Textarea)
  4. 글자 수 카운터
  5. 제출 버튼

사용자 액션

  1. 주제와 가이드라인 읽기
  2. 텍스트 에디터에 글 작성
  3. 최소 글자 수 도달 확인
  4. "제출" 버튼 클릭
  5. 완료 처리

저장 위치:

  • 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: 기본 렌더러

  1. TheoryRenderer (가장 간단)
  2. MissionRenderer
  3. QuizRenderer (주관식만)
  4. WritingPromptRenderer

Phase 2: 고급 기능

  1. QuizRenderer 객관식 지원
  2. 마크다운 렌더링 (react-markdown)
  3. 진행 상태 저장

Phase 3: UX 개선

  1. 애니메이션 (콘텐츠 전환)
  2. 로딩 상태
  3. 에러 처리

디자인 토큰

색상:

  • Theory: blue (파란색)
  • Quiz: purple (보라색)
  • Mission: orange (주황색)
  • WritingPrompt: green (초록색)

아이콘:

  • Theory: HiOutlineDocumentText
  • Quiz: HiOutlineQuestionMarkCircle
  • Mission: HiOutlineFlag
  • WritingPrompt: HiOutlinePencilAlt

참고 사항

접근성

  • 모든 인터랙티브 요소에 키보드 접근 가능
  • 스크린 리더 지원 (aria-label)
  • 명확한 포커스 표시

반응형

  • 모바일 우선 디자인
  • 터치 친화적 버튼 크기 (최소 44x44px)

성능

  • 마크다운 렌더링은 메모이제이션
  • 긴 콘텐츠는 가상화 고려

© 2024 BlueNovaLab. All rights reserved.